mirror of https://github.com/citusdata/citus.git
PG16 compatibility: Resolve compilation issues (#7005)
This PR provides successful compilation against PG16Beta2. It does some necessary refactoring to prepare for full support of version 16, in https://github.com/citusdata/citus/pull/6952 . Change RelFileNode to RelFileNumber or RelFileLocator Relevant PG commit b0a55e43299c4ea2a9a8c757f9c26352407d0ccc new header for varatt.h Relevant PG commit: d952373a987bad331c0e499463159dd142ced1ef drop support for Abs, use fabs Relevant PG commit 357cfefb09115292cfb98d504199e6df8201c957 tuplesort PGcommit: d37aa3d35832afde94e100c4d2a9618b3eb76472 Relevant PG commit: d37aa3d35832afde94e100c4d2a9618b3eb76472 Fix vacuum in columnar Relevant PG commit: 4ce3afb82ecfbf64d4f6247e725004e1da30f47c older one: b6074846cebc33d752f1d9a66e5a9932f21ad177 Add alloc_flags to pg_clean_ascii Relevant PG commit: 45b1a67a0fcb3f1588df596431871de4c93cb76f Merge GetNumConfigOptions() into get_guc_variables() Relevant PG commit: 3057465acfbea2f3dd7a914a1478064022c6eecd Minor PG refactor PG_FUNCNAME_MACRO __func__ Relevant PG commit 320f92b744b44f961e5d56f5f21de003e8027a7f Pass NULL context to stringToQualifiedNameList, typeStringToTypeName The pre-PG16 error behaviour for the following stringToQualifiedNameList & typeStringToTypeName was ereport(ERROR, ...) Now with PG16 we have this context input. We preserve the same behaviour by passing a NULL context, because of the following: (copy paste comment from PG16) If "context" isn't an ErrorSaveContext node, this behaves as errstart(ERROR, domain), and the errsave() macro ends up acting exactly like ereport(ERROR, ...). Relevant PG commit 858e776c84f48841e7e16fba7b690b76e54f3675 Use RangeVarCallbackMaintainsTable instead of RangeVarCallbackOwnsTable Relevant PG commit: 60684dd834a222fefedd49b19d1f0a6189c1632e FIX THIS: Not implemented grant-level control of role inheritance see PG commit e3ce2de09d814f8770b2e3b3c152b7671bcdb83f Make Scan node abstract PG commit: 8c73c11a0d39049de2c1f400d8765a0eb21f5228 Change in Var representations, get_relids_in_jointree PG commit 2489d76c4906f4461a364ca8ad7e0751ead8aa0d Deadlock detection changes because SHM_QUEUE is removed Relevant PG Commit: d137cb52cb7fd44a3f24f3c750fbf7924a4e9532 TU_UpdateIndexes Relevant PG commit 19d8e2308bc51ec4ab993ce90077342c915dd116 Use object_ownercheck and object_aclcheck functions Relevant PG commits: afbfc02983f86c4d71825efa6befd547fe81a926 c727f511bd7bf3c58063737bcf7a8f331346f253 Rework Permission Info for successful compilation Relevant PG commits: postgres/postgres@a61b1f7 postgres/postgres@b803b7d --------- Co-authored-by: onderkalaci <onderkalaci@gmail.com>pull/7037/head
parent
a282953274
commit
42d956888d
|
@ -18,11 +18,16 @@
|
|||
#include "lib/stringinfo.h"
|
||||
|
||||
#include "columnar/columnar_compression.h"
|
||||
#include "distributed/pg_version_constants.h"
|
||||
|
||||
#if HAVE_CITUS_LIBLZ4
|
||||
#include <lz4.h>
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||
#include "varatt.h"
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBZSTD
|
||||
#include <zstd.h>
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <PG16 because SHM_QUEUE is completely
|
||||
* removed from PG16
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* We have separate blocks for PG16 and <PG16 because SHM_QUEUE is completely
|
||||
* removed from PG16
|
||||
*/
|
||||
|
||||
#if PG_VERSION_NUM >= 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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "c.h"
|
||||
#include "distributed/citus_nodes.h"
|
||||
#include "pg_version_compat.h"
|
||||
|
||||
|
||||
typedef struct DeferredErrorMessage
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue