diff --git a/include/pgduckdb/pg/declarations.hpp b/include/pgduckdb/pg/declarations.hpp index 26244c8b..1c908ccc 100644 --- a/include/pgduckdb/pg/declarations.hpp +++ b/include/pgduckdb/pg/declarations.hpp @@ -12,6 +12,7 @@ It should not include any C++ code, only Postgres C declarations. */ extern "C" { +typedef int16_t AttrNumber; typedef uint32_t BlockNumber; typedef double Cardinality; @@ -25,6 +26,7 @@ struct FormData_pg_class; typedef FormData_pg_class *Form_pg_class; struct HeapTupleData; +typedef HeapTupleData *HeapTuple; struct Node; @@ -40,5 +42,4 @@ struct TupleDescData; typedef struct TupleDescData *TupleDesc; struct TupleTableSlot; - } diff --git a/include/pgduckdb/pg/relations.hpp b/include/pgduckdb/pg/relations.hpp index ec57cb09..1f3d4dc3 100644 --- a/include/pgduckdb/pg/relations.hpp +++ b/include/pgduckdb/pg/relations.hpp @@ -20,4 +20,16 @@ Form_pg_attribute GetAttr(const TupleDesc tupleDesc, int i); void EstimateRelSize(Relation rel, int32_t *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac); -} +Oid GetRelidFromSchemaAndTable(const char *, const char *); + +bool IsValidOid(Oid); + +HeapTuple SearchSysCacheForRel(Oid); + +bool IsValidHeapTuple(HeapTuple); + +bool IsRelView(HeapTuple); + +void ReleaseSysCache(HeapTuple); + +} // namespace pgduckdb diff --git a/include/pgduckdb/pgduckdb_types.hpp b/include/pgduckdb/pgduckdb_types.hpp index d7de1266..0a0644cc 100644 --- a/include/pgduckdb/pgduckdb_types.hpp +++ b/include/pgduckdb/pgduckdb_types.hpp @@ -10,7 +10,8 @@ typedef uint64_t idx_t; // From duckdb.h // DuckDB has date starting from 1/1/1970 while PG starts from 1/1/2000 constexpr int32_t PGDUCKDB_DUCK_DATE_OFFSET = 10957; -constexpr int64_t PGDUCKDB_DUCK_TIMESTAMP_OFFSET = static_cast(10957) * static_cast(86400000000) /* USECS_PER_DAY */; +constexpr int64_t PGDUCKDB_DUCK_TIMESTAMP_OFFSET = + static_cast(10957) * static_cast(86400000000) /* USECS_PER_DAY */; duckdb::LogicalType ConvertPostgresToDuckColumnType(Form_pg_attribute &attribute); Oid GetPostgresDuckDBType(duckdb::LogicalType type); diff --git a/include/pgduckdb/scan/heap_reader.hpp b/include/pgduckdb/scan/heap_reader.hpp index 0061bd96..4832ac4a 100644 --- a/include/pgduckdb/scan/heap_reader.hpp +++ b/include/pgduckdb/scan/heap_reader.hpp @@ -2,13 +2,13 @@ #include "duckdb.hpp" +#include "pgduckdb/scan/postgres_scan.hpp" + extern "C" { #include "postgres.h" #include "storage/bufmgr.h" } -#include "pgduckdb/scan/postgres_scan.hpp" - namespace pgduckdb { // HeapReaderGlobalState diff --git a/include/pgduckdb/scan/postgres_scan.hpp b/include/pgduckdb/scan/postgres_scan.hpp index 4e842eb4..defbdfb9 100644 --- a/include/pgduckdb/scan/postgres_scan.hpp +++ b/include/pgduckdb/scan/postgres_scan.hpp @@ -2,16 +2,11 @@ #include "duckdb.hpp" -extern "C" { -#include "postgres.h" -#include "miscadmin.h" -#include "access/relscan.h" -#include "executor/executor.h" -#include "nodes/pathnodes.h" -} - +#include "pgduckdb/pg/declarations.hpp" #include "pgduckdb/utility/allocator.hpp" +#include "pgduckdb/utility/cpp_only_file.hpp" // Must be last include. + namespace pgduckdb { class PostgresScanGlobalState { diff --git a/src/catalog/pgduckdb_transaction.cpp b/src/catalog/pgduckdb_transaction.cpp index 415d5293..8d1ad104 100644 --- a/src/catalog/pgduckdb_transaction.cpp +++ b/src/catalog/pgduckdb_transaction.cpp @@ -3,15 +3,13 @@ #include "pgduckdb/catalog/pgduckdb_transaction.hpp" #include "pgduckdb/catalog/pgduckdb_table.hpp" #include "pgduckdb/scan/postgres_scan.hpp" +#include "pgduckdb/pg/relations.hpp" + #include "duckdb/parser/parsed_data/create_table_info.hpp" #include "duckdb/parser/parsed_data/create_schema_info.hpp" #include "duckdb/catalog/catalog.hpp" -extern "C" { -#include "catalog/namespace.h" // makeRangeVarFromNameList -#include "utils/syscache.h" // RELOID -#include "utils/rel.h" // Form_pg_class, RELKIND_VIEW -} +#include "pgduckdb/utility/cpp_only_file.hpp" namespace pgduckdb { @@ -40,30 +38,19 @@ SchemaItems::GetTable(const duckdb::string &entry_name) { return it->second.get(); } - auto snapshot = schema->snapshot; - auto &catalog = schema->catalog; - - List *name_list = NIL; - name_list = lappend(name_list, makeString(pstrdup(name.c_str()))); - name_list = lappend(name_list, makeString(pstrdup(entry_name.c_str()))); - - RangeVar *table_range_var = makeRangeVarFromNameList(name_list); - Oid rel_oid = RangeVarGetRelid(table_range_var, AccessShareLock, true); - if (rel_oid == InvalidOid) { - // Table could not be found - return nullptr; + Oid rel_oid = GetRelidFromSchemaAndTable(name.c_str(), entry_name.c_str()); + if (!IsValidOid(rel_oid)) { + return nullptr; // Table could not be found } // Check if the Relation is a VIEW - auto tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(rel_oid)); - if (!HeapTupleIsValid(tuple)) { + auto tuple = SearchSysCacheForRel(rel_oid); + if (!IsValidHeapTuple(tuple)) { throw duckdb::CatalogException("Cache lookup failed for relation %u", rel_oid); } - auto relForm = (Form_pg_class)GETSTRUCT(tuple); - // Check if the relation is a view - if (relForm->relkind == RELKIND_VIEW) { + if (IsRelView(tuple)) { ReleaseSysCache(tuple); // Let the replacement scan handle this, the ReplacementScan replaces the view with its view_definition, which // will get bound again and hit a PostgresIndexTable / PostgresHeapTable. @@ -79,8 +66,8 @@ SchemaItems::GetTable(const duckdb::string &entry_name) { PostgresTable::SetTableInfo(info, rel); auto cardinality = PostgresTable::GetTableCardinality(rel); - auto table = duckdb::make_uniq(catalog, *schema, info, rel, cardinality, snapshot); - tables[entry_name] = std::move(table); + tables.emplace(entry_name, duckdb::make_uniq(schema->catalog, *schema, info, rel, cardinality, + schema->snapshot)); return tables[entry_name].get(); } diff --git a/src/pg/relations.cpp b/src/pg/relations.cpp index 0b9e3077..17f4529b 100644 --- a/src/pg/relations.cpp +++ b/src/pg/relations.cpp @@ -4,31 +4,39 @@ extern "C" { #include "postgres.h" -#include "access/relation.h" // relation_open and relation_close -#include "optimizer/plancat.h" // estimate_rel_size +#include "access/htup_details.h" // GETSTRUCT +#include "access/relation.h" // relation_open and relation_close +#include "catalog/namespace.h" // makeRangeVarFromNameList, RangeVarGetRelid +#include "optimizer/plancat.h" // estimate_rel_size #include "utils/rel.h" #include "utils/resowner.h" // CurrentResourceOwner and TopTransactionResourceOwner +#include "utils/syscache.h" // RELOID } namespace pgduckdb { -TupleDesc PDRelationGetDescr(Relation relation) { +TupleDesc +PDRelationGetDescr(Relation relation) { return relation->rd_att; } -int GetTupleDescNatts(const TupleDesc tupleDesc) { +int +GetTupleDescNatts(const TupleDesc tupleDesc) { return tupleDesc->natts; } -const char *GetAttName(const Form_pg_attribute att) { +const char * +GetAttName(const Form_pg_attribute att) { return NameStr(att->attname); } -Form_pg_attribute GetAttr(const TupleDesc tupleDesc, int i) { +Form_pg_attribute +GetAttr(const TupleDesc tupleDesc, int i) { return &tupleDesc->attrs[i]; } -Relation OpenRelation(Oid relationId) { +Relation +OpenRelation(Oid relationId) { /* * We always open & close the relation using the * TopTransactionResourceOwner to avoid having to close the relation @@ -42,7 +50,8 @@ Relation OpenRelation(Oid relationId) { return rel; } -void CloseRelation(Relation rel) { +void +CloseRelation(Relation rel) { /* * We always open & close the relation using the * TopTransactionResourceOwner to avoid having to close the relation @@ -56,8 +65,43 @@ void CloseRelation(Relation rel) { CurrentResourceOwner = saveResourceOwner; } -void EstimateRelSize(Relation rel, int32_t *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac) { +void +EstimateRelSize(Relation rel, int32_t *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac) { ::estimate_rel_size(rel, attr_widths, pages, tuples, allvisfrac); } +Oid +GetRelidFromSchemaAndTable(const char *schema_name, const char *entry_name) { + List *name_list = NIL; + name_list = lappend(name_list, makeString(pstrdup(schema_name))); + name_list = lappend(name_list, makeString(pstrdup(entry_name))); + RangeVar *table_range_var = makeRangeVarFromNameList(name_list); + return RangeVarGetRelid(table_range_var, AccessShareLock, true); +} + +bool +IsValidOid(Oid oid) { + return oid != InvalidOid; +} + +HeapTuple +SearchSysCacheForRel(Oid oid) { + return SearchSysCache1(RELOID, ObjectIdGetDatum(oid)); +} + +bool +IsValidHeapTuple(HeapTuple tuple) { + return HeapTupleIsValid(tuple); +} + +bool +IsRelView(HeapTuple tuple) { + return ((Form_pg_class)GETSTRUCT(tuple))->relkind == RELKIND_VIEW; +} + +void +ReleaseSysCache(HeapTuple tuple) { + ::ReleaseSysCache(tuple); +} + } // namespace pgduckdb diff --git a/src/pgduckdb_duckdb.cpp b/src/pgduckdb_duckdb.cpp index e2676566..a1c33966 100644 --- a/src/pgduckdb_duckdb.cpp +++ b/src/pgduckdb_duckdb.cpp @@ -5,6 +5,7 @@ #include "duckdb/parser/parsed_data/create_table_function_info.hpp" #include "pgduckdb/catalog/pgduckdb_storage.hpp" +#include "pgduckdb/scan/postgres_scan.hpp" extern "C" { #include "postgres.h" @@ -12,12 +13,12 @@ extern "C" { #include "utils/lsyscache.h" // get_relname_relid #include "utils/fmgrprotos.h" // pg_sequence_last_value #include "common/file_perm.h" +#include "miscadmin.h" // superuser } #include "pgduckdb/pgduckdb_options.hpp" #include "pgduckdb/pgduckdb_xact.hpp" #include "pgduckdb/pgduckdb_metadata_cache.hpp" -#include "pgduckdb/scan/postgres_scan.hpp" #include "pgduckdb/scan/postgres_seq_scan.hpp" #include "pgduckdb/pgduckdb_utils.hpp" diff --git a/src/pgduckdb_planner.cpp b/src/pgduckdb_planner.cpp index c1616d89..22a02d0f 100644 --- a/src/pgduckdb_planner.cpp +++ b/src/pgduckdb_planner.cpp @@ -1,6 +1,8 @@ #include "duckdb.hpp" #include "pgduckdb/catalog/pgduckdb_transaction.hpp" +#include "pgduckdb/scan/postgres_scan.hpp" + extern "C" { #include "postgres.h" #include "access/xact.h" @@ -17,7 +19,6 @@ extern "C" { } #include "pgduckdb/pgduckdb_duckdb.hpp" -#include "pgduckdb/scan/postgres_scan.hpp" #include "pgduckdb/pgduckdb_node.hpp" #include "pgduckdb/pgduckdb_planner.hpp" #include "pgduckdb/pgduckdb_types.hpp" diff --git a/src/pgduckdb_types.cpp b/src/pgduckdb_types.cpp index 8ab97743..9e0dbcd2 100644 --- a/src/pgduckdb_types.cpp +++ b/src/pgduckdb_types.cpp @@ -3,6 +3,8 @@ #include "duckdb/common/extra_type_info.hpp" #include "duckdb/common/types/uuid.hpp" +#include "pgduckdb/scan/postgres_scan.hpp" + extern "C" { #include "postgres.h" #include "fmgr.h" @@ -22,7 +24,6 @@ extern "C" { } #include "pgduckdb/pgduckdb.h" -#include "pgduckdb/scan/postgres_scan.hpp" #include "pgduckdb/types/decimal.hpp" #include "pgduckdb/pgduckdb_filter.hpp" #include "pgduckdb/pgduckdb_detoast.hpp" diff --git a/src/scan/heap_reader.cpp b/src/scan/heap_reader.cpp index 38cc832a..9378ac52 100644 --- a/src/scan/heap_reader.cpp +++ b/src/scan/heap_reader.cpp @@ -1,5 +1,7 @@ #include "duckdb.hpp" +#include "pgduckdb/scan/heap_reader.hpp" + extern "C" { #include "postgres.h" #include "pgstat.h" @@ -10,7 +12,6 @@ extern "C" { } #include "pgduckdb/pgduckdb_process_lock.hpp" -#include "pgduckdb/scan/heap_reader.hpp" #include "pgduckdb/pgduckdb_types.hpp" #include "pgduckdb/pgduckdb_utils.hpp" diff --git a/src/scan/postgres_scan.cpp b/src/scan/postgres_scan.cpp index 848db7d9..db84adb7 100644 --- a/src/scan/postgres_scan.cpp +++ b/src/scan/postgres_scan.cpp @@ -12,8 +12,11 @@ #include "duckdb/common/enums/statement_type.hpp" #include "duckdb/common/enums/expression_type.hpp" +#include "pgduckdb/scan/postgres_scan.hpp" + extern "C" { #include "postgres.h" +#include "access/htup_details.h" #include "catalog/namespace.h" #include "catalog/pg_class.h" #include "optimizer/planmain.h" @@ -25,7 +28,6 @@ extern "C" { } #include "pgduckdb/pgduckdb_process_lock.hpp" -#include "pgduckdb/scan/postgres_scan.hpp" #include "pgduckdb/pgduckdb_types.hpp" #include "pgduckdb/pgduckdb_utils.hpp"