diff --git a/src/backend/columnar/columnar_compression.c b/src/backend/columnar/columnar_compression.c index b73c1dac6..98a175b06 100644 --- a/src/backend/columnar/columnar_compression.c +++ b/src/backend/columnar/columnar_compression.c @@ -18,11 +18,16 @@ #include "lib/stringinfo.h" #include "columnar/columnar_compression.h" +#include "distributed/pg_version_constants.h" #if HAVE_CITUS_LIBLZ4 #include #endif +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "varatt.h" +#endif + #if HAVE_LIBZSTD #include #endif diff --git a/src/backend/columnar/columnar_customscan.c b/src/backend/columnar/columnar_customscan.c index bd01c4faa..4ea96a121 100644 --- a/src/backend/columnar/columnar_customscan.c +++ b/src/backend/columnar/columnar_customscan.c @@ -33,6 +33,10 @@ #include "optimizer/paths.h" #include "optimizer/plancat.h" #include "optimizer/restrictinfo.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "parser/parse_relation.h" +#include "parser/parsetree.h" +#endif #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/relcache.h" @@ -127,6 +131,9 @@ static List * set_deparse_context_planstate(List *dpcontext, Node *node, /* other helpers */ static List * ColumnarVarNeeded(ColumnarScanState *columnarScanState); static Bitmapset * ColumnarAttrNeeded(ScanState *ss); +#if PG_VERSION_NUM >= PG_VERSION_16 +static Bitmapset * fixup_inherited_columns(Oid parentId, Oid childId, Bitmapset *columns); +#endif /* saved hook value in case of unload */ static set_rel_pathlist_hook_type PreviousSetRelPathlistHook = NULL; @@ -535,7 +542,7 @@ ColumnarIndexScanAdditionalCost(PlannerInfo *root, RelOptInfo *rel, * "anti-correlated" (-1) since both help us avoiding from reading the * same stripe again and again. */ - double absIndexCorrelation = Abs(indexCorrelation); + double absIndexCorrelation = float_abs(indexCorrelation); /* * To estimate the number of stripes that we need to read, we do linear @@ -654,7 +661,7 @@ CheckVarStats(PlannerInfo *root, Var *var, Oid sortop, float4 *absVarCorrelation * If the Var is not highly correlated, then the chunk's min/max bounds * will be nearly useless. */ - if (Abs(varCorrelation) < ColumnarQualPushdownCorrelationThreshold) + if (float_abs(varCorrelation) < ColumnarQualPushdownCorrelationThreshold) { if (absVarCorrelation) { @@ -662,7 +669,7 @@ CheckVarStats(PlannerInfo *root, Var *var, Oid sortop, float4 *absVarCorrelation * Report absVarCorrelation if caller wants to know why given * var is rejected. */ - *absVarCorrelation = Abs(varCorrelation); + *absVarCorrelation = float_abs(varCorrelation); } return false; } @@ -1371,7 +1378,43 @@ AddColumnarScanPath(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, cpath->custom_private = list_make2(NIL, NIL); } - int numberOfColumnsRead = bms_num_members(rte->selectedCols); + int numberOfColumnsRead = 0; +#if PG_VERSION_NUM >= PG_VERSION_16 + if (rte->perminfoindex > 0) + { + /* + * If perminfoindex > 0, that means that this relation's permission info + * is directly found in the list of rteperminfos of the Query(root->parse) + * So, all we have to do here is retrieve that info. + */ + RTEPermissionInfo *perminfo = getRTEPermissionInfo(root->parse->rteperminfos, + rte); + numberOfColumnsRead = bms_num_members(perminfo->selectedCols); + } + else + { + /* + * If perminfoindex = 0, that means we are skipping the check for permission info + * for this relation, which means that it's either a partition or an inheritance child. + * In these cases, we need to access the permission info of the top parent of this relation. + * After thorough checking, we found that the index of the top parent pointing to the correct + * range table entry in Query's range tables (root->parse->rtable) is found under + * RelOptInfo rel->top_parent->relid. + * For reference, check expand_partitioned_rtentry and expand_inherited_rtentry PG functions + */ + Assert(rel->top_parent); + RangeTblEntry *parent_rte = rt_fetch(rel->top_parent->relid, root->parse->rtable); + RTEPermissionInfo *perminfo = getRTEPermissionInfo(root->parse->rteperminfos, + parent_rte); + numberOfColumnsRead = bms_num_members(fixup_inherited_columns(perminfo->relid, + rte->relid, + perminfo-> + selectedCols)); + } +#else + numberOfColumnsRead = bms_num_members(rte->selectedCols); +#endif + int numberOfClausesPushed = list_length(allClauses); CostColumnarScan(root, rel, rte->relid, cpath, numberOfColumnsRead, @@ -1391,6 +1434,69 @@ AddColumnarScanPath(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, } +#if PG_VERSION_NUM >= PG_VERSION_16 + +/* + * fixup_inherited_columns + * + * Exact function Copied from PG16 as it's static. + * + * When user is querying on a table with children, it implicitly accesses + * child tables also. So, we also need to check security label of child + * tables and columns, but there is no guarantee attribute numbers are + * same between the parent and children. + * It returns a bitmapset which contains attribute number of the child + * table based on the given bitmapset of the parent. + */ +static Bitmapset * +fixup_inherited_columns(Oid parentId, Oid childId, Bitmapset *columns) +{ + Bitmapset *result = NULL; + + /* + * obviously, no need to do anything here + */ + if (parentId == childId) + { + return columns; + } + + int index = -1; + while ((index = bms_next_member(columns, index)) >= 0) + { + /* bit numbers are offset by FirstLowInvalidHeapAttributeNumber */ + AttrNumber attno = index + FirstLowInvalidHeapAttributeNumber; + + /* + * whole-row-reference shall be fixed-up later + */ + if (attno == InvalidAttrNumber) + { + result = bms_add_member(result, index); + continue; + } + + char *attname = get_attname(parentId, attno, false); + attno = get_attnum(childId, attname); + if (attno == InvalidAttrNumber) + { + elog(ERROR, "cache lookup failed for attribute %s of relation %u", + attname, childId); + } + + result = bms_add_member(result, + attno - FirstLowInvalidHeapAttributeNumber); + + pfree(attname); + } + + return result; +} + + +#endif + + /* * CostColumnarScan calculates the cost of scanning the columnar table. The * cost is estimated by using all stripe metadata to estimate based on the @@ -1435,7 +1541,8 @@ ColumnarPerStripeScanCost(RelOptInfo *rel, Oid relationId, int numberOfColumnsRe ereport(ERROR, (errmsg("could not open relation with OID %u", relationId))); } - List *stripeList = StripesForRelfilenode(relation->rd_node); + List *stripeList = StripesForRelfilelocator(RelationPhysicalIdentifier_compat( + relation)); RelationClose(relation); uint32 maxColumnCount = 0; @@ -1492,7 +1599,8 @@ ColumnarTableStripeCount(Oid relationId) ereport(ERROR, (errmsg("could not open relation with OID %u", relationId))); } - List *stripeList = StripesForRelfilenode(relation->rd_node); + List *stripeList = StripesForRelfilelocator(RelationPhysicalIdentifier_compat( + relation)); int stripeCount = list_length(stripeList); RelationClose(relation); diff --git a/src/backend/columnar/columnar_metadata.c b/src/backend/columnar/columnar_metadata.c index 5781b341e..e7a6bfa95 100644 --- a/src/backend/columnar/columnar_metadata.c +++ b/src/backend/columnar/columnar_metadata.c @@ -47,6 +47,9 @@ #include "miscadmin.h" #include "nodes/execnodes.h" #include "lib/stringinfo.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "parser/parse_relation.h" +#endif #include "port.h" #include "storage/fd.h" #include "storage/lmgr.h" @@ -57,7 +60,12 @@ #include "utils/memutils.h" #include "utils/lsyscache.h" #include "utils/rel.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "storage/relfilelocator.h" +#include "utils/relfilenumbermap.h" +#else #include "utils/relfilenodemap.h" +#endif #define COLUMNAR_RELOPTION_NAMESPACE "columnar" #define SLOW_METADATA_ACCESS_WARNING \ @@ -112,7 +120,7 @@ static Oid ColumnarChunkGroupRelationId(void); static Oid ColumnarChunkIndexRelationId(void); static Oid ColumnarChunkGroupIndexRelationId(void); static Oid ColumnarNamespaceId(void); -static uint64 LookupStorageId(RelFileNode relfilenode); +static uint64 LookupStorageId(RelFileLocator relfilelocator); static uint64 GetHighestUsedRowNumber(uint64 storageId); static void DeleteStorageFromColumnarMetadataTable(Oid metadataTableId, AttrNumber storageIdAtrrNumber, @@ -591,14 +599,15 @@ ReadColumnarOptions(Oid regclass, ColumnarOptions *options) * of columnar.chunk. */ void -SaveStripeSkipList(RelFileNode relfilenode, uint64 stripe, StripeSkipList *chunkList, +SaveStripeSkipList(RelFileLocator relfilelocator, uint64 stripe, + StripeSkipList *chunkList, TupleDesc tupleDescriptor) { uint32 columnIndex = 0; uint32 chunkIndex = 0; uint32 columnCount = chunkList->columnCount; - uint64 storageId = LookupStorageId(relfilenode); + uint64 storageId = LookupStorageId(relfilelocator); Oid columnarChunkOid = ColumnarChunkRelationId(); Relation columnarChunk = table_open(columnarChunkOid, RowExclusiveLock); ModifyState *modifyState = StartModifyRelation(columnarChunk); @@ -657,10 +666,10 @@ SaveStripeSkipList(RelFileNode relfilenode, uint64 stripe, StripeSkipList *chunk * SaveChunkGroups saves the metadata for given chunk groups in columnar.chunk_group. */ void -SaveChunkGroups(RelFileNode relfilenode, uint64 stripe, +SaveChunkGroups(RelFileLocator relfilelocator, uint64 stripe, List *chunkGroupRowCounts) { - uint64 storageId = LookupStorageId(relfilenode); + uint64 storageId = LookupStorageId(relfilelocator); Oid columnarChunkGroupOid = ColumnarChunkGroupRelationId(); Relation columnarChunkGroup = table_open(columnarChunkGroupOid, RowExclusiveLock); ModifyState *modifyState = StartModifyRelation(columnarChunkGroup); @@ -693,7 +702,8 @@ SaveChunkGroups(RelFileNode relfilenode, uint64 stripe, * ReadStripeSkipList fetches chunk metadata for a given stripe. */ StripeSkipList * -ReadStripeSkipList(RelFileNode relfilenode, uint64 stripe, TupleDesc tupleDescriptor, +ReadStripeSkipList(RelFileLocator relfilelocator, uint64 stripe, + TupleDesc tupleDescriptor, uint32 chunkCount, Snapshot snapshot) { int32 columnIndex = 0; @@ -701,7 +711,7 @@ ReadStripeSkipList(RelFileNode relfilenode, uint64 stripe, TupleDesc tupleDescri uint32 columnCount = tupleDescriptor->natts; ScanKeyData scanKey[2]; - uint64 storageId = LookupStorageId(relfilenode); + uint64 storageId = LookupStorageId(relfilelocator); Oid columnarChunkOid = ColumnarChunkRelationId(); Relation columnarChunk = table_open(columnarChunkOid, AccessShareLock); @@ -1235,13 +1245,13 @@ InsertEmptyStripeMetadataRow(uint64 storageId, uint64 stripeId, uint32 columnCou /* - * StripesForRelfilenode returns a list of StripeMetadata for stripes + * StripesForRelfilelocator returns a list of StripeMetadata for stripes * of the given relfilenode. */ List * -StripesForRelfilenode(RelFileNode relfilenode) +StripesForRelfilelocator(RelFileLocator relfilelocator) { - uint64 storageId = LookupStorageId(relfilenode); + uint64 storageId = LookupStorageId(relfilelocator); return ReadDataFileStripeList(storageId, GetTransactionSnapshot()); } @@ -1256,9 +1266,9 @@ StripesForRelfilenode(RelFileNode relfilenode) * returns 0. */ uint64 -GetHighestUsedAddress(RelFileNode relfilenode) +GetHighestUsedAddress(RelFileLocator relfilelocator) { - uint64 storageId = LookupStorageId(relfilenode); + uint64 storageId = LookupStorageId(relfilelocator); uint64 highestUsedAddress = 0; uint64 highestUsedId = 0; @@ -1539,7 +1549,7 @@ BuildStripeMetadata(Relation columnarStripes, HeapTuple heapTuple) * metadata tables. */ void -DeleteMetadataRows(RelFileNode relfilenode) +DeleteMetadataRows(RelFileLocator relfilelocator) { /* * During a restore for binary upgrade, metadata tables and indexes may or @@ -1550,7 +1560,7 @@ DeleteMetadataRows(RelFileNode relfilenode) return; } - uint64 storageId = LookupStorageId(relfilenode); + uint64 storageId = LookupStorageId(relfilelocator); DeleteStorageFromColumnarMetadataTable(ColumnarStripeRelationId(), Anum_columnar_stripe_storageid, @@ -1713,7 +1723,14 @@ create_estate_for_relation(Relation rel) rte->relid = RelationGetRelid(rel); rte->relkind = rel->rd_rel->relkind; rte->rellockmode = AccessShareLock; + +#if PG_VERSION_NUM >= PG_VERSION_16 + List *perminfos = NIL; + addRTEPermissionInfo(&perminfos, rte); + ExecInitRangeTable(estate, list_make1(rte), perminfos); +#else ExecInitRangeTable(estate, list_make1(rte)); +#endif estate->es_output_cid = GetCurrentCommandId(true); @@ -1917,10 +1934,11 @@ ColumnarNamespaceId(void) * false if the relation doesn't have a meta page yet. */ static uint64 -LookupStorageId(RelFileNode relfilenode) +LookupStorageId(RelFileLocator relfilelocator) { - Oid relationId = RelidByRelfilenode(relfilenode.spcNode, - relfilenode.relNode); + Oid relationId = RelidByRelfilenumber(RelationTablespace_compat(relfilelocator), + RelationPhysicalIdentifierNumber_compat( + relfilelocator)); Relation relation = relation_open(relationId, AccessShareLock); uint64 storageId = ColumnarStorageGetStorageId(relation, false); @@ -1951,7 +1969,7 @@ columnar_relation_storageid(PG_FUNCTION_ARGS) Oid relationId = PG_GETARG_OID(0); Relation relation = relation_open(relationId, AccessShareLock); - if (!pg_class_ownercheck(relationId, GetUserId())) + if (!object_ownercheck(RelationRelationId, relationId, GetUserId())) { aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLE, get_rel_name(relationId)); diff --git a/src/backend/columnar/columnar_reader.c b/src/backend/columnar/columnar_reader.c index 7917a446a..526dd03cb 100644 --- a/src/backend/columnar/columnar_reader.c +++ b/src/backend/columnar/columnar_reader.c @@ -254,8 +254,9 @@ ColumnarReadFlushPendingWrites(ColumnarReadState *readState) { Assert(!readState->snapshotRegisteredByUs); - Oid relfilenode = readState->relation->rd_node.relNode; - FlushWriteStateForRelfilenode(relfilenode, GetCurrentSubTransactionId()); + RelFileNumber relfilenumber = RelationPhysicalIdentifierNumber_compat( + RelationPhysicalIdentifier_compat(readState->relation)); + FlushWriteStateForRelfilenumber(relfilenumber, GetCurrentSubTransactionId()); if (readState->snapshot == InvalidSnapshot || !IsMVCCSnapshot(readState->snapshot)) { @@ -984,7 +985,8 @@ ColumnarTableRowCount(Relation relation) { ListCell *stripeMetadataCell = NULL; uint64 totalRowCount = 0; - List *stripeList = StripesForRelfilenode(relation->rd_node); + List *stripeList = StripesForRelfilelocator(RelationPhysicalIdentifier_compat( + relation)); foreach(stripeMetadataCell, stripeList) { @@ -1012,7 +1014,8 @@ LoadFilteredStripeBuffers(Relation relation, StripeMetadata *stripeMetadata, bool *projectedColumnMask = ProjectedColumnMask(columnCount, projectedColumnList); - StripeSkipList *stripeSkipList = ReadStripeSkipList(relation->rd_node, + StripeSkipList *stripeSkipList = ReadStripeSkipList(RelationPhysicalIdentifier_compat( + relation), stripeMetadata->id, tupleDescriptor, stripeMetadata->chunkCount, diff --git a/src/backend/columnar/columnar_storage.c b/src/backend/columnar/columnar_storage.c index 9712e7160..7e7f7990b 100644 --- a/src/backend/columnar/columnar_storage.c +++ b/src/backend/columnar/columnar_storage.c @@ -188,7 +188,7 @@ ColumnarStorageInit(SMgrRelation srel, uint64 storageId) (char *) &metapage, sizeof(ColumnarMetapage)); phdr->pd_lower += sizeof(ColumnarMetapage); - log_newpage(&srel->smgr_rnode.node, MAIN_FORKNUM, + log_newpage(RelationPhysicalIdentifierBackend_compat(&srel), MAIN_FORKNUM, COLUMNAR_METAPAGE_BLOCKNO, page, true); PageSetChecksumInplace(page, COLUMNAR_METAPAGE_BLOCKNO); smgrextend(srel, MAIN_FORKNUM, COLUMNAR_METAPAGE_BLOCKNO, page, true); @@ -196,7 +196,7 @@ ColumnarStorageInit(SMgrRelation srel, uint64 storageId) /* write empty page */ PageInit(page, BLCKSZ, 0); - log_newpage(&srel->smgr_rnode.node, MAIN_FORKNUM, + log_newpage(RelationPhysicalIdentifierBackend_compat(&srel), MAIN_FORKNUM, COLUMNAR_EMPTY_BLOCKNO, page, true); PageSetChecksumInplace(page, COLUMNAR_EMPTY_BLOCKNO); smgrextend(srel, MAIN_FORKNUM, COLUMNAR_EMPTY_BLOCKNO, page, true); diff --git a/src/backend/columnar/columnar_tableam.c b/src/backend/columnar/columnar_tableam.c index 4a08feb54..dade931df 100644 --- a/src/backend/columnar/columnar_tableam.c +++ b/src/backend/columnar/columnar_tableam.c @@ -31,6 +31,7 @@ #include "executor/executor.h" #include "nodes/makefuncs.h" #include "optimizer/plancat.h" +#include "pg_version_compat.h" #include "pgstat.h" #include "safe_lib.h" #include "storage/bufmgr.h" @@ -206,7 +207,8 @@ columnar_beginscan_extended(Relation relation, Snapshot snapshot, uint32 flags, Bitmapset *attr_needed, List *scanQual) { CheckCitusColumnarVersion(ERROR); - Oid relfilenode = relation->rd_node.relNode; + RelFileNumber relfilenumber = RelationPhysicalIdentifierNumber_compat( + RelationPhysicalIdentifier_compat(relation)); /* * A memory context to use for scan-wide data, including the lazily @@ -236,7 +238,7 @@ columnar_beginscan_extended(Relation relation, Snapshot snapshot, scan->scanQual = copyObject(scanQual); scan->scanContext = scanContext; - if (PendingWritesInUpperTransactions(relfilenode, GetCurrentSubTransactionId())) + if (PendingWritesInUpperTransactions(relfilenumber, GetCurrentSubTransactionId())) { elog(ERROR, "cannot read from table when there is unflushed data in upper transactions"); @@ -432,8 +434,9 @@ columnar_index_fetch_begin(Relation rel) { CheckCitusColumnarVersion(ERROR); - Oid relfilenode = rel->rd_node.relNode; - if (PendingWritesInUpperTransactions(relfilenode, GetCurrentSubTransactionId())) + RelFileNumber relfilenumber = RelationPhysicalIdentifierNumber_compat( + RelationPhysicalIdentifier_compat(rel)); + if (PendingWritesInUpperTransactions(relfilenumber, GetCurrentSubTransactionId())) { /* XXX: maybe we can just flush the data and continue */ elog(ERROR, "cannot read from index when there is unflushed data in " @@ -815,7 +818,7 @@ static TM_Result columnar_tuple_update(Relation relation, ItemPointer otid, TupleTableSlot *slot, CommandId cid, Snapshot snapshot, Snapshot crosscheck, bool wait, TM_FailureData *tmfd, - LockTupleMode *lockmode, bool *update_indexes) + LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) { elog(ERROR, "columnar_tuple_update not implemented"); } @@ -841,11 +844,11 @@ columnar_finish_bulk_insert(Relation relation, int options) static void -columnar_relation_set_new_filenode(Relation rel, - const RelFileNode *newrnode, - char persistence, - TransactionId *freezeXid, - MultiXactId *minmulti) +columnar_relation_set_new_filelocator(Relation rel, + const RelFileLocator *newrlocator, + char persistence, + TransactionId *freezeXid, + MultiXactId *minmulti) { CheckCitusColumnarVersion(ERROR); @@ -861,16 +864,19 @@ columnar_relation_set_new_filenode(Relation rel, * state. If they are equal, this is a new relation object and we don't * need to clean anything. */ - if (rel->rd_node.relNode != newrnode->relNode) + if (RelationPhysicalIdentifierNumber_compat(RelationPhysicalIdentifier_compat(rel)) != + RelationPhysicalIdentifierNumberPtr_compat(newrlocator)) { - MarkRelfilenodeDropped(rel->rd_node.relNode, GetCurrentSubTransactionId()); + MarkRelfilenumberDropped(RelationPhysicalIdentifierNumber_compat( + RelationPhysicalIdentifier_compat(rel)), + GetCurrentSubTransactionId()); - DeleteMetadataRows(rel->rd_node); + DeleteMetadataRows(RelationPhysicalIdentifier_compat(rel)); } *freezeXid = RecentXmin; *minmulti = GetOldestMultiXactId(); - SMgrRelation srel = RelationCreateStorage_compat(*newrnode, persistence, true); + SMgrRelation srel = RelationCreateStorage_compat(*newrlocator, persistence, true); ColumnarStorageInit(srel, ColumnarMetadataNewStorageId()); InitColumnarOptions(rel->rd_id); @@ -885,12 +891,12 @@ static void columnar_relation_nontransactional_truncate(Relation rel) { CheckCitusColumnarVersion(ERROR); - RelFileNode relfilenode = rel->rd_node; + RelFileLocator relfilelocator = RelationPhysicalIdentifier_compat(rel); - NonTransactionDropWriteState(relfilenode.relNode); + NonTransactionDropWriteState(RelationPhysicalIdentifierNumber_compat(relfilelocator)); /* Delete old relfilenode metadata */ - DeleteMetadataRows(relfilenode); + DeleteMetadataRows(relfilelocator); /* * No need to set new relfilenode, since the table was created in this @@ -907,7 +913,7 @@ columnar_relation_nontransactional_truncate(Relation rel) static void -columnar_relation_copy_data(Relation rel, const RelFileNode *newrnode) +columnar_relation_copy_data(Relation rel, const RelFileLocator *newrnode) { elog(ERROR, "columnar_relation_copy_data not implemented"); } @@ -953,7 +959,8 @@ columnar_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap, ColumnarOptions columnarOptions = { 0 }; ReadColumnarOptions(OldHeap->rd_id, &columnarOptions); - ColumnarWriteState *writeState = ColumnarBeginWrite(NewHeap->rd_node, + ColumnarWriteState *writeState = ColumnarBeginWrite(RelationPhysicalIdentifier_compat( + NewHeap), columnarOptions, targetDesc); @@ -1028,7 +1035,8 @@ NeededColumnsList(TupleDesc tupdesc, Bitmapset *attr_needed) static uint64 ColumnarTableTupleCount(Relation relation) { - List *stripeList = StripesForRelfilenode(relation->rd_node); + List *stripeList = StripesForRelfilelocator(RelationPhysicalIdentifier_compat( + relation)); uint64 tupleCount = 0; ListCell *lc = NULL; @@ -1091,12 +1099,38 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params, List *indexList = RelationGetIndexList(rel); int nindexes = list_length(indexList); +#if PG_VERSION_NUM >= PG_VERSION_16 + struct VacuumCutoffs cutoffs; + vacuum_get_cutoffs(rel, params, &cutoffs); + + Assert(MultiXactIdPrecedesOrEquals(cutoffs.MultiXactCutoff, cutoffs.OldestMxact)); + Assert(TransactionIdPrecedesOrEquals(cutoffs.FreezeLimit, cutoffs.OldestXmin)); + + /* + * Columnar storage doesn't hold any transaction IDs, so we can always + * just advance to the most aggressive value. + */ + TransactionId newRelFrozenXid = cutoffs.OldestXmin; + MultiXactId newRelminMxid = cutoffs.OldestMxact; + double new_live_tuples = ColumnarTableTupleCount(rel); + + /* all visible pages are always 0 */ + BlockNumber new_rel_allvisible = 0; + + bool frozenxid_updated; + bool minmulti_updated; + + vac_update_relstats(rel, new_rel_pages, new_live_tuples, + new_rel_allvisible, nindexes > 0, + newRelFrozenXid, newRelminMxid, + &frozenxid_updated, &minmulti_updated, false); +#else TransactionId oldestXmin; TransactionId freezeLimit; MultiXactId multiXactCutoff; /* initialize xids */ -#if PG_VERSION_NUM >= PG_VERSION_15 +#if (PG_VERSION_NUM >= PG_VERSION_15) && (PG_VERSION_NUM < PG_VERSION_16) MultiXactId oldestMxact; vacuum_set_xid_limits(rel, params->freeze_min_age, @@ -1126,7 +1160,7 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params, * just advance to the most aggressive value. */ TransactionId newRelFrozenXid = oldestXmin; -#if PG_VERSION_NUM >= PG_VERSION_15 +#if (PG_VERSION_NUM >= PG_VERSION_15) && (PG_VERSION_NUM < PG_VERSION_16) MultiXactId newRelminMxid = oldestMxact; #else MultiXactId newRelminMxid = multiXactCutoff; @@ -1137,7 +1171,7 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params, /* all visible pages are always 0 */ BlockNumber new_rel_allvisible = 0; -#if PG_VERSION_NUM >= PG_VERSION_15 +#if (PG_VERSION_NUM >= PG_VERSION_15) && (PG_VERSION_NUM < PG_VERSION_16) bool frozenxid_updated; bool minmulti_updated; @@ -1149,6 +1183,7 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params, vac_update_relstats(rel, new_rel_pages, new_live_tuples, new_rel_allvisible, nindexes > 0, newRelFrozenXid, newRelminMxid, false); +#endif #endif pgstat_report_vacuum(RelationGetRelid(rel), @@ -1166,7 +1201,7 @@ static void LogRelationStats(Relation rel, int elevel) { ListCell *stripeMetadataCell = NULL; - RelFileNode relfilenode = rel->rd_node; + RelFileLocator relfilelocator = RelationPhysicalIdentifier_compat(rel); StringInfo infoBuf = makeStringInfo(); int compressionStats[COMPRESSION_COUNT] = { 0 }; @@ -1177,13 +1212,13 @@ LogRelationStats(Relation rel, int elevel) uint64 droppedChunksWithData = 0; uint64 totalDecompressedLength = 0; - List *stripeList = StripesForRelfilenode(relfilenode); + List *stripeList = StripesForRelfilelocator(relfilelocator); int stripeCount = list_length(stripeList); foreach(stripeMetadataCell, stripeList) { StripeMetadata *stripe = lfirst(stripeMetadataCell); - StripeSkipList *skiplist = ReadStripeSkipList(relfilenode, stripe->id, + StripeSkipList *skiplist = ReadStripeSkipList(relfilelocator, stripe->id, RelationGetDescr(rel), stripe->chunkCount, GetTransactionSnapshot()); @@ -1319,7 +1354,8 @@ TruncateColumnar(Relation rel, int elevel) * new stripes be added beyond highestPhysicalAddress while * we're truncating. */ - uint64 newDataReservation = Max(GetHighestUsedAddress(rel->rd_node) + 1, + uint64 newDataReservation = Max(GetHighestUsedAddress( + RelationPhysicalIdentifier_compat(rel)) + 1, ColumnarFirstLogicalOffset); BlockNumber old_rel_pages = smgrnblocks(RelationGetSmgr(rel), MAIN_FORKNUM); @@ -1826,8 +1862,8 @@ TupleSortSkipSmallerItemPointers(Tuplesortstate *tupleSort, ItemPointer targetIt Datum *abbrev = NULL; Datum tsDatum; bool tsDatumIsNull; - if (!tuplesort_getdatum(tupleSort, forwardDirection, &tsDatum, - &tsDatumIsNull, abbrev)) + if (!tuplesort_getdatum_compat(tupleSort, forwardDirection, false, + &tsDatum, &tsDatumIsNull, abbrev)) { ItemPointerSetInvalid(&tsItemPointerData); break; @@ -2068,12 +2104,13 @@ ColumnarTableDropHook(Oid relid) * tableam tables storage is managed by postgres. */ Relation rel = table_open(relid, AccessExclusiveLock); - RelFileNode relfilenode = rel->rd_node; + RelFileLocator relfilelocator = RelationPhysicalIdentifier_compat(rel); - DeleteMetadataRows(relfilenode); + DeleteMetadataRows(relfilelocator); DeleteColumnarTableOptions(rel->rd_id, true); - MarkRelfilenodeDropped(relfilenode.relNode, GetCurrentSubTransactionId()); + MarkRelfilenumberDropped(RelationPhysicalIdentifierNumber_compat(relfilelocator), + GetCurrentSubTransactionId()); /* keep the lock since we did physical changes to the relation */ table_close(rel, NoLock); @@ -2490,7 +2527,11 @@ static const TableAmRoutine columnar_am_methods = { .tuple_lock = columnar_tuple_lock, .finish_bulk_insert = columnar_finish_bulk_insert, - .relation_set_new_filenode = columnar_relation_set_new_filenode, +#if PG_VERSION_NUM >= PG_VERSION_16 + .relation_set_new_filelocator = columnar_relation_set_new_filelocator, +#else + .relation_set_new_filenode = columnar_relation_set_new_filelocator, +#endif .relation_nontransactional_truncate = columnar_relation_nontransactional_truncate, .relation_copy_data = columnar_relation_copy_data, .relation_copy_for_cluster = columnar_relation_copy_for_cluster, diff --git a/src/backend/columnar/columnar_writer.c b/src/backend/columnar/columnar_writer.c index 8e35b59b1..3b510ce74 100644 --- a/src/backend/columnar/columnar_writer.c +++ b/src/backend/columnar/columnar_writer.c @@ -22,12 +22,18 @@ #include "access/nbtree.h" #include "catalog/pg_am.h" #include "miscadmin.h" +#include "pg_version_compat.h" #include "storage/fd.h" #include "storage/smgr.h" #include "utils/guc.h" #include "utils/memutils.h" #include "utils/rel.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "storage/relfilelocator.h" +#include "utils/relfilenumbermap.h" +#else #include "utils/relfilenodemap.h" +#endif #include "columnar/columnar.h" #include "columnar/columnar_storage.h" @@ -37,7 +43,7 @@ struct ColumnarWriteState { TupleDesc tupleDescriptor; FmgrInfo **comparisonFunctionArray; - RelFileNode relfilenode; + RelFileLocator relfilelocator; MemoryContext stripeWriteContext; MemoryContext perTupleContext; @@ -84,7 +90,7 @@ static StringInfo CopyStringInfo(StringInfo sourceString); * data load operation. */ ColumnarWriteState * -ColumnarBeginWrite(RelFileNode relfilenode, +ColumnarBeginWrite(RelFileLocator relfilelocator, ColumnarOptions options, TupleDesc tupleDescriptor) { @@ -124,7 +130,7 @@ ColumnarBeginWrite(RelFileNode relfilenode, options.chunkRowCount); ColumnarWriteState *writeState = palloc0(sizeof(ColumnarWriteState)); - writeState->relfilenode = relfilenode; + writeState->relfilelocator = relfilelocator; writeState->options = options; writeState->tupleDescriptor = CreateTupleDescCopy(tupleDescriptor); writeState->comparisonFunctionArray = comparisonFunctionArray; @@ -174,8 +180,10 @@ ColumnarWriteRow(ColumnarWriteState *writeState, Datum *columnValues, bool *colu writeState->stripeSkipList = stripeSkipList; writeState->compressionBuffer = makeStringInfo(); - Oid relationId = RelidByRelfilenode(writeState->relfilenode.spcNode, - writeState->relfilenode.relNode); + Oid relationId = RelidByRelfilenumber(RelationTablespace_compat( + writeState->relfilelocator), + RelationPhysicalIdentifierNumber_compat( + writeState->relfilelocator)); Relation relation = relation_open(relationId, NoLock); writeState->emptyStripeReservation = ReserveEmptyStripe(relation, columnCount, chunkRowCount, @@ -393,8 +401,10 @@ FlushStripe(ColumnarWriteState *writeState) elog(DEBUG1, "Flushing Stripe of size %d", stripeBuffers->rowCount); - Oid relationId = RelidByRelfilenode(writeState->relfilenode.spcNode, - writeState->relfilenode.relNode); + Oid relationId = RelidByRelfilenumber(RelationTablespace_compat( + writeState->relfilelocator), + RelationPhysicalIdentifierNumber_compat( + writeState->relfilelocator)); Relation relation = relation_open(relationId, NoLock); /* @@ -486,10 +496,10 @@ FlushStripe(ColumnarWriteState *writeState) } } - SaveChunkGroups(writeState->relfilenode, + SaveChunkGroups(writeState->relfilelocator, stripeMetadata->id, writeState->chunkGroupRowCounts); - SaveStripeSkipList(writeState->relfilenode, + SaveStripeSkipList(writeState->relfilelocator, stripeMetadata->id, stripeSkipList, tupleDescriptor); diff --git a/src/backend/columnar/write_state_management.c b/src/backend/columnar/write_state_management.c index e3bfc9260..27d902e61 100644 --- a/src/backend/columnar/write_state_management.c +++ b/src/backend/columnar/write_state_management.c @@ -29,6 +29,7 @@ #include "executor/executor.h" #include "nodes/makefuncs.h" #include "optimizer/plancat.h" +#include "pg_version_compat.h" #include "pgstat.h" #include "storage/bufmgr.h" #include "storage/bufpage.h" @@ -77,7 +78,7 @@ typedef struct SubXidWriteState typedef struct WriteStateMapEntry { /* key of the entry */ - Oid relfilenode; + RelFileNumber relfilenumber; /* * If a table is dropped, we set dropped to true and set dropSubXid to the @@ -132,7 +133,7 @@ columnar_init_write_state(Relation relation, TupleDesc tupdesc, HASHCTL info; uint32 hashFlags = (HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); memset(&info, 0, sizeof(info)); - info.keysize = sizeof(Oid); + info.keysize = sizeof(RelFileNumber); info.hash = oid_hash; info.entrysize = sizeof(WriteStateMapEntry); info.hcxt = WriteStateContext; @@ -146,7 +147,10 @@ columnar_init_write_state(Relation relation, TupleDesc tupdesc, MemoryContextRegisterResetCallback(WriteStateContext, &cleanupCallback); } - WriteStateMapEntry *hashEntry = hash_search(WriteStateMap, &relation->rd_node.relNode, + WriteStateMapEntry *hashEntry = hash_search(WriteStateMap, + &RelationPhysicalIdentifierNumber_compat( + RelationPhysicalIdentifier_compat( + relation)), HASH_ENTER, &found); if (!found) { @@ -189,7 +193,8 @@ columnar_init_write_state(Relation relation, TupleDesc tupdesc, ReadColumnarOptions(tupSlotRelationId, &columnarOptions); SubXidWriteState *stackEntry = palloc0(sizeof(SubXidWriteState)); - stackEntry->writeState = ColumnarBeginWrite(relation->rd_node, + stackEntry->writeState = ColumnarBeginWrite(RelationPhysicalIdentifier_compat( + relation), columnarOptions, tupdesc); stackEntry->subXid = currentSubXid; @@ -206,14 +211,16 @@ columnar_init_write_state(Relation relation, TupleDesc tupdesc, * Flushes pending writes for given relfilenode in the given subtransaction. */ void -FlushWriteStateForRelfilenode(Oid relfilenode, SubTransactionId currentSubXid) +FlushWriteStateForRelfilenumber(RelFileNumber relfilenumber, + SubTransactionId currentSubXid) { if (WriteStateMap == NULL) { return; } - WriteStateMapEntry *entry = hash_search(WriteStateMap, &relfilenode, HASH_FIND, NULL); + WriteStateMapEntry *entry = hash_search(WriteStateMap, &relfilenumber, HASH_FIND, + NULL); Assert(!entry || !entry->dropped); @@ -320,14 +327,14 @@ DiscardWriteStateForAllRels(SubTransactionId currentSubXid, SubTransactionId par * Called when the given relfilenode is dropped. */ void -MarkRelfilenodeDropped(Oid relfilenode, SubTransactionId currentSubXid) +MarkRelfilenumberDropped(RelFileNumber relfilenumber, SubTransactionId currentSubXid) { if (WriteStateMap == NULL) { return; } - WriteStateMapEntry *entry = hash_search(WriteStateMap, &relfilenode, HASH_FIND, + WriteStateMapEntry *entry = hash_search(WriteStateMap, &relfilenumber, HASH_FIND, NULL); if (!entry || entry->dropped) { @@ -343,11 +350,11 @@ MarkRelfilenodeDropped(Oid relfilenode, SubTransactionId currentSubXid) * Called when the given relfilenode is dropped in non-transactional TRUNCATE. */ void -NonTransactionDropWriteState(Oid relfilenode) +NonTransactionDropWriteState(RelFileNumber relfilenumber) { if (WriteStateMap) { - hash_search(WriteStateMap, &relfilenode, HASH_REMOVE, false); + hash_search(WriteStateMap, &relfilenumber, HASH_REMOVE, false); } } @@ -356,14 +363,16 @@ NonTransactionDropWriteState(Oid relfilenode) * Returns true if there are any pending writes in upper transactions. */ bool -PendingWritesInUpperTransactions(Oid relfilenode, SubTransactionId currentSubXid) +PendingWritesInUpperTransactions(RelFileNumber relfilenumber, + SubTransactionId currentSubXid) { if (WriteStateMap == NULL) { return false; } - WriteStateMapEntry *entry = hash_search(WriteStateMap, &relfilenode, HASH_FIND, NULL); + WriteStateMapEntry *entry = hash_search(WriteStateMap, &relfilenumber, HASH_FIND, + NULL); if (entry && entry->writeStateStack != NULL) { diff --git a/src/backend/distributed/commands/domain.c b/src/backend/distributed/commands/domain.c index 392cbd6e2..82ef80c0f 100644 --- a/src/backend/distributed/commands/domain.c +++ b/src/backend/distributed/commands/domain.c @@ -64,7 +64,8 @@ CreateDomainStmt * RecreateDomainStmt(Oid domainOid) { CreateDomainStmt *stmt = makeNode(CreateDomainStmt); - stmt->domainname = stringToQualifiedNameList(format_type_be_qualified(domainOid)); + stmt->domainname = stringToQualifiedNameList_compat(format_type_be_qualified( + domainOid)); HeapTuple tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(domainOid)); if (!HeapTupleIsValid(tup)) diff --git a/src/backend/distributed/commands/index.c b/src/backend/distributed/commands/index.c index aa0715372..ae0a939a5 100644 --- a/src/backend/distributed/commands/index.c +++ b/src/backend/distributed/commands/index.c @@ -18,6 +18,9 @@ #include "catalog/index.h" #include "catalog/namespace.h" #include "catalog/pg_class.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "catalog/pg_namespace.h" +#endif #include "commands/defrem.h" #include "commands/tablecmds.h" #include "distributed/citus_ruleutils.h" @@ -558,7 +561,7 @@ ReindexStmtFindRelationOid(ReindexStmt *reindexStmt, bool missingOk) { relationId = RangeVarGetRelidExtended(reindexStmt->relation, lockmode, (missingOk) ? RVR_MISSING_OK : 0, - RangeVarCallbackOwnsTable, NULL); + RANGE_VAR_TABLE_CALLBACK, NULL); } return relationId; @@ -1055,8 +1058,8 @@ RangeVarCallbackForDropIndex(const RangeVar *rel, Oid relOid, Oid oldRelOid, voi errmsg("\"%s\" is not an index", rel->relname))); /* Allow DROP to either table owner or schema owner */ - if (!pg_class_ownercheck(relOid, GetUserId()) && - !pg_namespace_ownercheck(classform->relnamespace, GetUserId())) + if (!object_ownercheck(RelationRelationId, relOid, GetUserId()) && + !object_ownercheck(NamespaceRelationId, classform->relnamespace, GetUserId())) { aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_INDEX, rel->relname); } @@ -1140,7 +1143,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelI errmsg("\"%s\" is not an index", relation->relname))); /* Check permissions */ - if (!pg_class_ownercheck(relId, GetUserId())) + if (!object_ownercheck(RelationRelationId, relId, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_INDEX, relation->relname); /* Lock heap before index to avoid deadlock. */ diff --git a/src/backend/distributed/commands/multi_copy.c b/src/backend/distributed/commands/multi_copy.c index 5d7c279a6..eeed0a025 100644 --- a/src/backend/distributed/commands/multi_copy.c +++ b/src/backend/distributed/commands/multi_copy.c @@ -83,6 +83,9 @@ #include "distributed/locally_reserved_shared_connections.h" #include "distributed/placement_connection.h" #include "distributed/relation_access_tracking.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "distributed/relation_utils.h" +#endif #include "distributed/remote_commands.h" #include "distributed/remote_transaction.h" #include "distributed/replication_origin_session_utils.h" @@ -3149,10 +3152,17 @@ CheckCopyPermissions(CopyStmt *copyStatement) rel = table_openrv(copyStatement->relation, is_from ? RowExclusiveLock : AccessShareLock); - range_table = CreateRangeTable(rel, required_access); + range_table = CreateRangeTable(rel); RangeTblEntry *rte = (RangeTblEntry*) linitial(range_table); tupDesc = RelationGetDescr(rel); +#if PG_VERSION_NUM >= PG_VERSION_16 + /* create permission info for rte */ + RTEPermissionInfo *perminfo = GetFilledPermissionInfo(rel->rd_id, rte->inh, required_access); +#else + rte->requiredPerms = required_access; +#endif + attnums = CopyGetAttnums(tupDesc, rel, copyStatement->attlist); foreach(cur, attnums) { @@ -3160,15 +3170,29 @@ CheckCopyPermissions(CopyStmt *copyStatement) if (is_from) { +#if PG_VERSION_NUM >= PG_VERSION_16 + perminfo->insertedCols = bms_add_member(perminfo->insertedCols, attno); +#else rte->insertedCols = bms_add_member(rte->insertedCols, attno); +#endif } else { +#if PG_VERSION_NUM >= PG_VERSION_16 + perminfo->selectedCols = bms_add_member(perminfo->selectedCols, attno); +#else rte->selectedCols = bms_add_member(rte->selectedCols, attno); +#endif } } +#if PG_VERSION_NUM >= PG_VERSION_16 + /* link rte to its permission info then check permissions */ + rte->perminfoindex = 1; + ExecCheckPermissions(list_make1(rte), list_make1(perminfo), true); +#else ExecCheckRTPerms(range_table, true); +#endif /* TODO: Perform RLS checks once supported */ @@ -3181,13 +3205,12 @@ CheckCopyPermissions(CopyStmt *copyStatement) * CreateRangeTable creates a range table with the given relation. */ List * -CreateRangeTable(Relation rel, AclMode requiredAccess) +CreateRangeTable(Relation rel) { RangeTblEntry *rte = makeNode(RangeTblEntry); rte->rtekind = RTE_RELATION; rte->relid = rel->rd_id; rte->relkind = rel->rd_rel->relkind; - rte->requiredPerms = requiredAccess; return list_make1(rte); } diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index 4c21b2f43..4e274d270 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -703,12 +703,13 @@ MakeSetStatementArguments(char *configurationName, char *configurationValue) * is no other way to determine allowed units, and value types other than * using this function */ - struct config_generic **gucVariables = get_guc_variables(); - int numOpts = GetNumConfigOptions(); + int gucCount = 0; + struct config_generic **gucVariables = get_guc_variables_compat(&gucCount); + struct config_generic **matchingConfig = (struct config_generic **) SafeBsearch((void *) &key, (void *) gucVariables, - numOpts, + gucCount, sizeof(struct config_generic *), ConfigGenericNameCompare); @@ -818,10 +819,12 @@ GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options) grantRoleStmt->grantee_roles = list_make1(roleSpec); } +#if PG_VERSION_NUM < PG_VERSION_16 if (strcmp(option->defname, "adminmembers") == 0) { grantRoleStmt->admin_opt = true; } +#endif stmts = lappend(stmts, grantRoleStmt); } @@ -868,7 +871,9 @@ GenerateGrantRoleStmtsOfRole(Oid roleid) grantRoleStmt->grantor = NULL; +#if PG_VERSION_NUM < PG_VERSION_16 grantRoleStmt->admin_opt = membership->admin_option; +#endif stmts = lappend(stmts, grantRoleStmt); } diff --git a/src/backend/distributed/commands/truncate.c b/src/backend/distributed/commands/truncate.c index 70fee6bd5..4de518a06 100644 --- a/src/backend/distributed/commands/truncate.c +++ b/src/backend/distributed/commands/truncate.c @@ -182,7 +182,7 @@ truncate_local_data_after_distributing_table(PG_FUNCTION_ARGS) TruncateStmt *truncateStmt = makeNode(TruncateStmt); char *relationName = generate_qualified_relation_name(relationId); - List *names = stringToQualifiedNameList(relationName); + List *names = stringToQualifiedNameList_compat(relationName); truncateStmt->relations = list_make1(makeRangeVarFromNameList(names)); truncateStmt->restart_seqs = false; truncateStmt->behavior = DROP_CASCADE; diff --git a/src/backend/distributed/commands/type.c b/src/backend/distributed/commands/type.c index 24ca91aeb..02e5f0dee 100644 --- a/src/backend/distributed/commands/type.c +++ b/src/backend/distributed/commands/type.c @@ -187,7 +187,7 @@ RecreateCompositeTypeStmt(Oid typeOid) Assert(get_typtype(typeOid) == TYPTYPE_COMPOSITE); CompositeTypeStmt *stmt = makeNode(CompositeTypeStmt); - List *names = stringToQualifiedNameList(format_type_be_qualified(typeOid)); + List *names = stringToQualifiedNameList_compat(format_type_be_qualified(typeOid)); stmt->typevar = makeRangeVarFromNameList(names); stmt->coldeflist = CompositeTypeColumnDefList(typeOid); @@ -252,7 +252,7 @@ RecreateEnumStmt(Oid typeOid) Assert(get_typtype(typeOid) == TYPTYPE_ENUM); CreateEnumStmt *stmt = makeNode(CreateEnumStmt); - stmt->typeName = stringToQualifiedNameList(format_type_be_qualified(typeOid)); + stmt->typeName = stringToQualifiedNameList_compat(format_type_be_qualified(typeOid)); stmt->vals = EnumValsList(typeOid); return stmt; @@ -565,7 +565,8 @@ CreateTypeDDLCommandsIdempotent(const ObjectAddress *typeAddress) char * GenerateBackupNameForTypeCollision(const ObjectAddress *address) { - List *names = stringToQualifiedNameList(format_type_be_qualified(address->objectId)); + List *names = stringToQualifiedNameList_compat(format_type_be_qualified( + address->objectId)); RangeVar *rel = makeRangeVarFromNameList(names); char *newName = palloc0(NAMEDATALEN); diff --git a/src/backend/distributed/deparser/deparse_role_stmts.c b/src/backend/distributed/deparser/deparse_role_stmts.c index 0e9b300bb..620e7606d 100644 --- a/src/backend/distributed/deparser/deparse_role_stmts.c +++ b/src/backend/distributed/deparser/deparse_role_stmts.c @@ -349,10 +349,12 @@ AppendGrantRoleStmt(StringInfo buf, GrantRoleStmt *stmt) { appendStringInfo(buf, "%s ", stmt->is_grant ? "GRANT" : "REVOKE"); +#if PG_VERSION_NUM < PG_VERSION_16 if (!stmt->is_grant && stmt->admin_opt) { appendStringInfo(buf, "ADMIN OPTION FOR "); } +#endif AppendRoleList(buf, stmt->granted_roles); @@ -362,10 +364,12 @@ AppendGrantRoleStmt(StringInfo buf, GrantRoleStmt *stmt) if (stmt->is_grant) { +#if PG_VERSION_NUM < PG_VERSION_16 if (stmt->admin_opt) { appendStringInfo(buf, " WITH ADMIN OPTION"); } +#endif if (stmt->grantor) { diff --git a/src/backend/distributed/metadata/metadata_cache.c b/src/backend/distributed/metadata/metadata_cache.c index 3f0460ca8..d4aea5f90 100644 --- a/src/backend/distributed/metadata/metadata_cache.c +++ b/src/backend/distributed/metadata/metadata_cache.c @@ -83,7 +83,9 @@ #include "utils/memutils.h" #include "utils/palloc.h" #include "utils/rel.h" +#if PG_VERSION_NUM < PG_VERSION_16 #include "utils/relfilenodemap.h" +#endif #include "utils/relmapper.h" #include "utils/resowner.h" #include "utils/syscache.h" diff --git a/src/backend/distributed/metadata/metadata_utility.c b/src/backend/distributed/metadata/metadata_utility.c index 9d3c236c5..afe49b1ab 100644 --- a/src/backend/distributed/metadata/metadata_utility.c +++ b/src/backend/distributed/metadata/metadata_utility.c @@ -29,6 +29,9 @@ #include "catalog/pg_constraint.h" #include "catalog/pg_extension.h" #include "catalog/pg_namespace.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "catalog/pg_proc_d.h" +#endif #include "catalog/pg_type.h" #include "commands/extension.h" #include "commands/sequence.h" @@ -2263,7 +2266,7 @@ EnsureTablePermissions(Oid relationId, AclMode mode) void EnsureTableOwner(Oid relationId) { - if (!pg_class_ownercheck(relationId, GetUserId())) + if (!object_ownercheck(RelationRelationId, relationId, GetUserId())) { aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLE, get_rel_name(relationId)); @@ -2278,7 +2281,7 @@ EnsureTableOwner(Oid relationId) void EnsureSchemaOwner(Oid schemaId) { - if (!pg_namespace_ownercheck(schemaId, GetUserId())) + if (!object_ownercheck(NamespaceRelationId, schemaId, GetUserId())) { aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA, get_namespace_name(schemaId)); @@ -2294,7 +2297,7 @@ EnsureSchemaOwner(Oid schemaId) void EnsureFunctionOwner(Oid functionId) { - if (!pg_proc_ownercheck(functionId, GetUserId())) + if (!object_ownercheck(ProcedureRelationId, functionId, GetUserId())) { aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, get_func_name(functionId)); diff --git a/src/backend/distributed/metadata/pg_get_object_address_13_14_15.c b/src/backend/distributed/metadata/pg_get_object_address_13_14_15.c index bcd74fbbc..54f764fc1 100644 --- a/src/backend/distributed/metadata/pg_get_object_address_13_14_15.c +++ b/src/backend/distributed/metadata/pg_get_object_address_13_14_15.c @@ -93,7 +93,7 @@ PgGetObjectAddress(char *ttype, ArrayType *namearr, ArrayType *argsarr) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("name or argument lists may not contain nulls"))); } - typename = typeStringToTypeName(TextDatumGetCString(elems[0])); + typename = typeStringToTypeName_compat(TextDatumGetCString(elems[0]), NULL); } else if (type == OBJECT_LARGEOBJECT) { @@ -160,7 +160,8 @@ PgGetObjectAddress(char *ttype, ArrayType *namearr, ArrayType *argsarr) errmsg("name or argument lists may not contain nulls"))); } args = lappend(args, - typeStringToTypeName(TextDatumGetCString(elems[i]))); + typeStringToTypeName_compat(TextDatumGetCString(elems[i]), + NULL)); } } else diff --git a/src/backend/distributed/operations/shard_rebalancer.c b/src/backend/distributed/operations/shard_rebalancer.c index 20004f5fb..a8cb3df5c 100644 --- a/src/backend/distributed/operations/shard_rebalancer.c +++ b/src/backend/distributed/operations/shard_rebalancer.c @@ -2373,8 +2373,8 @@ GetSetCommandListForNewConnections(void) { List *commandList = NIL; - struct config_generic **guc_vars = get_guc_variables(); - int gucCount = GetNumConfigOptions(); + int gucCount = 0; + struct config_generic **guc_vars = get_guc_variables_compat(&gucCount); for (int gucIndex = 0; gucIndex < gucCount; gucIndex++) { diff --git a/src/backend/distributed/planner/fast_path_router_planner.c b/src/backend/distributed/planner/fast_path_router_planner.c index 7b97d3ff5..41802ee83 100644 --- a/src/backend/distributed/planner/fast_path_router_planner.c +++ b/src/backend/distributed/planner/fast_path_router_planner.c @@ -103,15 +103,24 @@ PlannedStmt * GeneratePlaceHolderPlannedStmt(Query *parse) { PlannedStmt *result = makeNode(PlannedStmt); +#if PG_VERSION_NUM >= PG_VERSION_16 + SeqScan *scanNode = makeNode(SeqScan); + Plan *plan = &(scanNode->scan.plan); +#else Scan *scanNode = makeNode(Scan); Plan *plan = &scanNode->plan; +#endif Node *distKey PG_USED_FOR_ASSERTS_ONLY = NULL; Assert(FastPathRouterQuery(parse, &distKey)); /* there is only a single relation rte */ +#if PG_VERSION_NUM >= PG_VERSION_16 + scanNode->scan.scanrelid = 1; +#else scanNode->scanrelid = 1; +#endif plan->targetlist = copyObject(FetchStatementTargetList((Node *) parse)); diff --git a/src/backend/distributed/planner/query_colocation_checker.c b/src/backend/distributed/planner/query_colocation_checker.c index a6e64b9c1..f5701fdb1 100644 --- a/src/backend/distributed/planner/query_colocation_checker.c +++ b/src/backend/distributed/planner/query_colocation_checker.c @@ -126,7 +126,7 @@ static RangeTblEntry * AnchorRte(Query *subquery) { FromExpr *joinTree = subquery->jointree; - Relids joinRelIds = get_relids_in_jointree((Node *) joinTree, false); + Relids joinRelIds = get_relids_in_jointree_compat((Node *) joinTree, false, false); int currentRTEIndex = -1; RangeTblEntry *anchorRangeTblEntry = NULL; diff --git a/src/backend/distributed/shared_library_init.c b/src/backend/distributed/shared_library_init.c index 2493a8ea9..a2b1811b8 100644 --- a/src/backend/distributed/shared_library_init.c +++ b/src/backend/distributed/shared_library_init.c @@ -2650,8 +2650,8 @@ RegisterCitusConfigVariables(void) static void OverridePostgresConfigProperties(void) { - struct config_generic **guc_vars = get_guc_variables(); - int gucCount = GetNumConfigOptions(); + int gucCount = 0; + struct config_generic **guc_vars = get_guc_variables_compat(&gucCount); for (int gucIndex = 0; gucIndex < gucCount; gucIndex++) { @@ -2810,7 +2810,7 @@ ShowShardsForAppNamePrefixesCheckHook(char **newval, void **extra, GucSource sou } char *prefixAscii = pstrdup(appNamePrefix); - pg_clean_ascii(prefixAscii); + pg_clean_ascii_compat(prefixAscii, 0); if (strcmp(prefixAscii, appNamePrefix) != 0) { diff --git a/src/backend/distributed/test/fake_am.c b/src/backend/distributed/test/fake_am.c index 1654bf095..8a723e4c4 100644 --- a/src/backend/distributed/test/fake_am.c +++ b/src/backend/distributed/test/fake_am.c @@ -254,7 +254,7 @@ fake_tuple_update(Relation relation, ItemPointer otid, TupleTableSlot *slot, CommandId cid, Snapshot snapshot, Snapshot crosscheck, bool wait, TM_FailureData *tmfd, - LockTupleMode *lockmode, bool *update_indexes) + LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) { elog(ERROR, "fake_tuple_update not implemented"); } @@ -283,7 +283,7 @@ fake_finish_bulk_insert(Relation relation, int options) */ static void fake_relation_set_new_filenode(Relation rel, - const RelFileNode *newrnode, + const RelFileLocator *newrnode, char persistence, TransactionId *freezeXid, MultiXactId *minmulti) @@ -344,7 +344,7 @@ fake_relation_nontransactional_truncate(Relation rel) static void -fake_copy_data(Relation rel, const RelFileNode *newrnode) +fake_copy_data(Relation rel, const RelFileLocator *newrnode) { elog(ERROR, "fake_copy_data not implemented"); } @@ -555,7 +555,11 @@ static const TableAmRoutine fake_methods = { .tuple_satisfies_snapshot = fake_tuple_satisfies_snapshot, .index_delete_tuples = fake_index_delete_tuples, +#if PG_VERSION_NUM >= PG_VERSION_16 + .relation_set_new_filelocator = fake_relation_set_new_filenode, +#else .relation_set_new_filenode = fake_relation_set_new_filenode, +#endif .relation_nontransactional_truncate = fake_relation_nontransactional_truncate, .relation_copy_data = fake_copy_data, .relation_copy_for_cluster = fake_copy_for_cluster, diff --git a/src/backend/distributed/transaction/lock_graph.c b/src/backend/distributed/transaction/lock_graph.c index 0be4bb2e9..0b4c0f02e 100644 --- a/src/backend/distributed/transaction/lock_graph.c +++ b/src/backend/distributed/transaction/lock_graph.c @@ -725,7 +725,100 @@ UnlockLockData(void) * which also contains entries for locks which have not been granted yet, but * it does not reflect the order of the wait queue. We therefore handle the * wait queue separately. + * + * We have separate blocks for PG16 and = PG_VERSION_16 +static void +AddEdgesForLockWaits(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remaining) +{ + /* the lock for which this process is waiting */ + LOCK *waitLock = waitingProc->waitLock; + + /* determine the conflict mask for the lock level used by the process */ + LockMethod lockMethodTable = GetLocksMethodTable(waitLock); + int conflictMask = lockMethodTable->conflictTab[waitingProc->waitLockMode]; + + /* iterate through the queue of processes holding the lock */ + dlist_head *procLocks = &waitLock->procLocks; + + dlist_iter iter; + dlist_foreach(iter, procLocks) + { + PROCLOCK *procLock = dlist_container(PROCLOCK, lockLink, iter.cur); + PGPROC *currentProc = procLock->tag.myProc; + + /* + * Skip processes from the same lock group, processes that don't conflict, + * and processes that are waiting on safe operations. + */ + if (!IsSameLockGroup(waitingProc, currentProc) && + IsConflictingLockMask(procLock->holdMask, conflictMask) && + !IsProcessWaitingForSafeOperations(currentProc)) + { + AddWaitEdge(waitGraph, waitingProc, currentProc, remaining); + } + } +} + + +static void +AddEdgesForWaitQueue(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remaining) +{ + /* the lock for which this process is waiting */ + LOCK *waitLock = waitingProc->waitLock; + + /* determine the conflict mask for the lock level used by the process */ + LockMethod lockMethodTable = GetLocksMethodTable(waitLock); + int conflictMask = lockMethodTable->conflictTab[waitingProc->waitLockMode]; + + /* iterate through the wait queue */ + dclist_head *waitQueue = &waitLock->waitProcs; + + dlist_iter iter; + dclist_foreach(iter, waitQueue) + { + PGPROC *currentProc = dlist_container(PGPROC, links, iter.cur); + + if (currentProc == waitingProc) + { + /* + * Iterate through the queue from the start until we encounter waitingProc, + * since we only care about processes in front of waitingProc in the queue. + */ + break; + } + + int awaitMask = LOCKBIT_ON(currentProc->waitLockMode); + + /* + * Skip processes from the same lock group, processes that don't conflict, + * and processes that are waiting on safe operations. + */ + if (!IsSameLockGroup(waitingProc, currentProc) && + IsConflictingLockMask(awaitMask, conflictMask) && + !IsProcessWaitingForSafeOperations(currentProc)) + { + AddWaitEdge(waitGraph, waitingProc, currentProc, remaining); + } + + currentProc = (PGPROC *) currentProc->links.next; + } +} + + +#else + static void AddEdgesForLockWaits(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remaining) { @@ -762,10 +855,6 @@ AddEdgesForLockWaits(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remai } -/* - * AddEdgesForWaitQueue adds an edge to the wait graph for processes in front of - * waitingProc in the wait queue that are trying to acquire a conflicting lock. - */ static void AddEdgesForWaitQueue(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remaining) { @@ -805,6 +894,9 @@ AddEdgesForWaitQueue(WaitGraph *waitGraph, PGPROC *waitingProc, PROCStack *remai } +#endif + + /* * AddWaitEdge adds a new wait edge to a wait graph. The nodes in the graph are * transactions and an edge indicates the "waiting" process is blocked on a lock diff --git a/src/backend/distributed/utils/aggregate_utils.c b/src/backend/distributed/utils/aggregate_utils.c index 91f6fc523..773e0aa25 100644 --- a/src/backend/distributed/utils/aggregate_utils.c +++ b/src/backend/distributed/utils/aggregate_utils.c @@ -168,7 +168,8 @@ aclcheckAggregate(ObjectType objectType, Oid userOid, Oid funcOid) AclResult aclresult; if (funcOid != InvalidOid) { - aclresult = pg_proc_aclcheck(funcOid, userOid, ACL_EXECUTE); + aclresult = object_aclcheck(ProcedureRelationId, funcOid, userOid, + ACL_EXECUTE); if (aclresult != ACLCHECK_OK) { aclcheck_error(aclresult, objectType, get_func_name(funcOid)); diff --git a/src/backend/distributed/utils/function_utils.c b/src/backend/distributed/utils/function_utils.c index 006e29555..48f878e13 100644 --- a/src/backend/distributed/utils/function_utils.c +++ b/src/backend/distributed/utils/function_utils.c @@ -41,7 +41,8 @@ FunctionOidExtended(const char *schemaName, const char *functionName, int argume bool missingOK) { char *qualifiedFunctionName = quote_qualified_identifier(schemaName, functionName); - List *qualifiedFunctionNameList = stringToQualifiedNameList(qualifiedFunctionName); + List *qualifiedFunctionNameList = stringToQualifiedNameList_compat( + qualifiedFunctionName); List *argumentList = NIL; const bool findVariadics = false; const bool findDefaults = false; diff --git a/src/backend/distributed/utils/relation_utils.c b/src/backend/distributed/utils/relation_utils.c index 12c76a4ab..ef02736ea 100644 --- a/src/backend/distributed/utils/relation_utils.c +++ b/src/backend/distributed/utils/relation_utils.c @@ -14,6 +14,9 @@ #include "distributed/relation_utils.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "miscadmin.h" +#endif #include "utils/lsyscache.h" #include "utils/rel.h" @@ -28,3 +31,37 @@ RelationGetNamespaceName(Relation relation) char *namespaceName = get_namespace_name(namespaceId); return namespaceName; } + + +#if PG_VERSION_NUM >= PG_VERSION_16 + +/* + * GetFilledPermissionInfo creates RTEPermissionInfo for a given RTE + * and fills it with given data and returns this RTEPermissionInfo object. + * Added this function since Postgres's addRTEPermissionInfo doesn't fill the data. + * + * Given data consists of relid, inh and requiredPerms + * Took a quick look around Postgres, unless specified otherwise, + * we are dealing with GetUserId(). + * Currently the following entries are filled like this: + * perminfo->checkAsUser = GetUserId(); + * perminfo->selectedCols = NULL; + * perminfo->insertedCols = NULL; + * perminfo->updatedCols = NULL; + */ +RTEPermissionInfo * +GetFilledPermissionInfo(Oid relid, bool inh, AclMode requiredPerms) +{ + RTEPermissionInfo *perminfo = makeNode(RTEPermissionInfo); + perminfo->relid = relid; + perminfo->inh = inh; + perminfo->requiredPerms = requiredPerms; + perminfo->checkAsUser = GetUserId(); + perminfo->selectedCols = NULL; + perminfo->insertedCols = NULL; + perminfo->updatedCols = NULL; + return perminfo; +} + + +#endif diff --git a/src/backend/distributed/worker/worker_create_or_replace.c b/src/backend/distributed/worker/worker_create_or_replace.c index b40f712b5..804e71125 100644 --- a/src/backend/distributed/worker/worker_create_or_replace.c +++ b/src/backend/distributed/worker/worker_create_or_replace.c @@ -525,8 +525,8 @@ CreateRenameTypeStmt(const ObjectAddress *address, char *newName) RenameStmt *stmt = makeNode(RenameStmt); stmt->renameType = OBJECT_TYPE; - stmt->object = (Node *) stringToQualifiedNameList(format_type_be_qualified( - address->objectId)); + stmt->object = (Node *) stringToQualifiedNameList_compat(format_type_be_qualified( + address->objectId)); stmt->newname = newName; diff --git a/src/include/columnar/columnar.h b/src/include/columnar/columnar.h index 13195b1d6..59a66ab25 100644 --- a/src/include/columnar/columnar.h +++ b/src/include/columnar/columnar.h @@ -16,9 +16,14 @@ #include "fmgr.h" #include "lib/stringinfo.h" #include "nodes/parsenodes.h" +#include "pg_version_compat.h" #include "storage/bufpage.h" #include "storage/lockdefs.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "storage/relfilelocator.h" +#else #include "storage/relfilenode.h" +#endif #include "utils/relcache.h" #include "utils/snapmgr.h" @@ -224,7 +229,7 @@ extern void columnar_init_gucs(void); extern CompressionType ParseCompressionType(const char *compressionTypeString); /* Function declarations for writing to a columnar table */ -extern ColumnarWriteState * ColumnarBeginWrite(RelFileNode relfilenode, +extern ColumnarWriteState * ColumnarBeginWrite(RelFileLocator relfilelocator, ColumnarOptions options, TupleDesc tupleDescriptor); extern uint64 ColumnarWriteRow(ColumnarWriteState *state, Datum *columnValues, @@ -279,21 +284,21 @@ extern bool ReadColumnarOptions(Oid regclass, ColumnarOptions *options); extern bool IsColumnarTableAmTable(Oid relationId); /* columnar_metadata_tables.c */ -extern void DeleteMetadataRows(RelFileNode relfilenode); +extern void DeleteMetadataRows(RelFileLocator relfilelocator); extern uint64 ColumnarMetadataNewStorageId(void); -extern uint64 GetHighestUsedAddress(RelFileNode relfilenode); +extern uint64 GetHighestUsedAddress(RelFileLocator relfilelocator); extern EmptyStripeReservation * ReserveEmptyStripe(Relation rel, uint64 columnCount, uint64 chunkGroupRowCount, uint64 stripeRowCount); extern StripeMetadata * CompleteStripeReservation(Relation rel, uint64 stripeId, uint64 sizeBytes, uint64 rowCount, uint64 chunkCount); -extern void SaveStripeSkipList(RelFileNode relfilenode, uint64 stripe, +extern void SaveStripeSkipList(RelFileLocator relfilelocator, uint64 stripe, StripeSkipList *stripeSkipList, TupleDesc tupleDescriptor); -extern void SaveChunkGroups(RelFileNode relfilenode, uint64 stripe, +extern void SaveChunkGroups(RelFileLocator relfilelocator, uint64 stripe, List *chunkGroupRowCounts); -extern StripeSkipList * ReadStripeSkipList(RelFileNode relfilenode, uint64 stripe, +extern StripeSkipList * ReadStripeSkipList(RelFileLocator relfilelocator, uint64 stripe, TupleDesc tupleDescriptor, uint32 chunkCount, Snapshot snapshot); @@ -316,15 +321,16 @@ extern ColumnarWriteState * columnar_init_write_state(Relation relation, TupleDe tupdesc, Oid tupSlotRelationId, SubTransactionId currentSubXid); -extern void FlushWriteStateForRelfilenode(Oid relfilenode, SubTransactionId - currentSubXid); +extern void FlushWriteStateForRelfilenumber(RelFileNumber relfilenumber, + SubTransactionId currentSubXid); extern void FlushWriteStateForAllRels(SubTransactionId currentSubXid, SubTransactionId parentSubXid); extern void DiscardWriteStateForAllRels(SubTransactionId currentSubXid, SubTransactionId parentSubXid); -extern void MarkRelfilenodeDropped(Oid relfilenode, SubTransactionId currentSubXid); -extern void NonTransactionDropWriteState(Oid relfilenode); -extern bool PendingWritesInUpperTransactions(Oid relfilenode, +extern void MarkRelfilenumberDropped(RelFileNumber relfilenumber, + SubTransactionId currentSubXid); +extern void NonTransactionDropWriteState(RelFileNumber relfilenumber); +extern bool PendingWritesInUpperTransactions(RelFileNumber relfilenumber, SubTransactionId currentSubXid); extern MemoryContext GetWriteContextForDebug(void); diff --git a/src/include/columnar/columnar_metadata.h b/src/include/columnar/columnar_metadata.h index c17799483..2af4354a0 100644 --- a/src/include/columnar/columnar_metadata.h +++ b/src/include/columnar/columnar_metadata.h @@ -12,6 +12,8 @@ #ifndef COLUMNAR_METADATA_H #define COLUMNAR_METADATA_H +#include "pg_version_compat.h" + /* * StripeMetadata represents information about a stripe. This information is * stored in the metadata table "columnar.stripe". @@ -49,7 +51,7 @@ typedef struct EmptyStripeReservation uint64 stripeFirstRowNumber; } EmptyStripeReservation; -extern List * StripesForRelfilenode(RelFileNode relfilenode); +extern List * StripesForRelfilelocator(RelFileLocator relfilelocator); extern void ColumnarStorageUpdateIfNeeded(Relation rel, bool isUpgrade); extern List * ExtractColumnarRelOptions(List *inOptions, List **outColumnarOptions); extern void SetColumnarRelOptions(RangeVar *rv, List *reloptions); diff --git a/src/include/distributed/commands/multi_copy.h b/src/include/distributed/commands/multi_copy.h index 4255c952d..fa59894ad 100644 --- a/src/include/distributed/commands/multi_copy.h +++ b/src/include/distributed/commands/multi_copy.h @@ -182,7 +182,7 @@ extern void AppendCopyRowData(Datum *valueArray, bool *isNullArray, extern void AppendCopyBinaryHeaders(CopyOutState headerOutputState); extern void AppendCopyBinaryFooters(CopyOutState footerOutputState); extern void EndRemoteCopy(int64 shardId, List *connectionList); -extern List * CreateRangeTable(Relation rel, AclMode requiredAccess); +extern List * CreateRangeTable(Relation rel); extern Node * ProcessCopyStmt(CopyStmt *copyStatement, QueryCompletion *completionTag, const char *queryString); diff --git a/src/include/distributed/errormessage.h b/src/include/distributed/errormessage.h index 7e0b1c33d..3c19a9c83 100644 --- a/src/include/distributed/errormessage.h +++ b/src/include/distributed/errormessage.h @@ -12,6 +12,7 @@ #include "c.h" #include "distributed/citus_nodes.h" +#include "pg_version_compat.h" typedef struct DeferredErrorMessage diff --git a/src/include/distributed/relation_utils.h b/src/include/distributed/relation_utils.h index 873398f00..acf84a9da 100644 --- a/src/include/distributed/relation_utils.h +++ b/src/include/distributed/relation_utils.h @@ -13,8 +13,16 @@ #include "postgres.h" +#include "distributed/pg_version_constants.h" +#if PG_VERSION_NUM >= PG_VERSION_16 +#include "parser/parse_relation.h" +#endif #include "utils/relcache.h" extern char * RelationGetNamespaceName(Relation relation); +#if PG_VERSION_NUM >= PG_VERSION_16 +extern RTEPermissionInfo * GetFilledPermissionInfo(Oid relid, bool inh, + AclMode requiredPerms); +#endif #endif /* RELATION_UTILS_H */ diff --git a/src/include/pg_version_compat.h b/src/include/pg_version_compat.h index 00c5e286b..3177aec28 100644 --- a/src/include/pg_version_compat.h +++ b/src/include/pg_version_compat.h @@ -13,6 +13,139 @@ #include "distributed/pg_version_constants.h" +#if PG_VERSION_NUM >= PG_VERSION_16 + +#include "utils/guc_tables.h" + +#define pg_clean_ascii_compat(a, b) pg_clean_ascii(a, b) + +#define RelationPhysicalIdentifier_compat(a) ((a)->rd_locator) +#define RelationTablespace_compat(a) (a.spcOid) +#define RelationPhysicalIdentifierNumber_compat(a) (a.relNumber) +#define RelationPhysicalIdentifierNumberPtr_compat(a) (a->relNumber) +#define RelationPhysicalIdentifierBackend_compat(a) (a->smgr_rlocator.locator) + +#define float_abs(a) fabs(a) + +#define RANGE_VAR_TABLE_CALLBACK RangeVarCallbackMaintainsTable + +#define tuplesort_getdatum_compat(a, b, c, d, e, f) tuplesort_getdatum(a, b, c, d, e, f) + +static inline struct config_generic ** +get_guc_variables_compat(int *gucCount) +{ + return get_guc_variables(gucCount); +} + + +#define PG_FUNCNAME_MACRO __func__ + +#define stringToQualifiedNameList_compat(a) stringToQualifiedNameList(a, NULL) +#define typeStringToTypeName_compat(a, b) typeStringToTypeName(a, b) + +#define get_relids_in_jointree_compat(a, b, c) get_relids_in_jointree(a, b, c) + +#define object_ownercheck(a, b, c) object_ownercheck(a, b, c) +#define object_aclcheck(a, b, c, d) object_aclcheck(a, b, c, d) + +#else + +#include "catalog/pg_class_d.h" +#include "catalog/pg_namespace.h" +#include "catalog/pg_proc_d.h" +#include "storage/relfilenode.h" +#include "utils/guc.h" +#include "utils/guc_tables.h" + +#define RANGE_VAR_TABLE_CALLBACK RangeVarCallbackOwnsTable + +#define pg_clean_ascii_compat(a, b) pg_clean_ascii(a) + +#define RelationPhysicalIdentifier_compat(a) ((a)->rd_node) +#define RelationTablespace_compat(a) (a.spcNode) +#define RelationPhysicalIdentifierNumber_compat(a) (a.relNode) +#define RelationPhysicalIdentifierNumberPtr_compat(a) (a->relNode) +#define RelationPhysicalIdentifierBackend_compat(a) (a->smgr_rnode.node) +typedef RelFileNode RelFileLocator; +typedef Oid RelFileNumber; +#define RelidByRelfilenumber(a, b) RelidByRelfilenode(a, b) + +#define float_abs(a) Abs(a) + +#define tuplesort_getdatum_compat(a, b, c, d, e, f) tuplesort_getdatum(a, b, d, e, f) + +static inline struct config_generic ** +get_guc_variables_compat(int *gucCount) +{ + *gucCount = GetNumConfigOptions(); + return get_guc_variables(); +} + + +#define stringToQualifiedNameList_compat(a) stringToQualifiedNameList(a) +#define typeStringToTypeName_compat(a, b) typeStringToTypeName(a) + +#define get_relids_in_jointree_compat(a, b, c) get_relids_in_jointree(a, b) + +static inline bool +object_ownercheck(Oid classid, Oid objectid, Oid roleid) +{ + switch (classid) + { + case RelationRelationId: + { + return pg_class_ownercheck(objectid, roleid); + } + + case NamespaceRelationId: + { + return pg_namespace_ownercheck(objectid, roleid); + } + + case ProcedureRelationId: + { + return pg_proc_ownercheck(objectid, roleid); + } + + default: + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Missing classid:%d", + classid))); + } + } +} + + +static inline AclResult +object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode) +{ + switch (classid) + { + case NamespaceRelationId: + { + return pg_namespace_aclcheck(objectid, roleid, mode); + } + + case ProcedureRelationId: + { + return pg_proc_aclcheck(objectid, roleid, mode); + } + + default: + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Missing classid:%d", + classid))); + } + } +} + + +typedef bool TU_UpdateIndexes; + +#endif + #if PG_VERSION_NUM >= PG_VERSION_15 #define ProcessCompletedNotifies() #define RelationCreateStorage_compat(a, b, c) RelationCreateStorage(a, b, c) diff --git a/src/test/regress/expected/columnar_create.out b/src/test/regress/expected/columnar_create.out index d679b7790..73b891177 100644 --- a/src/test/regress/expected/columnar_create.out +++ b/src/test/regress/expected/columnar_create.out @@ -54,7 +54,7 @@ CREATE MATERIALIZED VIEW columnar_table_1_mv USING columnar AS SELECT * FROM columnar_table_1; SELECT columnar.get_storage_id(oid) AS columnar_table_1_mv_storage_id FROM pg_class WHERE relname='columnar_table_1_mv' \gset --- test columnar_relation_set_new_filenode +-- test columnar_relation_set_new_filelocator REFRESH MATERIALIZED VIEW columnar_table_1_mv; SELECT columnar_test_helpers.columnar_metadata_has_storage_id(:columnar_table_1_mv_storage_id); columnar_metadata_has_storage_id diff --git a/src/test/regress/sql/columnar_create.sql b/src/test/regress/sql/columnar_create.sql index 017cc0d8f..408ce126e 100644 --- a/src/test/regress/sql/columnar_create.sql +++ b/src/test/regress/sql/columnar_create.sql @@ -56,7 +56,7 @@ AS SELECT * FROM columnar_table_1; SELECT columnar.get_storage_id(oid) AS columnar_table_1_mv_storage_id FROM pg_class WHERE relname='columnar_table_1_mv' \gset --- test columnar_relation_set_new_filenode +-- test columnar_relation_set_new_filelocator REFRESH MATERIALIZED VIEW columnar_table_1_mv; SELECT columnar_test_helpers.columnar_metadata_has_storage_id(:columnar_table_1_mv_storage_id);