diff --git a/Makefile b/Makefile index 323946f2..1d9211df 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,8 @@ SRCS = src/utility/copy.cpp \ OBJS = $(subst .cpp,.o, $(SRCS)) -REGRESS = basic +REGRESS = basic \ + search_path PG_CONFIG ?= pg_config diff --git a/expected/search_path.out b/expected/search_path.out new file mode 100644 index 00000000..e69de29b diff --git a/sql/search_path.sql b/sql/search_path.sql new file mode 100644 index 00000000..cc86d01c --- /dev/null +++ b/sql/search_path.sql @@ -0,0 +1,30 @@ +CREATE TABLE t(a INT); +INSERT INTO t SELECT g from generate_series(1,10) g; +SELECT count(*) FROM t; +SELECT count(*) FROM public.t; + +-- Create schema `other` +CREATE SCHEMA other; +CREATE TABLE other.t(a INT); +INSERT INTO other.t SELECT g from generate_series(1,100) g; +SELECT count(*) FROM other.t; + +-- Test fully qualified table name combinations +SELECT count(*) FROM public.t, other.t; +SELECT count(*) FROM t, other.t; +SELECT count(*) FROM t,t; + +-- search_path ORDER matters. +SET search_path TO other, public; +SELECT count(*) FROM t; +SELECT count(*) FROM t, public.t; + +-- No search_path +SET search_path TO ''; +SELECT count(*) FROM t, other.t; +SELECT count(*) FROM public.t, other.t; + +-- Cleanup +DROP TABLE other.t; +DROP SCHEMA other; +RESET search_path; \ No newline at end of file diff --git a/src/quack_heap_scan.cpp b/src/quack_heap_scan.cpp index d84c3075..507e5f3b 100644 --- a/src/quack_heap_scan.cpp +++ b/src/quack_heap_scan.cpp @@ -5,8 +5,15 @@ #include "duckdb/parser/expression/constant_expression.hpp" #include "duckdb/parser/expression/comparison_expression.hpp" #include "duckdb/parser/expression/columnref_expression.hpp" +#include "duckdb/parser/qualified_name.hpp" #include "duckdb/common/enums/expression_type.hpp" +extern "C" { +#include "postgres.h" +#include "catalog/namespace.h" +#include "utils/regproc.h" +} + #include "quack/quack_heap_scan.hpp" #include "quack/quack_types.hpp" @@ -143,22 +150,26 @@ FindMatchingHeapRelation(List *tables, const duckdb::string &to_find) { RangeTblEntry *table = (RangeTblEntry *)lfirst(lc); if (table->relid) { auto rel = RelationIdGetRelation(table->relid); + if (!RelationIsValid(rel)) { elog(ERROR, "Relation with OID %u is not valid", table->relid); return nullptr; } - char *rel_name = RelationGetRelationName(rel); - auto table_name = std::string(rel_name); - if (duckdb::StringUtil::CIEquals(table_name, to_find)) { - /* Allow only heap tables */ - if (!rel->rd_amhandler || (GetTableAmRoutine(rel->rd_amhandler) != GetHeapamTableAmRoutine())) { - /* This doesn't have an access method handler, we cant read from this */ - RelationClose(rel); - return nullptr; - } else { - RelationClose(rel); - return table; - } + + /* Allow only heap tables */ + if (!rel->rd_amhandler || (GetTableAmRoutine(rel->rd_amhandler) != GetHeapamTableAmRoutine())) { + /* This doesn't have an access method handler, we cant read from this */ + RelationClose(rel); + return nullptr; + } + + RangeVar *tableRangeVar = makeRangeVarFromNameList(stringToQualifiedNameList(to_find.c_str(), NULL)); + /* Look up and lock the appropriate relation using namespace search */ + Oid relOid = RangeVarGetRelid(tableRangeVar, AccessShareLock, true); + + if (table->relid == relOid) { + RelationClose(rel); + return table; } RelationClose(rel); } @@ -196,6 +207,7 @@ PostgresHeapReplacementScan(duckdb::ClientContext &context, const duckdb::string auto children = CreateFunctionArguments(table, GetActiveSnapshot()); auto table_function = duckdb::make_uniq(); table_function->function = duckdb::make_uniq("postgres_heap_scan", std::move(children)); + table_function->alias = table_name; return std::move(table_function); }