22
33#include < libpq-fe.h>
44
5+ #include " duckdb/common/unique_ptr.hpp"
56#include " duckdb/main/extension_util.hpp"
67#include " duckdb/common/shared_ptr.hpp"
78#include " duckdb/common/helper.hpp"
1011#include " postgres_scanner.hpp"
1112#include " postgres_result.hpp"
1213#include " postgres_binary_reader.hpp"
14+ #include " postgres_text_reader.hpp"
1315#include " storage/postgres_catalog.hpp"
1416#include " storage/postgres_transaction.hpp"
1517#include " storage/postgres_table_set.hpp"
@@ -34,6 +36,10 @@ struct PostgresLocalState : public LocalTableFunctionState {
3436
3537 void ScanChunk (ClientContext &context, const PostgresBindData &bind_data, PostgresGlobalState &gstate,
3638 DataChunk &output);
39+ void ScanChunkWithBinaryReader (ClientContext &context, const PostgresBindData &bind_data, PostgresGlobalState &gstate,
40+ DataChunk &output);
41+ void ScanChunkWithTextReader (ClientContext &context, const PostgresBindData &bind_data, PostgresGlobalState &gstate,
42+ DataChunk &output);
3743};
3844
3945struct PostgresGlobalState : public GlobalTableFunctionState {
@@ -248,6 +254,18 @@ static void PostgresInitInternal(ClientContext &context, const PostgresBindData
248254 filter += " AND " ;
249255 }
250256 filter += filter_string;
257+ };
258+ lstate.exec = false ;
259+ lstate.done = false ;
260+ Value use_legacy_text_protocol;
261+ if (context.TryGetCurrentSetting (" pg_use_legacy_text_protocol" , use_legacy_text_protocol)) {
262+ if (BooleanValue::Get (use_legacy_text_protocol)) {
263+ lstate.sql = StringUtil::Format (
264+ R"( SELECT %s FROM %s.%s %s%s;)" ,
265+ col_names, KeywordHelper::WriteQuoted (bind_data->schema_name , ' "' ),
266+ KeywordHelper::WriteQuoted (bind_data->table_name , ' "' ), filter, bind_data->limit );
267+ return ;
268+ }
251269 }
252270 if (bind_data->table_name .empty ()) {
253271 D_ASSERT (!bind_data->sql .empty ());
@@ -261,8 +279,7 @@ static void PostgresInitInternal(ClientContext &context, const PostgresBindData
261279 col_names, KeywordHelper::WriteQuoted (bind_data->schema_name , ' "' ),
262280 KeywordHelper::WriteQuoted (bind_data->table_name , ' "' ), filter, bind_data->limit );
263281 }
264- lstate.exec = false ;
265- lstate.done = false ;
282+
266283}
267284
268285static idx_t PostgresMaxThreads (ClientContext &context, const FunctionData *bind_data_p) {
@@ -417,7 +434,7 @@ static unique_ptr<LocalTableFunctionState> PostgresInitLocalState(ExecutionConte
417434 return GetLocalState (context.client , input, gstate);
418435}
419436
420- void PostgresLocalState::ScanChunk (ClientContext &context, const PostgresBindData &bind_data,
437+ void PostgresLocalState::ScanChunkWithBinaryReader (ClientContext &context, const PostgresBindData &bind_data,
421438 PostgresGlobalState &gstate, DataChunk &output) {
422439 idx_t output_offset = 0 ;
423440 PostgresBinaryReader reader (connection);
@@ -472,6 +489,41 @@ void PostgresLocalState::ScanChunk(ClientContext &context, const PostgresBindDat
472489 }
473490}
474491
492+ void PostgresLocalState::ScanChunkWithTextReader (ClientContext &context, const PostgresBindData &bind_data,
493+ PostgresGlobalState &gstate, DataChunk &output) {
494+ PostgresTextReader reader (connection);
495+ if (done && !PostgresParallelStateNext (context, &bind_data, *this , gstate)) {
496+ return ;
497+ }
498+
499+ if (!exec) {
500+ reader.ReadTextFrom (sql);
501+ exec = true ;
502+ }
503+
504+ output.SetCardinality (reader.RowCount ());
505+ for (idx_t output_idx = 0 ; output_idx < output.ColumnCount (); output_idx++) {
506+ auto col_idx = column_ids[output_idx];
507+ auto &out_vec = output.data [output_idx];
508+ reader.LoadResultTo (col_idx, out_vec);
509+ }
510+ reader.Reset ();
511+ done = true ;
512+ return ;
513+ }
514+
515+ void PostgresLocalState::ScanChunk (ClientContext &context, const PostgresBindData &bind_data,
516+ PostgresGlobalState &gstate, DataChunk &output) {
517+ Value use_legacy_text_protocol;
518+ if (context.TryGetCurrentSetting (" pg_use_legacy_text_protocol" , use_legacy_text_protocol)) {
519+ if (BooleanValue::Get (use_legacy_text_protocol)) {
520+ ScanChunkWithTextReader (context, bind_data, gstate, output);
521+ return ;
522+ }
523+ }
524+ ScanChunkWithBinaryReader (context, bind_data, gstate, output);
525+ }
526+
475527static void PostgresScan (ClientContext &context, TableFunctionInput &data, DataChunk &output) {
476528 auto &bind_data = data.bind_data ->Cast <PostgresBindData>();
477529 auto &gstate = data.global_state ->Cast <PostgresGlobalState>();
0 commit comments