diff --git a/.github/workflows/IntegrationTests.yml b/.github/workflows/IntegrationTests.yml index 7159e7e40..be30e9b71 100644 --- a/.github/workflows/IntegrationTests.yml +++ b/.github/workflows/IntegrationTests.yml @@ -118,7 +118,7 @@ jobs: run: | source ./create-postgres-tables.sh psql -d postgresscanner -c "SELECT 42" - make test + ./build/release/test/unittest 'test/sql/*' linux-pgbouncer: name: Linux PgBouncer @@ -228,7 +228,7 @@ jobs: LOCAL_EXTENSION_REPO: 'build/release/repository' run: | psql -d postgresscanner -c "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()" - make test + ./build/release/test/unittest 'test/sql/*' - name: Run tests directly env: @@ -242,7 +242,7 @@ jobs: LOCAL_EXTENSION_REPO: 'build/release/repository' run: | psql -d postgresscanner -c "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()" - make test + ./build/release/test/unittest 'test/sql/*' - name: Upload log if: always() @@ -283,7 +283,9 @@ jobs: sudo apt-get install -y -q -o=Dpkg::Use-Pty=0 \ build-essential \ ccache \ - cmake + cmake \ + mold \ + ninja-build - name: Cache Key id: cache_key @@ -341,7 +343,7 @@ jobs: run: | source ./create-postgres-tables.sh psql -d postgresscanner -c "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()" - make test + ./build/relassert/test/unittest 'test/sql/*' windows-tests: name: Windows Tests @@ -466,4 +468,4 @@ jobs: shell: bash run: | psql -d postgresscanner -c "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()" - make test + ./build/release/test/unittest 'test/sql/*' diff --git a/.github/workflows/MainDistributionPipeline.yml b/.github/workflows/MainDistributionPipeline.yml index 8743340dc..560257565 100644 --- a/.github/workflows/MainDistributionPipeline.yml +++ b/.github/workflows/MainDistributionPipeline.yml @@ -12,10 +12,10 @@ concurrency: jobs: duckdb-stable-build: name: Build extension binaries - uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.5-variegata + uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@main with: - duckdb_version: v1.5.3 - ci_tools_version: v1.5-variegata + duckdb_version: main + ci_tools_version: main extension_name: postgres_scanner exclude_archs: 'wasm_mvp;wasm_eh;wasm_threads;windows_amd64_mingw' opt_in_archs: 'linux_amd64_musl;linux_arm64_musl;windows_amd64_arm' @@ -24,11 +24,11 @@ jobs: duckdb-stable-deploy: name: Deploy extension binaries needs: duckdb-stable-build - uses: duckdb/extension-ci-tools/.github/workflows/_extension_deploy.yml@v1.5-variegata + uses: duckdb/extension-ci-tools/.github/workflows/_extension_deploy.yml@main secrets: inherit with: - duckdb_version: v1.5.3 - ci_tools_version: v1.5-variegata + duckdb_version: main + ci_tools_version: main extension_name: postgres_scanner exclude_archs: 'wasm_mvp;wasm_eh;wasm_threads;windows_amd64_mingw' opt_in_archs: 'linux_amd64_musl;linux_arm64_musl;windows_amd64_arm' diff --git a/duckdb b/duckdb index 14eca11bd..be587a70e 160000 --- a/duckdb +++ b/duckdb @@ -1 +1 @@ -Subproject commit 14eca11bd9d4a0de2ea0f078be588a9c1c5b279c +Subproject commit be587a70ee5eae815e333ca121d39b6905f34535 diff --git a/extension-ci-tools b/extension-ci-tools index 4b3b37b0c..69338b624 160000 --- a/extension-ci-tools +++ b/extension-ci-tools @@ -1 +1 @@ -Subproject commit 4b3b37b0c9de00da54e1765d65abfea3f94617f4 +Subproject commit 69338b62443a27122b44a4898e044e3f2dd9a621 diff --git a/scripts/time_tests.py b/scripts/time_tests.py index b8b586281..08daa2241 100755 --- a/scripts/time_tests.py +++ b/scripts/time_tests.py @@ -51,10 +51,6 @@ def run_and_time_unit_tests(): env_vars['LOCAL_EXTENSION_REPO'] = extension_repo_path test_files = sorted(test_files) - for test_file_full_path in test_files: - print(test_file_full_path) - - sys.exit(1) for test_file_full_path in test_files: # Get the path relative to the project root, as required by the unittest executable diff --git a/src/include/postgres_binary_writer.hpp b/src/include/postgres_binary_writer.hpp index fef2fafe0..cff8e8cb3 100644 --- a/src/include/postgres_binary_writer.hpp +++ b/src/include/postgres_binary_writer.hpp @@ -11,6 +11,9 @@ #include "duckdb.hpp" #include "duckdb/common/types/interval.hpp" #include "duckdb/common/serializer/memory_stream.hpp" +#include "duckdb/common/vector/list_vector.hpp" +#include "duckdb/common/vector/map_vector.hpp" +#include "duckdb/common/vector/struct_vector.hpp" #include "postgres_conversion.hpp" namespace duckdb { @@ -427,9 +430,9 @@ class PostgresBinaryWriter { WriteRawInteger(0); // data size (nop for now) WriteRawInteger(child_entries.size()); // column count for (auto &child : child_entries) { - auto value_oid = PostgresUtils::ToPostgresOid(child->GetType()); + auto value_oid = PostgresUtils::ToPostgresOid(child.GetType()); WriteRawInteger(value_oid); // value oid - WriteValue(*child, r); + WriteValue(child, r); } auto end_position = stream.GetPosition(); // after writing all list elements update the field size diff --git a/src/include/postgres_filter_pushdown.hpp b/src/include/postgres_filter_pushdown.hpp index d3dc0b629..f6407f330 100644 --- a/src/include/postgres_filter_pushdown.hpp +++ b/src/include/postgres_filter_pushdown.hpp @@ -8,9 +8,8 @@ #pragma once -#include "duckdb/planner/table_filter.hpp" -#include "duckdb/planner/filter/conjunction_filter.hpp" -#include "duckdb/planner/filter/constant_filter.hpp" +#include "duckdb/planner/table_filter_set.hpp" +#include "duckdb/planner/filter/expression_filter.hpp" namespace duckdb { @@ -21,10 +20,13 @@ class PostgresFilterPushdown { private: static string TransformCTIDLiteral(const Value &val); - static string TransformConstantFilter(string &column_name, ConstantFilter &filter, column_t column_id); - static string TransformFilter(string &column_name, TableFilter &filter, column_t column_id); + static string TransformConstantFilter(const string &column_name, ExpressionType comparison_type, + const Value &constant, column_t column_id); + static string TransformFilter(const string &column_name, const TableFilter &filter, column_t column_id); + static string TransformExpression(const string &column_name, const Expression &expr, column_t column_id); + static string TransformExpressionSubject(const string &column_name, const Expression &expr); static string TransformComparison(ExpressionType type); - static string CreateExpression(string &column_name, vector> &filters, string op, + static string CreateExpression(const string &column_name, const vector> &filters, string op, column_t column_id); }; diff --git a/src/include/storage/postgres_catalog.hpp b/src/include/storage/postgres_catalog.hpp index 19c3af2b5..9161e46fd 100644 --- a/src/include/storage/postgres_catalog.hpp +++ b/src/include/storage/postgres_catalog.hpp @@ -81,6 +81,12 @@ class PostgresCatalog : public Catalog { bool InMemory() override; string GetDBPath() override; + bool Supports(RemoteCapability capability) const override { + return capability == RemoteCapability::IS_REMOTE || capability == RemoteCapability::CONNECT; + } + unique_ptr RemoteExecute(ClientContext &context, const string &sql) override; + string GetConnectDisplay() override; + PostgresConnectionPool &GetConnectionPool() { return *connection_pool; } diff --git a/src/postgres_binary_parser.cpp b/src/postgres_binary_parser.cpp index 96d5bc672..900a2905c 100644 --- a/src/postgres_binary_parser.cpp +++ b/src/postgres_binary_parser.cpp @@ -1,6 +1,10 @@ #include "postgres_binary_parser.hpp" #include "duckdb/common/types/geometry.hpp" +#include "duckdb/common/vector/flat_vector.hpp" +#include "duckdb/common/vector/list_vector.hpp" +#include "duckdb/common/vector/struct_vector.hpp" + namespace duckdb { PostgresBinaryParser::PostgresBinaryParser(vector types_p, vector postgres_types_p) @@ -41,7 +45,7 @@ bool PostgresBinaryParser::ReadChunk(DataChunk &output, const vector & ReadValue(types[col_idx], postgres_types[col_idx], out_vec, output_offset); } } - output.SetCardinality(output_offset + 1); + output.SetChildCardinality(output_offset + 1); } return true; } @@ -104,13 +108,13 @@ void PostgresBinaryParser::ReadGeometry(const LogicalType &type, const PostgresT default: throw InternalException("Unsupported type for ReadGeometry"); } - auto list_entries = FlatVector::GetData(out_vec); + auto list_entries = FlatVector::GetDataMutable(out_vec); auto child_offset = ListVector::GetListSize(out_vec); ListVector::Reserve(out_vec, child_offset + element_count); list_entries[output_offset].offset = child_offset; list_entries[output_offset].length = element_count; - auto &child_vector = ListVector::GetEntry(out_vec); - auto child_data = FlatVector::GetData(child_vector); + auto &child_vector = ListVector::GetChildMutable(out_vec); + auto child_data = FlatVector::GetDataMutable(child_vector); for (idx_t i = 0; i < element_count; i++) { child_data[child_offset + i] = ReadDouble(); } @@ -120,7 +124,7 @@ void PostgresBinaryParser::ReadGeometry(const LogicalType &type, const PostgresT void PostgresBinaryParser::ReadArray(const LogicalType &type, const PostgresType &postgres_type, Vector &out_vec, idx_t output_offset, uint32_t current_count, uint32_t dimensions[], uint32_t ndim) { - auto list_entries = FlatVector::GetData(out_vec); + auto list_entries = FlatVector::GetDataMutable(out_vec); auto child_offset = ListVector::GetListSize(out_vec); auto child_dimension = dimensions[0]; auto child_count = current_count * child_dimension; @@ -132,7 +136,7 @@ void PostgresBinaryParser::ReadArray(const LogicalType &type, const PostgresType current_offset += child_dimension; } ListVector::Reserve(out_vec, child_offset + child_count); - auto &child_vec = ListVector::GetEntry(out_vec); + auto &child_vec = ListVector::GetChildMutable(out_vec); auto &child_type = ListType::GetChildType(type); auto &child_pg_type = postgres_type.children[0]; if (ndim > 1) { @@ -155,38 +159,38 @@ void PostgresBinaryParser::ReadValue(const LogicalType &type, const PostgresType switch (type.id()) { case LogicalTypeId::SMALLINT: D_ASSERT(value_len == sizeof(int16_t)); - FlatVector::GetData(out_vec)[output_offset] = ReadInteger(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadInteger(); break; case LogicalTypeId::INTEGER: D_ASSERT(value_len == sizeof(int32_t)); - FlatVector::GetData(out_vec)[output_offset] = ReadInteger(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadInteger(); break; case LogicalTypeId::UINTEGER: D_ASSERT(value_len == sizeof(uint32_t)); - FlatVector::GetData(out_vec)[output_offset] = ReadInteger(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadInteger(); break; case LogicalTypeId::BIGINT: if (postgres_type.info == PostgresTypeAnnotation::CTID) { D_ASSERT(value_len == 6); int64_t page_index = ReadInteger(); int64_t row_in_page = ReadInteger(); - FlatVector::GetData(out_vec)[output_offset] = (page_index << 16LL) + row_in_page; + FlatVector::GetDataMutable(out_vec)[output_offset] = (page_index << 16LL) + row_in_page; return; } D_ASSERT(value_len == sizeof(int64_t)); - FlatVector::GetData(out_vec)[output_offset] = ReadInteger(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadInteger(); break; case LogicalTypeId::FLOAT: D_ASSERT(value_len == sizeof(float)); - FlatVector::GetData(out_vec)[output_offset] = ReadFloat(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadFloat(); break; case LogicalTypeId::DOUBLE: { if (postgres_type.info == PostgresTypeAnnotation::NUMERIC_AS_DOUBLE) { - FlatVector::GetData(out_vec)[output_offset] = ReadDecimal(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadDecimal(); break; } D_ASSERT(value_len == sizeof(double)); - FlatVector::GetData(out_vec)[output_offset] = ReadDouble(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadDouble(); break; } @@ -205,22 +209,24 @@ void PostgresBinaryParser::ReadValue(const LogicalType &type, const PostgresType value_len--; } } - FlatVector::GetData(out_vec)[output_offset] = StringVector::AddStringOrBlob(out_vec, str, value_len); + FlatVector::GetDataMutable(out_vec)[output_offset] = + StringVector::AddStringOrBlob(out_vec, str, value_len); break; } case LogicalTypeId::GEOMETRY: { const auto str = ReadString(value_len); string_t res_val; - if (!Geometry::FromBinary(string_t(str, value_len), res_val, out_vec, true)) { + auto &string_heap = StringVector::GetStringHeap(out_vec); + if (!Geometry::FromBinary(string_t(str, value_len), res_val, string_heap, true)) { throw InvalidInputException("Failed to parse Postgres geometry data"); } - FlatVector::GetData(out_vec)[output_offset] = res_val; + FlatVector::GetDataMutable(out_vec)[output_offset] = res_val; break; } case LogicalTypeId::BOOLEAN: D_ASSERT(value_len == sizeof(bool)); - FlatVector::GetData(out_vec)[output_offset] = ReadBoolean(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadBoolean(); break; case LogicalTypeId::DECIMAL: { if (value_len < sizeof(uint16_t) * 4) { @@ -228,16 +234,17 @@ void PostgresBinaryParser::ReadValue(const LogicalType &type, const PostgresType } switch (type.InternalType()) { case PhysicalType::INT16: - FlatVector::GetData(out_vec)[output_offset] = ReadDecimal(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadDecimal(); break; case PhysicalType::INT32: - FlatVector::GetData(out_vec)[output_offset] = ReadDecimal(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadDecimal(); break; case PhysicalType::INT64: - FlatVector::GetData(out_vec)[output_offset] = ReadDecimal(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadDecimal(); break; case PhysicalType::INT128: - FlatVector::GetData(out_vec)[output_offset] = ReadDecimal(); + FlatVector::GetDataMutable(out_vec)[output_offset] = + ReadDecimal(); break; default: throw InvalidInputException("Unsupported decimal storage type"); @@ -247,24 +254,24 @@ void PostgresBinaryParser::ReadValue(const LogicalType &type, const PostgresType case LogicalTypeId::DATE: { D_ASSERT(value_len == sizeof(int32_t)); - auto out_ptr = FlatVector::GetData(out_vec); + auto out_ptr = FlatVector::GetDataMutable(out_vec); out_ptr[output_offset] = ReadDate(); break; } case LogicalTypeId::TIME: { D_ASSERT(value_len == sizeof(int64_t)); - FlatVector::GetData(out_vec)[output_offset] = ReadTime(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadTime(); break; } case LogicalTypeId::TIME_TZ: { D_ASSERT(value_len == sizeof(int64_t) + sizeof(int32_t)); - FlatVector::GetData(out_vec)[output_offset] = ReadTimeTZ(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadTimeTZ(); break; } case LogicalTypeId::TIMESTAMP_TZ: case LogicalTypeId::TIMESTAMP: { D_ASSERT(value_len == sizeof(int64_t)); - FlatVector::GetData(out_vec)[output_offset] = ReadTimestamp(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadTimestamp(); break; } case LogicalTypeId::ENUM: { @@ -275,14 +282,14 @@ void PostgresBinaryParser::ReadValue(const LogicalType &type, const PostgresType } switch (type.InternalType()) { case PhysicalType::UINT8: - FlatVector::GetData(out_vec)[output_offset] = (uint8_t)offset; + FlatVector::GetDataMutable(out_vec)[output_offset] = (uint8_t)offset; break; case PhysicalType::UINT16: - FlatVector::GetData(out_vec)[output_offset] = (uint16_t)offset; + FlatVector::GetDataMutable(out_vec)[output_offset] = (uint16_t)offset; break; case PhysicalType::UINT32: - FlatVector::GetData(out_vec)[output_offset] = (uint32_t)offset; + FlatVector::GetDataMutable(out_vec)[output_offset] = (uint32_t)offset; break; default: @@ -293,16 +300,16 @@ void PostgresBinaryParser::ReadValue(const LogicalType &type, const PostgresType break; } case LogicalTypeId::INTERVAL: { - FlatVector::GetData(out_vec)[output_offset] = ReadInterval(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadInterval(); break; } case LogicalTypeId::UUID: { D_ASSERT(value_len == 2 * sizeof(int64_t)); - FlatVector::GetData(out_vec)[output_offset] = ReadUUID(); + FlatVector::GetDataMutable(out_vec)[output_offset] = ReadUUID(); break; } case LogicalTypeId::LIST: { - auto &list_entry = FlatVector::GetData(out_vec)[output_offset]; + auto &list_entry = FlatVector::GetDataMutable(out_vec)[output_offset]; auto child_offset = ListVector::GetListSize(out_vec); if (value_len < 1) { @@ -357,8 +364,8 @@ void PostgresBinaryParser::ReadValue(const LogicalType &type, const PostgresType auto &child_entries = StructVector::GetEntries(out_vec); if (postgres_type.info == PostgresTypeAnnotation::GEOM_POINT) { D_ASSERT(value_len == sizeof(double) * 2); - FlatVector::GetData(*child_entries[0])[output_offset] = ReadDouble(); - FlatVector::GetData(*child_entries[1])[output_offset] = ReadDouble(); + FlatVector::GetDataMutable(child_entries[0])[output_offset] = ReadDouble(); + FlatVector::GetDataMutable(child_entries[1])[output_offset] = ReadDouble(); break; } auto entry_count = ReadInteger(); @@ -367,7 +374,7 @@ void PostgresBinaryParser::ReadValue(const LogicalType &type, const PostgresType entry_count); } for (idx_t c = 0; c < entry_count; c++) { - auto &child = *child_entries[c]; + auto &child = child_entries[c]; auto value_oid = ReadInteger(); ReadValue(child.GetType(), postgres_type.children[c], child, output_offset); } diff --git a/src/postgres_binary_reader.cpp b/src/postgres_binary_reader.cpp index 79ee46998..c41e5fe3d 100644 --- a/src/postgres_binary_reader.cpp +++ b/src/postgres_binary_reader.cpp @@ -1,3 +1,7 @@ +#include "duckdb/common/vector/list_vector.hpp" +#include "duckdb/common/vector/map_vector.hpp" +#include "duckdb/common/vector/string_vector.hpp" +#include "duckdb/common/vector/struct_vector.hpp" #include "postgres_binary_reader.hpp" #include "postgres_scanner.hpp" diff --git a/src/postgres_copy_to.cpp b/src/postgres_copy_to.cpp index 72580a358..501324600 100644 --- a/src/postgres_copy_to.cpp +++ b/src/postgres_copy_to.cpp @@ -1,3 +1,6 @@ +#include "duckdb/common/vector/list_vector.hpp" +#include "duckdb/common/vector/map_vector.hpp" +#include "duckdb/common/vector/struct_vector.hpp" #include "postgres_connection.hpp" #include "postgres_binary_writer.hpp" #include "postgres_text_writer.hpp" @@ -176,9 +179,9 @@ void CastListToPostgresArray(ClientContext &context, Vector &input, Vector &varc CastToPostgresVarchar(context, child_data, child_varchar, child_count); // construct the list entries - auto child_entries = FlatVector::GetData(child_varchar); - auto list_entries = FlatVector::GetData(input); - auto result_entries = FlatVector::GetData(varchar_vector); + auto child_entries = FlatVector::GetDataMutable(child_varchar); + auto list_entries = FlatVector::GetDataMutable(input); + auto result_entries = FlatVector::GetDataMutable(varchar_vector); for (idx_t r = 0; r < size; r++) { if (FlatVector::IsNull(input, r)) { FlatVector::SetNull(varchar_vector, r, true); @@ -214,12 +217,12 @@ void CastStructToPostgres(ClientContext &context, Vector &input, Vector &varchar vector child_varchar_vectors; for (idx_t c = 0; c < child_vectors.size(); c++) { Vector child_varchar(LogicalType::VARCHAR, size); - CastToPostgresVarchar(context, *child_vectors[c], child_varchar, size); + CastToPostgresVarchar(context, child_vectors[c], child_varchar, size); child_varchar_vectors.push_back(std::move(child_varchar)); } // construct the struct entries - auto result_entries = FlatVector::GetData(varchar_vector); + auto result_entries = FlatVector::GetDataMutable(varchar_vector); for (idx_t r = 0; r < size; r++) { if (FlatVector::IsNull(input, r)) { FlatVector::SetNull(varchar_vector, r, true); @@ -234,7 +237,7 @@ void CastStructToPostgres(ClientContext &context, Vector &input, Vector &varchar if (FlatVector::IsNull(child_varchar_vectors[c], r)) { result += ""; // Struct literals encode null by omitting the value } else { - auto child = FlatVector::GetData(child_varchar_vectors[c])[r]; + auto child = FlatVector::GetDataMutable(child_varchar_vectors[c])[r]; QuoteAndEscapeIfNeeded(child.GetString(), result, child.GetSize()); } } @@ -244,8 +247,8 @@ void CastStructToPostgres(ClientContext &context, Vector &input, Vector &varchar } void CastBlobToPostgres(ClientContext &context, Vector &input, Vector &result, idx_t size) { - auto input_data = FlatVector::GetData(input); - auto result_data = FlatVector::GetData(result); + auto input_data = FlatVector::GetDataMutable(input); + auto result_data = FlatVector::GetDataMutable(result); for (idx_t r = 0; r < size; r++) { if (FlatVector::IsNull(input, r)) { FlatVector::SetNull(result, r, true); @@ -321,7 +324,7 @@ void PostgresConnection::CopyChunk(ClientContext &context, PostgresCopyState &st for (idx_t c = 0; c < chunk.ColumnCount(); c++) { CastToPostgresVarchar(context, chunk.data[c], varchar_chunk.data[c], chunk.size()); } - varchar_chunk.SetCardinality(chunk.size()); + varchar_chunk.SetChildCardinality(chunk.size()); PostgresTextWriter writer(state); for (idx_t r = 0; r < chunk.size(); r++) { diff --git a/src/postgres_filter_pushdown.cpp b/src/postgres_filter_pushdown.cpp index 62cf05b96..23916444a 100644 --- a/src/postgres_filter_pushdown.cpp +++ b/src/postgres_filter_pushdown.cpp @@ -1,17 +1,22 @@ #include "postgres_filter_pushdown.hpp" #include "duckdb/parser/keyword_helper.hpp" -#include "duckdb/planner/filter/in_filter.hpp" -#include "duckdb/planner/filter/optional_filter.hpp" -#include "duckdb/planner/filter/struct_filter.hpp" +#include "duckdb/function/scalar/struct_utils.hpp" +#include "duckdb/planner/expression/bound_comparison_expression.hpp" +#include "duckdb/planner/expression/bound_conjunction_expression.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression/bound_operator_expression.hpp" +#include "duckdb/planner/filter/table_filter_functions.hpp" #include "duckdb/common/enum_util.hpp" namespace duckdb { -string PostgresFilterPushdown::CreateExpression(string &column_name, vector> &filters, - string op, column_t column_id) { +string PostgresFilterPushdown::CreateExpression(const string &column_name, + const vector> &filters, string op, + column_t column_id) { vector filter_entries; for (auto &filter : filters) { - auto filter_str = TransformFilter(column_name, *filter, column_id); + auto filter_str = TransformExpression(column_name, *filter, column_id); if (!filter_str.empty()) { filter_entries.push_back(std::move(filter_str)); } @@ -67,84 +72,155 @@ string PostgresFilterPushdown::TransformCTIDLiteral(const Value &constant) { throw InternalException("FIXME: transform ctid literal"); } -string PostgresFilterPushdown::TransformConstantFilter(string &column_name, ConstantFilter &constant_filter, - column_t column_id) { +string PostgresFilterPushdown::TransformConstantFilter(const string &column_name, ExpressionType comparison_type, + const Value &constant, column_t column_id) { string constant_string; if (IsVirtualColumn(column_id)) { return "FALSE"; } else { - constant_string = TransformLiteral(constant_filter.constant); + constant_string = TransformLiteral(constant); } - auto operator_string = TransformComparison(constant_filter.comparison_type); - string comparison = StringUtil::Format("%s %s %s", column_name, operator_string, constant_string); - if (constant_filter.constant.type().id() == LogicalTypeId::VARCHAR) { - comparison += " COLLATE \"C\""; - } - return comparison; + auto operator_string = TransformComparison(comparison_type); + return StringUtil::Format("%s %s %s", column_name, operator_string, constant_string); } -string PostgresFilterPushdown::TransformFilter(string &column_name, TableFilter &filter, column_t column_id) { - switch (filter.filter_type) { - case TableFilterType::IS_NULL: - return column_name + " IS NULL"; - case TableFilterType::IS_NOT_NULL: - return column_name + " IS NOT NULL"; - case TableFilterType::CONJUNCTION_AND: { - auto &conjunction_filter = filter.Cast(); - return CreateExpression(column_name, conjunction_filter.child_filters, "AND", column_id); - } - case TableFilterType::CONJUNCTION_OR: { - auto &conjunction_filter = filter.Cast(); - return CreateExpression(column_name, conjunction_filter.child_filters, "OR", column_id); +string PostgresFilterPushdown::TransformExpressionSubject(const string &column_name, const Expression &expr) { + switch (expr.GetExpressionClass()) { + case ExpressionClass::BOUND_REF: + case ExpressionClass::BOUND_COLUMN_REF: + return column_name; + case ExpressionClass::BOUND_FUNCTION: { + auto &func = expr.Cast(); + idx_t child_idx; + if (!TryGetStructExtractChildIndex(func, child_idx) || func.GetChildren().empty()) { + return string(); + } + auto parent_name = TransformExpressionSubject(column_name, *func.GetChildren()[0]); + if (parent_name.empty()) { + return string(); + } + auto &struct_type = func.GetChildren()[0]->GetReturnType(); + if (struct_type.id() != LogicalTypeId::STRUCT || StructType::IsUnnamed(struct_type)) { + return string(); + } + auto child_name = KeywordHelper::WriteQuoted(StructType::GetChildName(struct_type, child_idx), '\"'); + return "(" + parent_name + ")." + child_name; } - case TableFilterType::CONSTANT_COMPARISON: { - auto &constant_filter = filter.Cast(); - return TransformConstantFilter(column_name, constant_filter, column_id); + default: + return string(); } - case TableFilterType::STRUCT_EXTRACT: { - auto &struct_filter = filter.Cast(); - auto child_name = KeywordHelper::WriteQuoted(struct_filter.child_name, '\"'); - auto new_name = "(" + column_name + ")." + child_name; - return TransformFilter(new_name, *struct_filter.child_filter, column_id); +} + +string PostgresFilterPushdown::TransformExpression(const string &column_name, const Expression &expr, + column_t column_id) { + if (BoundComparisonExpression::IsComparison(expr)) { + auto &comparison = expr.Cast(); + auto comparison_type = comparison.GetExpressionType(); + auto &left = BoundComparisonExpression::Left(comparison); + auto &right = BoundComparisonExpression::Right(comparison); + auto subject = TransformExpressionSubject(column_name, left); + const Value *constant = nullptr; + if (!subject.empty() && right.GetExpressionClass() == ExpressionClass::BOUND_CONSTANT) { + constant = &right.Cast().GetValue(); + } else { + subject = TransformExpressionSubject(column_name, right); + if (!subject.empty() && left.GetExpressionClass() == ExpressionClass::BOUND_CONSTANT) { + constant = &left.Cast().GetValue(); + comparison_type = FlipComparisonExpression(comparison_type); + } + } + if (!constant || subject.empty()) { + return string(); + } + return TransformConstantFilter(subject, comparison_type, *constant, column_id); } - case TableFilterType::OPTIONAL_FILTER: { - auto &optional_filter = filter.Cast(); - return TransformFilter(column_name, *optional_filter.child_filter, column_id); + + switch (expr.GetExpressionClass()) { + case ExpressionClass::BOUND_CONJUNCTION: { + auto &conjunction = expr.Cast(); + switch (conjunction.GetExpressionType()) { + case ExpressionType::CONJUNCTION_AND: + return CreateExpression(column_name, conjunction.GetChildren(), "AND", column_id); + case ExpressionType::CONJUNCTION_OR: + return CreateExpression(column_name, conjunction.GetChildren(), "OR", column_id); + default: + return string(); + } } - case TableFilterType::IN_FILTER: { - auto &in_filter = filter.Cast(); - string in_list; - for (auto &val : in_filter.values) { - if (!in_list.empty()) { - in_list += ", "; + case ExpressionClass::BOUND_OPERATOR: { + auto &op = expr.Cast(); + auto subject = + op.GetChildren().empty() ? string() : TransformExpressionSubject(column_name, *op.GetChildren()[0]); + switch (op.GetExpressionType()) { + case ExpressionType::OPERATOR_IS_NULL: + return !subject.empty() ? subject + " IS NULL" : string(); + case ExpressionType::OPERATOR_IS_NOT_NULL: + return !subject.empty() ? subject + " IS NOT NULL" : string(); + case ExpressionType::COMPARE_IN: { + if (subject.empty()) { + return string(); } - in_list += TransformLiteral(val); + string in_list; + for (idx_t i = 1; i < op.GetChildren().size(); i++) { + if (op.GetChildren()[i]->GetExpressionClass() != ExpressionClass::BOUND_CONSTANT) { + return string(); + } + if (!in_list.empty()) { + in_list += ", "; + } + auto &constant = op.GetChildren()[i]->Cast().GetValue(); + in_list += IsVirtualColumn(column_id) ? "FALSE" : TransformLiteral(constant); + } + return IsVirtualColumn(column_id) ? "FALSE" : subject + " IN (" + in_list + ")"; + } + default: + return string(); } - return column_name + " IN (" + in_list + ")"; } - case TableFilterType::DYNAMIC_FILTER: + case ExpressionClass::BOUND_FUNCTION: { + auto &func = expr.Cast(); + if (func.Function().GetName() == OptionalFilterScalarFun::NAME && func.BindInfo()) { + auto &data = func.BindInfo()->Cast(); + return data.child_filter_expr ? TransformExpression(column_name, *data.child_filter_expr, column_id) + : string(); + } + if (func.Function().GetName() == SelectivityOptionalFilterScalarFun::NAME && func.BindInfo()) { + auto &data = func.BindInfo()->Cast(); + return data.child_filter_expr ? TransformExpression(column_name, *data.child_filter_expr, column_id) + : string(); + } + if (func.Function().GetName() == DynamicFilterScalarFun::NAME) { + return string(); + } return string(); + } default: throw InternalException("Unsupported table filter type"); } } +string PostgresFilterPushdown::TransformFilter(const string &column_name, const TableFilter &filter, + column_t column_id) { + auto &expr_filter = ExpressionFilter::GetExpressionFilter(filter, "PostgresFilterPushdown::TransformFilter"); + return TransformExpression(column_name, *expr_filter.expr, column_id); +} + string PostgresFilterPushdown::TransformFilters(const vector &column_ids, optional_ptr filters, const vector &names) { - if (!filters || filters->filters.empty()) { + if (!filters || !filters->HasFilters()) { // no filters return string(); } string result; - for (auto &entry : filters->filters) { + for (auto &entry : *filters) { string column_name; - auto column_id = column_ids[entry.first]; + auto column_id = column_ids[entry.GetIndex()]; if (IsVirtualColumn(column_id)) { column_name = "ctid"; } else { column_name = KeywordHelper::WriteQuoted(names[column_id], '"'); } - auto &filter = *entry.second; + auto &filter = entry.Filter(); auto filter_text = TransformFilter(column_name, filter, column_id); if (filter_text.empty()) { diff --git a/src/postgres_hstore.cpp b/src/postgres_hstore.cpp index 3a5a0cc69..c1fe02ada 100644 --- a/src/postgres_hstore.cpp +++ b/src/postgres_hstore.cpp @@ -168,22 +168,19 @@ void PostgresHstoreGetFun(DataChunk &args, ExpressionState &state, Vector &resul auto &hstore_vector = args.data[0]; auto &key_vector = args.data[1]; - BinaryExecutor::ExecuteWithNulls( - hstore_vector, key_vector, result, args.size(), - [&](string_t hstore, string_t key, ValidityMask &mask, idx_t idx) -> string_t { + BinaryExecutor::Execute( + hstore_vector, key_vector, result, args.size(), [&](string_t hstore, string_t key) -> optional { auto pairs = ParseHstore(hstore.GetString()); for (auto it = pairs.rbegin(); it != pairs.rend(); ++it) { if (it->key == key.GetString()) { if (!it->value) { - mask.SetInvalid(idx); - return string_t {}; + return nullopt; } return StringVector::AddString(result, *it->value); } } - mask.SetInvalid(idx); - return string_t {}; + return nullopt; }); } diff --git a/src/postgres_text_reader.cpp b/src/postgres_text_reader.cpp index 3f41a8f5d..132b0b585 100644 --- a/src/postgres_text_reader.cpp +++ b/src/postgres_text_reader.cpp @@ -1,3 +1,7 @@ +#include "duckdb/common/vector/list_vector.hpp" +#include "duckdb/common/vector/map_vector.hpp" +#include "duckdb/common/vector/string_vector.hpp" +#include "duckdb/common/vector/struct_vector.hpp" #include "postgres_text_reader.hpp" #include "postgres_scanner.hpp" #include "duckdb/common/types/blob.hpp" @@ -33,7 +37,7 @@ struct PostgresListParser { if (!quoted && str == "NULL") { FlatVector::SetNull(vector, size, true); } else { - FlatVector::GetData(vector)[size] = StringVector::AddStringOrBlob(vector, str); + FlatVector::GetDataMutable(vector)[size] = StringVector::AddStringOrBlob(vector, str); } size++; quoted = false; @@ -70,7 +74,7 @@ struct PostgresStructParser { if (!quoted && str == "NULL") { FlatVector::SetNull(col, row_offset, true); } else { - FlatVector::GetData(col)[row_offset] = StringVector::AddStringOrBlob(col, str); + FlatVector::GetDataMutable(col)[row_offset] = StringVector::AddStringOrBlob(col, str); } column_offset++; } @@ -203,7 +207,7 @@ void PostgresTextReader::ConvertList(Vector &source, Vector &target, const Postg source.ToUnifiedFormat(count, vdata); auto strings = UnifiedVectorFormat::GetData(vdata); - auto list_data = FlatVector::GetData(target); + auto list_data = FlatVector::GetDataMutable(target); PostgresListParser list_parser; for (idx_t i = 0; i < count; i++) { @@ -245,7 +249,7 @@ void PostgresTextReader::ConvertStruct(Vector &source, Vector &target, const Pos ParsePostgresStruct(struct_parser, strings[i]); } for (idx_t c = 0; c < children.size(); c++) { - ConvertVector(struct_parser.data.data[c], *children[c], + ConvertVector(struct_parser.data.data[c], children[c], c >= postgres_type.children.size() ? PostgresType() : postgres_type.children[c], count); } } @@ -255,7 +259,7 @@ void PostgresTextReader::ConvertCTID(Vector &source, Vector &target, idx_t count UnifiedVectorFormat vdata; source.ToUnifiedFormat(count, vdata); auto strings = UnifiedVectorFormat::GetData(vdata); - auto result = FlatVector::GetData(target); + auto result = FlatVector::GetDataMutable(target); for (idx_t i = 0; i < count; i++) { if (!vdata.validity.RowIsValid(i)) { @@ -276,7 +280,7 @@ void PostgresTextReader::ConvertBlob(Vector &source, Vector &target, idx_t count UnifiedVectorFormat vdata; source.ToUnifiedFormat(count, vdata); auto strings = UnifiedVectorFormat::GetData(vdata); - auto result = FlatVector::GetData(target); + auto result = FlatVector::GetDataMutable(target); for (idx_t i = 0; i < count; i++) { if (!vdata.validity.RowIsValid(i)) { @@ -309,7 +313,7 @@ static void ConvertGeometry(Vector &source, Vector &target, idx_t count) { UnifiedVectorFormat vdata; source.ToUnifiedFormat(count, vdata); const auto strings = UnifiedVectorFormat::GetData(vdata); - const auto result = FlatVector::GetData(target); + const auto result = FlatVector::GetDataMutable(target); string result_blob; @@ -343,7 +347,7 @@ static void ConvertGeometry(Vector &source, Vector &target, idx_t count) { } // Finally convert from WKB (which will handle big-endian format too) - if (!Geometry::FromBinary(result_blob, result[out_idx], target, true)) { + if (!Geometry::FromBinary(result_blob, result[out_idx], StringVector::GetStringHeap(target), true)) { throw InvalidInputException("Failed to parse geometry from WKB - invalid format"); } } @@ -397,11 +401,11 @@ PostgresReadResult PostgresTextReader::Read(DataChunk &output) { FlatVector::SetNull(out_vec, output_offset, true); continue; } - auto col_data = FlatVector::GetData(out_vec); + auto col_data = FlatVector::GetDataMutable(out_vec); col_data[output_offset] = StringVector::AddStringOrBlob(out_vec, result->GetStringRef(row_offset, output_idx)); } - scan_chunk.SetCardinality(scan_chunk.size() + 1); + scan_chunk.SetChildCardinality(scan_chunk.size() + 1); } for (idx_t c = 0; c < output.ColumnCount(); c++) { auto col_idx = column_ids[c]; @@ -413,7 +417,7 @@ PostgresReadResult PostgresTextReader::Read(DataChunk &output) { ConvertVector(scan_chunk.data[c], output.data[c], bind_data.postgres_types[c], scan_chunk.size()); } } - output.SetCardinality(scan_chunk.size()); + output.SetChildCardinality(scan_chunk.size()); bool finished = row_offset >= result->Count(); if (finished) { diff --git a/src/postgres_utils.cpp b/src/postgres_utils.cpp index 41bb09306..d5fe93a40 100644 --- a/src/postgres_utils.cpp +++ b/src/postgres_utils.cpp @@ -16,7 +16,7 @@ PGconn *PostgresUtils::PGConnect(const string &dsn, const string &attach_path) { char *msg_cstr = PQerrorMessage(conn); std::string msg = msg_cstr != nullptr ? std::string(msg_cstr) : std::string(); PQfinish(conn); - throw IOException("Unable to connect to Postgres at \"%s\": %s", attach_path, msg); + throw IOException("Unable TODO:REMOVEME to connect to Postgres at \"%s\": %s", attach_path, msg); } PQsetNoticeProcessor(conn, PGNoticeProcessor, nullptr); return conn; diff --git a/src/storage/postgres_catalog.cpp b/src/storage/postgres_catalog.cpp index 2ab239d9f..4754e6bf3 100644 --- a/src/storage/postgres_catalog.cpp +++ b/src/storage/postgres_catalog.cpp @@ -9,11 +9,50 @@ #include "duckdb/storage/database_size.hpp" #include "duckdb/parser/parsed_data/drop_info.hpp" #include "duckdb/parser/parsed_data/create_schema_info.hpp" +#include "duckdb/parser/expression/constant_expression.hpp" +#include "duckdb/parser/expression/function_expression.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" #include "duckdb/main/attached_database.hpp" #include "duckdb/main/secret/secret_manager.hpp" namespace duckdb { +unique_ptr PostgresCatalog::RemoteExecute(ClientContext &context, const string &sql) { + vector> args; + args.push_back(make_uniq(Value(GetName()))); + args.push_back(make_uniq(Value(sql))); + auto func_ref = make_uniq(); + func_ref->function = make_uniq("postgres_query", std::move(args)); + return func_ref; +} + +string PostgresCatalog::GetConnectDisplay() { + // `postgres://[:]` — standard postgres URI shorthand. dbname is already shown + // via current_database in the prompt, so it's omitted here. + string host, port; + for (auto &pair : StringUtil::Split(connection_string, " ")) { + auto eq = pair.find('='); + if (eq == string::npos) { + continue; + } + auto key = pair.substr(0, eq); + auto val = pair.substr(eq + 1); + if (key == "host") { + host = val; + } else if (key == "port") { + port = val; + } + } + string result = "postgres://"; + if (!host.empty()) { + result += host; + } + if (!port.empty()) { + result += ":" + port; + } + return result; +} + unique_ptr GetSecret(ClientContext &context, const string &secret_name) { auto &secret_manager = SecretManager::Get(context); auto transaction = CatalogTransaction::GetSystemCatalogTransaction(context); diff --git a/src/storage/postgres_configure_pool.cpp b/src/storage/postgres_configure_pool.cpp index 08297e712..912bcfa1a 100644 --- a/src/storage/postgres_configure_pool.cpp +++ b/src/storage/postgres_configure_pool.cpp @@ -142,7 +142,7 @@ static void ConfigurePoolFunction(ClientContext &context, TableFunctionInput &in auto &lstate = input.local_state->Cast(); if (lstate.exec_state == ExecState::EXHAUSTED) { - output.SetCardinality(0); + output.SetChildCardinality(0); return; } @@ -225,7 +225,7 @@ static void ConfigurePoolFunction(ClientContext &context, TableFunctionInput &in row_idx++; } - output.SetCardinality(row_idx); + output.SetChildCardinality(row_idx); lstate.exec_state = ExecState::EXHAUSTED; } diff --git a/src/storage/postgres_delete.cpp b/src/storage/postgres_delete.cpp index d2e6a24b5..7c9b02355 100644 --- a/src/storage/postgres_delete.cpp +++ b/src/storage/postgres_delete.cpp @@ -61,7 +61,7 @@ SinkResultType PostgresDelete::Sink(ExecutionContext &context, DataChunk &chunk, chunk.Flatten(); auto &row_identifiers = chunk.data[row_id_index]; - auto row_data = FlatVector::GetData(row_identifiers); + auto row_data = FlatVector::GetDataMutable(row_identifiers); for (idx_t i = 0; i < chunk.size(); i++) { if (!gstate.ctid_list.empty()) { gstate.ctid_list += ","; @@ -99,7 +99,7 @@ SinkFinalizeType PostgresDelete::Finalize(Pipeline &pipeline, Event &event, Clie SourceResultType PostgresDelete::GetDataInternal(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const { auto &insert_gstate = sink_state->Cast(); - chunk.SetCardinality(1); + chunk.SetChildCardinality(1); chunk.SetValue(0, 0, Value::BIGINT(insert_gstate.delete_count)); return SourceResultType::FINISHED; @@ -129,7 +129,7 @@ PhysicalOperator &PostgresCatalog::PlanDelete(ClientContext &context, PhysicalPl auto &bound_ref = op.expressions[0]->Cast(); PostgresCatalog::MaterializePostgresScans(plan); - auto &delete_op = planner.Make(op, op.table, bound_ref.index); + auto &delete_op = planner.Make(op, op.table, bound_ref.Index()); delete_op.children.push_back(plan); return delete_op; } diff --git a/src/storage/postgres_index_set.cpp b/src/storage/postgres_index_set.cpp index 2ccd309c5..f18353803 100644 --- a/src/storage/postgres_index_set.cpp +++ b/src/storage/postgres_index_set.cpp @@ -46,10 +46,10 @@ void PostgresIndexSet::LoadEntries(ClientContext &context, PostgresTransaction & } void PGUnqualifyColumnReferences(ParsedExpression &expr) { - if (expr.type == ExpressionType::COLUMN_REF) { + if (expr.GetExpressionType() == ExpressionType::COLUMN_REF) { auto &colref = expr.Cast(); - auto name = std::move(colref.column_names.back()); - colref.column_names = {std::move(name)}; + auto name = std::move(colref.ColumnNamesMutable().back()); + colref.ColumnNamesMutable() = {std::move(name)}; return; } ParsedExpressionIterator::EnumerateChildren(expr, PGUnqualifyColumnReferences); diff --git a/src/storage/postgres_insert.cpp b/src/storage/postgres_insert.cpp index 5310b1d53..e754c0714 100644 --- a/src/storage/postgres_insert.cpp +++ b/src/storage/postgres_insert.cpp @@ -151,7 +151,7 @@ SinkFinalizeType PostgresInsert::Finalize(Pipeline &pipeline, Event &event, Clie SourceResultType PostgresInsert::GetDataInternal(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const { auto &insert_gstate = sink_state->Cast(); - chunk.SetCardinality(1); + chunk.SetChildCardinality(1); chunk.SetValue(0, 0, Value::BIGINT(insert_gstate.insert_count)); return SourceResultType::FINISHED; diff --git a/src/storage/postgres_merge_into.cpp b/src/storage/postgres_merge_into.cpp index 03188d612..7bcab80df 100644 --- a/src/storage/postgres_merge_into.cpp +++ b/src/storage/postgres_merge_into.cpp @@ -51,7 +51,7 @@ unique_ptr PostgresPlanMergeIntoAction(PostgresCatalog &catal break; } case MergeActionType::MERGE_DELETE: { - LogicalDelete delete_op(op.table, 0); + LogicalDelete delete_op(op.table, TableIndex(0)); auto ref = make_uniq(LogicalType::BIGINT, op.row_id_start); delete_op.expressions.push_back(std::move(ref)); delete_op.bound_constraints = std::move(bound_constraints); @@ -59,7 +59,7 @@ unique_ptr PostgresPlanMergeIntoAction(PostgresCatalog &catal break; } case MergeActionType::MERGE_INSERT: { - LogicalInsert insert_op(op.table, 0); + LogicalInsert insert_op(op.table, TableIndex(0)); insert_op.bound_constraints = std::move(bound_constraints); for (auto &def : op.bound_defaults) { insert_op.bound_defaults.push_back(def->Copy()); diff --git a/src/storage/postgres_table_set.cpp b/src/storage/postgres_table_set.cpp index ccbc19c17..c3e903972 100644 --- a/src/storage/postgres_table_set.cpp +++ b/src/storage/postgres_table_set.cpp @@ -386,7 +386,7 @@ void PostgresTableSet::AlterTable(ClientContext &context, PostgresTransaction &t "only constant DEFAULT expressions are supported"); } const ConstantExpression &default_const_expr = default_expr.Cast(); - std::string sql_str = default_const_expr.value.ToSQLString(); + std::string sql_str = default_const_expr.GetValue().ToSQLString(); sql += " DEFAULT "; sql += sql_str; } diff --git a/src/storage/postgres_update.cpp b/src/storage/postgres_update.cpp index 42dc5bb71..d6dd54469 100644 --- a/src/storage/postgres_update.cpp +++ b/src/storage/postgres_update.cpp @@ -119,13 +119,13 @@ SinkResultType PostgresUpdate::Sink(ExecutionContext &context, DataChunk &chunk, D_ASSERT(expressions[i]->GetExpressionType() == ExpressionType::BOUND_REF); auto &binding = expressions[i]->Cast(); - gstate.insert_chunk.data[i].Reference(chunk.data[binding.index]); + gstate.insert_chunk.data[i].Reference(chunk.data[binding.Index()]); } // convert our row ids back into ctids auto &row_identifiers = chunk.data[chunk.ColumnCount() - 1]; auto &ctid_vector = gstate.insert_chunk.data[gstate.insert_chunk.ColumnCount() - 1]; - auto row_data = FlatVector::GetData(row_identifiers); - auto varchar_data = FlatVector::GetData(ctid_vector); + auto row_data = FlatVector::GetDataMutable(row_identifiers); + auto varchar_data = FlatVector::GetDataMutable(ctid_vector); for (idx_t r = 0; r < chunk.size(); r++) { // extract the ctid from the row id @@ -140,7 +140,7 @@ SinkResultType PostgresUpdate::Sink(ExecutionContext &context, DataChunk &chunk, ctid_string += ")'"; varchar_data[r] = StringVector::AddString(ctid_vector, ctid_string); } - gstate.insert_chunk.SetCardinality(chunk); + gstate.insert_chunk.SetChildCardinality(chunk.size()); auto &transaction = PostgresTransaction::Get(context.client, gstate.table.catalog); auto &connection = transaction.GetConnection(); @@ -180,7 +180,7 @@ SinkFinalizeType PostgresUpdate::Finalize(Pipeline &pipeline, Event &event, Clie SourceResultType PostgresUpdate::GetDataInternal(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const { auto &insert_gstate = sink_state->Cast(); - chunk.SetCardinality(1); + chunk.SetChildCardinality(1); chunk.SetValue(0, 0, Value::BIGINT(insert_gstate.update_count)); return SourceResultType::FINISHED; diff --git a/test/sql/scanner/ssl.test b/test/sql/scanner/ssl.test index 92216dcb8..59ce75f5c 100644 --- a/test/sql/scanner/ssl.test +++ b/test/sql/scanner/ssl.test @@ -6,6 +6,8 @@ require postgres_scanner require-env POSTGRES_TEST_DATABASE_AVAILABLE +require-env POSTGRES_TEST_TEMPORARY_DISABLED + statement ok CALL postgres_attach('dbname=postgresscanner sslmode=require'); diff --git a/test/sql/storage/attach_connection_pool_configure.test b/test/sql/storage/attach_connection_pool_configure.test index 943051d43..73b25e5da 100644 --- a/test/sql/storage/attach_connection_pool_configure.test +++ b/test/sql/storage/attach_connection_pool_configure.test @@ -6,9 +6,17 @@ require postgres_scanner require-env POSTGRES_TEST_DATABASE_AVAILABLE +require-env POSTGRES_TEST_TEMPORARY_DISABLED + statement ok PRAGMA enable_verification +statement ok +ATTACH 'dbname=postgresscanner' AS loader (TYPE POSTGRES); + +statement ok +DETACH loader; + statement ok SET pg_pool_max_connections = 8 @@ -26,7 +34,7 @@ SELECT catalog_name, max_connections, cache_hits, cache_misses, try_failures, th FROM postgres_configure_pool() ORDER BY catalog_name ---- -s 8 1 1 0 FALSE 0 60000 1 30000 SELECT 1 +s 8 2 1 0 FALSE 0 60000 1 30000 SELECT 1 s1 8 1 1 0 FALSE 0 60000 1 30000 SELECT 1 query II diff --git a/test/sql/storage/attach_like.test b/test/sql/storage/attach_like.test index 4722f62f4..87961f0e8 100644 --- a/test/sql/storage/attach_like.test +++ b/test/sql/storage/attach_like.test @@ -6,6 +6,8 @@ require postgres_scanner require-env POSTGRES_TEST_DATABASE_AVAILABLE +require-env POSTGRES_TEST_TEMPORARY_DISABLED + statement ok PRAGMA enable_verification diff --git a/test/sql/storage/attach_non_existent.test b/test/sql/storage/attach_non_existent.test index d4f067dd4..8fc52cfbe 100644 --- a/test/sql/storage/attach_non_existent.test +++ b/test/sql/storage/attach_non_existent.test @@ -12,4 +12,4 @@ PRAGMA enable_verification statement error ATTACH 'dbname=dbdoesnotexistx' AS s1 (TYPE POSTGRES) ---- -does not exist +dbdoesnotexistx diff --git a/test/sql/storage/attach_secret.test b/test/sql/storage/attach_secret.test index 6dfde17e3..96c5361a4 100644 --- a/test/sql/storage/attach_secret.test +++ b/test/sql/storage/attach_secret.test @@ -6,6 +6,8 @@ require postgres_scanner require-env POSTGRES_TEST_DATABASE_AVAILABLE +require-env POSTGRES_TEST_TEMPORARY_DISABLED + statement ok PRAGMA enable_verification diff --git a/test/sql/storage/attach_timeout_error.test b/test/sql/storage/attach_timeout_error.test index 92ff0cc80..807e2da71 100644 --- a/test/sql/storage/attach_timeout_error.test +++ b/test/sql/storage/attach_timeout_error.test @@ -6,6 +6,8 @@ require postgres_scanner require-env POSTGRES_TEST_DATABASE_AVAILABLE +require-env POSTGRES_TEST_TEMPORARY_DISABLED + statement ok ATTACH 'dbname=postgresscanner options=''-c statement_timeout=1000''' AS s (TYPE POSTGRES, READ_ONLY); diff --git a/test/sql/storage/attach_types.test b/test/sql/storage/attach_types.test index 566b6c923..4a0697940 100644 --- a/test/sql/storage/attach_types.test +++ b/test/sql/storage/attach_types.test @@ -36,7 +36,7 @@ NULL NULL NULL NULL # test all types statement ok CREATE TABLE all_types_tbl AS SELECT * -EXCLUDE (float, double, ubigint, hugeint, uhugeint, nested_int_array, struct, struct_of_arrays, array_of_structs, map, "union", fixed_int_array, fixed_varchar_array, fixed_nested_int_array, fixed_nested_varchar_array, fixed_struct_array, struct_of_fixed_array, fixed_array_of_int_list, list_of_fixed_int_array, bignum, geometry) +EXCLUDE (float, double, ubigint, hugeint, uhugeint, nested_int_array, struct, struct_of_arrays, array_of_structs, map, "union", fixed_int_array, fixed_varchar_array, fixed_nested_int_array, fixed_nested_varchar_array, fixed_struct_array, struct_of_fixed_array, fixed_array_of_int_list, list_of_fixed_int_array, bignum, geometry, timestamp_tz_ns) REPLACE( CASE WHEN int IS NOT NULL THEN '2000-01-01' ELSE NULL END AS date, CASE WHEN int IS NOT NULL THEN '2000-01-01 01:02:03' ELSE NULL END AS timestamp, diff --git a/test/sql/storage/postgres_execute_transaction.test b/test/sql/storage/postgres_execute_transaction.test index 1515facc1..5bc33930c 100644 --- a/test/sql/storage/postgres_execute_transaction.test +++ b/test/sql/storage/postgres_execute_transaction.test @@ -6,6 +6,8 @@ require postgres_scanner require-env POSTGRES_TEST_DATABASE_AVAILABLE +require-env POSTGRES_TEST_TEMPORARY_DISABLED + statement ok PRAGMA enable_verification