diff --git a/src/include/postgres_utils.hpp b/src/include/postgres_utils.hpp index 8fd839e6b..a2651767b 100644 --- a/src/include/postgres_utils.hpp +++ b/src/include/postgres_utils.hpp @@ -106,6 +106,8 @@ class PostgresUtils { static PostgresQueryMode ExtractQueryMode(Value &value); static PostgresCatalog &GetCatalogByName(ClientContext &context, const std::string &name); + static void DeduplicateColumns(vector &names); + private: static mutex libpq_init_lock; static bool libpq_connect_succeeded_at_least_once; diff --git a/src/postgres_query.cpp b/src/postgres_query.cpp index d28b23993..f0b310d6c 100644 --- a/src/postgres_query.cpp +++ b/src/postgres_query.cpp @@ -206,9 +206,10 @@ static unique_ptr PGQueryBind(ClientContext &context, TableFunctio result->postgres_types.push_back(postgres_type); return_types.emplace_back(converted_type); char *name_ptr = PQfname(describe_prepared, c); - string name = name_ptr ? name_ptr : StringUtil::Format("unnamed_%llu", c); + string name = name_ptr ? name_ptr : "unnamed"; names.emplace_back(name); } + PostgresUtils::DeduplicateColumns(names); int nparams = PQnparams(describe_prepared); if (nparams != param_values.size()) { throw BinderException("Incorrect number of parameters specified, expected: %d, actual: %zu, query: \"%s\"", diff --git a/src/postgres_utils.cpp b/src/postgres_utils.cpp index 7d2ec7780..dd1f98ebd 100644 --- a/src/postgres_utils.cpp +++ b/src/postgres_utils.cpp @@ -781,4 +781,24 @@ PostgresCatalog &PostgresUtils::GetCatalogByName(ClientContext &context, const s return catalog.Cast(); } +void PostgresUtils::DeduplicateColumns(vector &names) { + identifier_map_t name_map; + for (auto &column_name : names) { + if (name_map.find(column_name) == name_map.end()) { + // Name does not exist yet + name_map[column_name]++; + } else { + // Name already exists, we add _x where x is the repetition number + Identifier new_column_name(column_name + "_" + std::to_string(name_map[column_name])); + while (name_map.find(new_column_name) != name_map.end()) { + // This name is already here due to a previous definition + name_map[column_name]++; + new_column_name = Identifier(column_name + "_" + std::to_string(name_map[column_name])); + } + column_name = new_column_name; + name_map[new_column_name]++; + } + } +} + } // namespace duckdb diff --git a/test/sql/scanner/postgres_query.test b/test/sql/scanner/postgres_query.test index 46301ce25..56a8c53ce 100644 --- a/test/sql/scanner/postgres_query.test +++ b/test/sql/scanner/postgres_query.test @@ -342,5 +342,19 @@ WHERE query = 'SELECT "brand" FROM (SELECT * FROM cars WHERE color=''red'') AS _ statement ok CALL disable_logging() +# duplicate column names + +query III +FROM postgres_query('s1', 'SELECT 41, 42, 43') +---- +41 42 43 + +query I +SELECT column_name FROM (DESCRIBE FROM postgres_query('s1', 'SELECT 41, 42, 43')) +---- +?column? +?column?_1 +?column?_2 + statement ok DETACH s1 diff --git a/test/sql/storage/limit_parallel_bug.test b/test/sql/storage/limit_parallel_bug.test_slow similarity index 96% rename from test/sql/storage/limit_parallel_bug.test rename to test/sql/storage/limit_parallel_bug.test_slow index dc325a9e7..76570f50d 100644 --- a/test/sql/storage/limit_parallel_bug.test +++ b/test/sql/storage/limit_parallel_bug.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/limit_parallel_bug.test +# name: test/sql/storage/limit_parallel_bug.test_slow # description: Test LIMIT bug with parallelism (issues #380, #395) # group: [storage]