From 56b8ef3454103349afa0dd9f5c0335f8ffc1629a Mon Sep 17 00:00:00 2001 From: Amit Date: Sat, 14 Apr 2018 00:22:55 +0900 Subject: [PATCH v1 1/3] Make copying of cached partitioning info more consistent Currently there are many callers that hold onto pointers that point into the partitioning related information cached in relcache. There are others, such as the planner, who copy important information before using the information. Make everyone copy! Now because no part of the backend relies on the guarantee that pointers to partitioning info in relcache points to same memory even across relcache flushes, we don't need special guards as implemented in RelationClearRelation() to provide the aforementioned guarantee. --- src/backend/catalog/heap.c | 2 +- src/backend/catalog/partition.c | 20 +---- src/backend/catalog/pg_constraint.c | 9 ++- src/backend/commands/indexcmds.c | 8 +- src/backend/commands/tablecmds.c | 75 ++++++++---------- src/backend/commands/trigger.c | 23 +++--- src/backend/executor/execPartition.c | 63 ++++++++------- src/backend/optimizer/prep/prepunion.c | 14 ++-- src/backend/optimizer/util/plancat.c | 75 ++++++------------ src/backend/parser/parse_utilcmd.c | 4 +- src/backend/partitioning/partbounds.c | 38 +++++---- src/backend/partitioning/partprune.c | 25 +++--- src/backend/utils/cache/partcache.c | 140 ++++++++++++++++++++++++++++++++- src/backend/utils/cache/relcache.c | 95 ++-------------------- src/include/catalog/partition.h | 2 - src/include/executor/execPartition.h | 10 ++- src/include/partitioning/partbounds.h | 2 +- src/include/partitioning/partprune.h | 2 +- src/include/utils/partcache.h | 5 ++ src/include/utils/rel.h | 12 --- 20 files changed, 318 insertions(+), 306 deletions(-) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 39813de991..bdb47001c8 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -3473,7 +3473,7 @@ StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound) * relcache entry for that partition every time a partition is added or * removed. */ - defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent)); + defaultPartOid = RelationGetDefaultPartitionOid(parent); if (OidIsValid(defaultPartOid)) CacheInvalidateRelcacheByRelid(defaultPartOid); diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index de801ad788..3c76b6c69a 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -256,27 +256,11 @@ has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr) } /* - * get_default_oid_from_partdesc - * - * Given a partition descriptor, return the OID of the default partition, if - * one exists; else, return InvalidOid. - */ -Oid -get_default_oid_from_partdesc(PartitionDesc partdesc) -{ - if (partdesc && partdesc->boundinfo && - partition_bound_has_default(partdesc->boundinfo)) - return partdesc->oids[partdesc->boundinfo->default_index]; - - return InvalidOid; -} - -/* * get_default_partition_oid * * Given a relation OID, return the OID of the default partition, if one - * exists. Use get_default_oid_from_partdesc where possible, for - * efficiency. + * exists. If you have the parent relation open, use + * RelationGetDefaultPartitionOid() instead. */ Oid get_default_partition_oid(Oid parentId) diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index c5b5395791..686d0aa580 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -32,6 +32,7 @@ #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" +#include "utils/partcache.h" #include "utils/rel.h" #include "utils/syscache.h" #include "utils/tqual.h" @@ -625,12 +626,14 @@ CloneForeignKeyConstraints(Oid parentId, Oid relationId, List **cloned) if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { - PartitionDesc partdesc = RelationGetPartitionDesc(rel); + int nparts = RelationGetPartitionCount(rel); + Oid *partoids = RelationGetPartitionOids(rel); int i; - for (i = 0; i < partdesc->nparts; i++) + Assert(partoids != NULL || nparts == 0); + for (i = 0; i < nparts; i++) CloneForeignKeyConstraints(RelationGetRelid(rel), - partdesc->oids[i], + partoids[i], cloned); } diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index f2dcc1c51f..e335dfecc4 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -878,15 +878,12 @@ DefineIndex(Oid relationId, */ if (!stmt->relation || stmt->relation->inh) { - PartitionDesc partdesc = RelationGetPartitionDesc(rel); - int nparts = partdesc->nparts; - Oid *part_oids = palloc(sizeof(Oid) * nparts); + int nparts = RelationGetPartitionCount(rel); + Oid *part_oids = RelationGetPartitionOids(rel); bool invalidate_parent = false; TupleDesc parentDesc; Oid *opfamOids; - memcpy(part_oids, partdesc->oids, sizeof(Oid) * nparts); - parentDesc = CreateTupleDescCopy(RelationGetDescr(rel)); opfamOids = palloc(sizeof(Oid) * numberOfKeyAttributes); for (i = 0; i < numberOfKeyAttributes; i++) @@ -902,6 +899,7 @@ DefineIndex(Oid relationId, * If none matches, build a new index by calling ourselves * recursively with the same options (except for the index name). */ + Assert(part_oids != NULL || nparts == 0); for (i = 0; i < nparts; i++) { Oid childRelid = part_oids[i]; diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index c1a9bda433..fe4265d4bb 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -829,8 +829,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, * the places such that lock parent, lock default partition and then * lock the partition so as to avoid a deadlock. */ - defaultPartOid = - get_default_oid_from_partdesc(RelationGetPartitionDesc(parent)); + defaultPartOid = RelationGetDefaultPartitionOid(parent); if (OidIsValid(defaultPartOid)) defaultRel = heap_open(defaultPartOid, AccessExclusiveLock); @@ -5864,18 +5863,14 @@ ATPrepDropNotNull(Relation rel, bool recurse, bool recursing) * If the parent is a partitioned table, like check constraints, we do not * support removing the NOT NULL while partitions exist. */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - { - PartitionDesc partdesc = RelationGetPartitionDesc(rel); - - Assert(partdesc != NULL); - if (partdesc->nparts > 0 && !recurse && !recursing) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("cannot remove constraint from only the partitioned table when partitions exist"), - errhint("Do not specify the ONLY keyword."))); - } + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && + RelationGetPartitionCount(rel) > 0 && !recurse && !recursing) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("cannot remove constraint from only the partitioned table when partitions exist"), + errhint("Do not specify the ONLY keyword."))); } + static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) { @@ -6009,16 +6004,12 @@ ATPrepSetNotNull(Relation rel, bool recurse, bool recursing) * constraints must be added to the child tables. Complain if requested * otherwise and partitions exist. */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - { - PartitionDesc partdesc = RelationGetPartitionDesc(rel); - - if (partdesc && partdesc->nparts > 0 && !recurse && !recursing) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("cannot add constraint to only the partitioned table when partitions exist"), - errhint("Do not specify the ONLY keyword."))); - } + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && + RelationGetPartitionCount(rel) > 0 && !recurse && !recursing) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("cannot add constraint to only the partitioned table when partitions exist"), + errhint("Do not specify the ONLY keyword."))); } /* @@ -7699,13 +7690,13 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, */ if (recurse && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { - PartitionDesc partdesc; + int nparts = RelationGetPartitionCount(rel); + Oid *partoids = RelationGetPartitionOids(rel); - partdesc = RelationGetPartitionDesc(rel); - - for (i = 0; i < partdesc->nparts; i++) + Assert(partoids != NULL || nparts == 0); + for (i = 0; i < nparts; i++) { - Oid partitionId = partdesc->oids[i]; + Oid partitionId = partoids[i]; Relation partition = heap_open(partitionId, lockmode); AlteredTableInfo *childtab; ObjectAddress childAddr; @@ -13989,10 +13980,12 @@ QueuePartitionConstraintValidation(List **wqueue, Relation scanrel, } else if (scanrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { - PartitionDesc partdesc = RelationGetPartitionDesc(scanrel); + int nparts = RelationGetPartitionCount(scanrel); + Oid *partoids = RelationGetPartitionOids(scanrel); int i; - for (i = 0; i < partdesc->nparts; i++) + Assert(partoids != NULL || nparts == 0); + for (i = 0; i < nparts; i++) { Relation part_rel; bool found_whole_row; @@ -14001,7 +13994,7 @@ QueuePartitionConstraintValidation(List **wqueue, Relation scanrel, /* * This is the minimum lock we need to prevent deadlocks. */ - part_rel = heap_open(partdesc->oids[i], AccessExclusiveLock); + part_rel = heap_open(partoids[i], AccessExclusiveLock); /* * Adjust the constraint for scanrel so that it matches this @@ -14051,8 +14044,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) * We must lock the default partition if one exists, because attaching a * new partition will change its partition constraint. */ - defaultPartOid = - get_default_oid_from_partdesc(RelationGetPartitionDesc(rel)); + defaultPartOid = RelationGetDefaultPartitionOid(rel); if (OidIsValid(defaultPartOid)) LockRelationOid(defaultPartOid, AccessExclusiveLock); @@ -14628,8 +14620,7 @@ ATExecDetachPartition(Relation rel, RangeVar *name) * We must lock the default partition, because detaching this partition * will change its partition constraint. */ - defaultPartOid = - get_default_oid_from_partdesc(RelationGetPartitionDesc(rel)); + defaultPartOid = RelationGetDefaultPartitionOid(rel); if (OidIsValid(defaultPartOid)) LockRelationOid(defaultPartOid, AccessExclusiveLock); @@ -14830,8 +14821,9 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) AttrNumber *attmap; bool found; int i; - PartitionDesc partDesc; - Oid constraintOid, + int nparts = RelationGetPartitionCount(parentTbl); + Oid *partoids = RelationGetPartitionOids(parentTbl), + constraintOid, cldConstrId = InvalidOid; /* @@ -14849,11 +14841,11 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) RelationGetRelationName(partIdx)))); /* Make sure it indexes a partition of the other index's table */ - partDesc = RelationGetPartitionDesc(parentTbl); found = false; - for (i = 0; i < partDesc->nparts; i++) + Assert(partoids != NULL || nparts == 0); + for (i = 0; i < nparts; i++) { - if (partDesc->oids[i] == state.partitionOid) + if (partoids[i] == state.partitionOid) { found = true; break; @@ -14984,6 +14976,7 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) int tuples = 0; HeapTuple inhTup; bool updated = false; + int nparts = RelationGetPartitionCount(partedTbl); Assert(partedIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX); @@ -15023,7 +15016,7 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) * If we found as many inherited indexes as the partitioned table has * partitions, we're good; update pg_index to set indisvalid. */ - if (tuples == RelationGetPartitionDesc(partedTbl)->nparts) + if (tuples == nparts) { Relation idxRel; HeapTuple newtup; diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 02d2a0ffd7..5081f46dda 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -55,6 +55,7 @@ #include "utils/inval.h" #include "utils/lsyscache.h" #include "utils/memutils.h" +#include "utils/partcache.h" #include "utils/rel.h" #include "utils/snapmgr.h" #include "utils/syscache.h" @@ -1087,7 +1088,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, */ if (partition_recurse) { - PartitionDesc partdesc = RelationGetPartitionDesc(rel); + int nparts = RelationGetPartitionCount(rel); + Oid *partoids = RelationGetPartitionOids(rel); List *idxs = NIL; List *childTbls = NIL; ListCell *l; @@ -1119,7 +1121,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, oldcxt = MemoryContextSwitchTo(perChildCxt); /* Iterate to create the trigger on each existing partition */ - for (i = 0; i < partdesc->nparts; i++) + Assert(partoids != NULL || nparts == 0); + for (i = 0; i < nparts; i++) { Oid indexOnChild = InvalidOid; ListCell *l2; @@ -1128,14 +1131,14 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Node *qual; bool found_whole_row; - childTbl = heap_open(partdesc->oids[i], ShareRowExclusiveLock); + childTbl = heap_open(partoids[i], ShareRowExclusiveLock); /* Find which of the child indexes is the one on this partition */ if (OidIsValid(indexOid)) { forboth(l, idxs, l2, childTbls) { - if (lfirst_oid(l2) == partdesc->oids[i]) + if (lfirst_oid(l2) == partoids[i]) { indexOnChild = lfirst_oid(l); break; @@ -1144,7 +1147,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, if (!OidIsValid(indexOnChild)) elog(ERROR, "failed to find index matching index \"%s\" in partition \"%s\"", get_rel_name(indexOid), - get_rel_name(partdesc->oids[i])); + get_rel_name(partoids[i])); } /* @@ -1172,7 +1175,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, elog(ERROR, "unexpected whole-row reference found in trigger WHEN clause"); CreateTrigger(childStmt, queryString, - partdesc->oids[i], refRelOid, + partoids[i], refRelOid, InvalidOid, indexOnChild, funcoid, trigoid, qual, isInternal, true); @@ -1855,14 +1858,16 @@ EnableDisableTrigger(Relation rel, const char *tgname, if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && (TRIGGER_FOR_ROW(oldtrig->tgtype))) { - PartitionDesc partdesc = RelationGetPartitionDesc(rel); + int nparts = RelationGetPartitionCount(rel); + Oid *partoids = RelationGetPartitionOids(rel); int i; - for (i = 0; i < partdesc->nparts; i++) + Assert(partoids != NULL || nparts == 0); + for (i = 0; i < nparts; i++) { Relation part; - part = relation_open(partdesc->oids[i], lockmode); + part = relation_open(partoids[i], lockmode); EnableDisableTrigger(part, NameStr(oldtrig->tgname), fires_when, skip_system, lockmode); heap_close(part, NoLock); /* keep lock till commit */ diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 218645d43b..f04bd276ee 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -40,8 +40,8 @@ static void FormPartitionKeyDatum(PartitionDispatch pd, EState *estate, Datum *values, bool *isnull); -static int get_partition_for_tuple(Relation relation, Datum *values, - bool *isnull); +static int get_partition_for_tuple(PartitionDispatch pd, Datum *values, + bool *isnull); static char *ExecBuildSlotPartitionKeyDescription(Relation rel, Datum *values, bool *isnull, @@ -208,13 +208,11 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd, parent = pd[0]; while (true) { - PartitionDesc partdesc; TupleTableSlot *myslot = parent->tupslot; TupleConversionMap *map = parent->tupmap; int cur_index = -1; rel = parent->reldesc; - partdesc = RelationGetPartitionDesc(rel); /* * Convert the tuple to this parent's layout so that we can do certain @@ -245,13 +243,13 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd, * Nothing for get_partition_for_tuple() to do if there are no * partitions to begin with. */ - if (partdesc->nparts == 0) + if (parent->nparts == 0) { result = -1; break; } - cur_index = get_partition_for_tuple(rel, values, isnull); + cur_index = get_partition_for_tuple(parent, values, isnull); /* * cur_index < 0 means we failed to find a partition of this parent. @@ -881,8 +879,10 @@ get_partition_dispatch_recurse(Relation rel, Relation parent, List **pds, List **leaf_part_oids) { TupleDesc tupdesc = RelationGetDescr(rel); - PartitionDesc partdesc = RelationGetPartitionDesc(rel); PartitionKey partkey = RelationGetPartitionKey(rel); + int nparts = RelationGetPartitionCount(rel); + Oid *partoids = RelationGetPartitionOids(rel); + PartitionBoundInfo boundinfo = RelationGetPartitionBounds(rel); PartitionDispatch pd; int i; @@ -894,7 +894,8 @@ get_partition_dispatch_recurse(Relation rel, Relation parent, pd->reldesc = rel; pd->key = partkey; pd->keystate = NIL; - pd->partdesc = partdesc; + pd->nparts = nparts; + pd->boundinfo = boundinfo; if (parent != NULL) { /* @@ -939,10 +940,10 @@ get_partition_dispatch_recurse(Relation rel, Relation parent, * the tree. This value is used to continue the search in the next level * of the partition tree. */ - pd->indexes = (int *) palloc(partdesc->nparts * sizeof(int)); - for (i = 0; i < partdesc->nparts; i++) + pd->indexes = (int *) palloc(nparts * sizeof(int)); + for (i = 0; i < nparts; i++) { - Oid partrelid = partdesc->oids[i]; + Oid partrelid = partoids[i]; if (get_rel_relkind(partrelid) != RELKIND_PARTITIONED_TABLE) { @@ -1034,23 +1035,22 @@ FormPartitionKeyDatum(PartitionDispatch pd, * Finds partition of relation which accepts the partition key specified * in values and isnull * - * Return value is index of the partition (>= 0 and < partdesc->nparts) if one - * found or -1 if none found. + * Return value is index of the partition (>= 0 and < nparts) if one found or + * -1 if none found. */ -int -get_partition_for_tuple(Relation relation, Datum *values, bool *isnull) +static int +get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull) { int bound_offset; int part_index = -1; - PartitionKey key = RelationGetPartitionKey(relation); - PartitionDesc partdesc = RelationGetPartitionDesc(relation); + PartitionKey key = pd->key; + PartitionBoundInfo boundinfo = pd->boundinfo; /* Route as appropriate based on partitioning strategy. */ switch (key->strategy) { case PARTITION_STRATEGY_HASH: { - PartitionBoundInfo boundinfo = partdesc->boundinfo; int greatest_modulus = get_hash_partition_greatest_modulus(boundinfo); uint64 rowHash = compute_hash_value(key->partnatts, key->partsupfunc, @@ -1063,8 +1063,8 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull) case PARTITION_STRATEGY_LIST: if (isnull[0]) { - if (partition_bound_accepts_nulls(partdesc->boundinfo)) - part_index = partdesc->boundinfo->null_index; + if (partition_bound_accepts_nulls(boundinfo)) + part_index = boundinfo->null_index; } else { @@ -1072,10 +1072,10 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull) bound_offset = partition_list_bsearch(key->partsupfunc, key->partcollation, - partdesc->boundinfo, + boundinfo, values[0], &equal); if (bound_offset >= 0 && equal) - part_index = partdesc->boundinfo->indexes[bound_offset]; + part_index = boundinfo->indexes[bound_offset]; } break; @@ -1102,7 +1102,7 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull) { bound_offset = partition_range_datum_bsearch(key->partsupfunc, key->partcollation, - partdesc->boundinfo, + boundinfo, key->partnatts, values, &equal); @@ -1113,7 +1113,7 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull) * bound of the partition we're looking for, if there * actually exists one. */ - part_index = partdesc->boundinfo->indexes[bound_offset + 1]; + part_index = boundinfo->indexes[bound_offset + 1]; } } break; @@ -1128,7 +1128,7 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull) * the default partition, if there is one. */ if (part_index < 0) - part_index = partdesc->boundinfo->default_index; + part_index = boundinfo->default_index; return part_index; } @@ -1147,7 +1147,7 @@ ExecBuildSlotPartitionKeyDescription(Relation rel, int maxfieldlen) { StringInfoData buf; - PartitionKey key = RelationGetPartitionKey(rel); + PartitionKey key = RelationGetPartitionKey(rel); int partnatts = get_partition_natts(key); int i; Oid relid = RelationGetRelid(rel); @@ -1395,9 +1395,10 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) PartitionPruneInfo *pinfo = (PartitionPruneInfo *) lfirst(lc); PartitionPruningData *pprune = &prunedata[i]; PartitionPruneContext *context = &pprune->context; - PartitionDesc partdesc; Relation rel; PartitionKey partkey; + int nparts; + PartitionBoundInfo boundinfo; int partnatts; pprune->present_parts = bms_copy(pinfo->present_parts); @@ -1419,8 +1420,10 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) */ rel = relation_open(pinfo->reloid, NoLock); + /* Copy data from relcache into current memory context. */ partkey = RelationGetPartitionKey(rel); - partdesc = RelationGetPartitionDesc(rel); + nparts = RelationGetPartitionCount(rel); + boundinfo = RelationGetPartitionBounds(rel); context->strategy = partkey->strategy; context->partnatts = partnatts = partkey->partnatts; @@ -1428,8 +1431,8 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) context->partopcintype = partkey->partopcintype; context->partcollation = partkey->partcollation; context->partsupfunc = partkey->partsupfunc; - context->nparts = pinfo->nparts; - context->boundinfo = partition_bounds_copy(partdesc->boundinfo, partkey); + context->nparts = nparts; + context->boundinfo = boundinfo; context->planstate = planstate; context->safeparams = NULL; /* empty for now */ diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 8d86e98adc..8af2e21b27 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -49,6 +49,7 @@ #include "parser/parse_coerce.h" #include "parser/parsetree.h" #include "utils/lsyscache.h" +#include "utils/partcache.h" #include "utils/rel.h" #include "utils/selfuncs.h" @@ -1584,7 +1585,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) oldrelation = heap_open(parentOID, NoLock); /* Scan the inheritance set and expand it */ - if (RelationGetPartitionDesc(oldrelation) != NULL) + if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { Assert(rte->relkind == RELKIND_PARTITIONED_TABLE); @@ -1675,13 +1676,11 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, RangeTblEntry *childrte; Index childRTindex; bool has_child = false; - PartitionDesc partdesc = RelationGetPartitionDesc(parentrel); + int nparts = RelationGetPartitionCount(parentrel); + Oid *partoids = RelationGetPartitionOids(parentrel); check_stack_depth(); - /* A partitioned table should always have a partition descriptor. */ - Assert(partdesc); - Assert(parentrte->inh); /* @@ -1700,9 +1699,10 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte, top_parentrc, parentrel, appinfos, &childrte, &childRTindex); - for (i = 0; i < partdesc->nparts; i++) + Assert(partoids != NULL || nparts == 0); + for (i = 0; i < nparts; i++) { - Oid childOID = partdesc->oids[i]; + Oid childOID = partoids[i]; Relation childrel; /* Open rel; we already have required locks */ diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 1ff0ef4866..cfda6f2a34 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -27,7 +27,6 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/heap.h" -#include "catalog/partition.h" #include "catalog/pg_am.h" #include "catalog/pg_statistic_ext.h" #include "foreign/fdwapi.h" @@ -72,8 +71,9 @@ static List *build_index_tlist(PlannerInfo *root, IndexOptInfo *index, static List *get_relation_statistics(RelOptInfo *rel, Relation relation); static void set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel, Relation relation); -static PartitionScheme find_partition_scheme(PlannerInfo *root, Relation rel); -static void set_baserel_partition_key_exprs(Relation relation, +static PartitionScheme find_partition_scheme(PlannerInfo *root, Relation rel, + PartitionKey partkey); +static void set_baserel_partition_key_exprs(PartitionKey partkey, RelOptInfo *rel); /* @@ -1871,18 +1871,19 @@ static void set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel, Relation relation) { - PartitionDesc partdesc; - PartitionKey partkey; + PartitionKey partkey = RelationGetPartitionKey(relation); + int nparts = RelationGetPartitionCount(relation); + PartitionBoundInfo boundinfo = RelationGetPartitionBounds(relation); Assert(relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); + Assert(partkey != NULL); + Assert(boundinfo != NULL || nparts == 0); - partdesc = RelationGetPartitionDesc(relation); - partkey = RelationGetPartitionKey(relation); - rel->part_scheme = find_partition_scheme(root, relation); - Assert(partdesc != NULL && rel->part_scheme != NULL); - rel->boundinfo = partition_bounds_copy(partdesc->boundinfo, partkey); - rel->nparts = partdesc->nparts; - set_baserel_partition_key_exprs(relation, rel); + rel->part_scheme = find_partition_scheme(root, relation, partkey); + Assert(rel->part_scheme != NULL); + rel->boundinfo = boundinfo; + rel->nparts = nparts; + set_baserel_partition_key_exprs(partkey, rel); rel->partition_qual = RelationGetPartitionQual(relation); } @@ -1892,9 +1893,9 @@ set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel, * Find or create a PartitionScheme for this Relation. */ static PartitionScheme -find_partition_scheme(PlannerInfo *root, Relation relation) +find_partition_scheme(PlannerInfo *root, Relation rel, + PartitionKey partkey) { - PartitionKey partkey = RelationGetPartitionKey(relation); ListCell *lc; int partnatts, i; @@ -1935,10 +1936,7 @@ find_partition_scheme(PlannerInfo *root, Relation relation) /* * If partopfamily and partopcintype matched, must have the same - * partition comparison functions. Note that we cannot reliably - * Assert the equality of function structs themselves for they might - * be different across PartitionKey's, so just Assert for the function - * OIDs. + * partition comparison functions. */ #ifdef USE_ASSERT_CHECKING for (i = 0; i < partkey->partnatts; i++) @@ -1951,40 +1949,18 @@ find_partition_scheme(PlannerInfo *root, Relation relation) } /* - * Did not find matching partition scheme. Create one copying relevant - * information from the relcache. We need to copy the contents of the - * array since the relcache entry may not survive after we have closed the - * relation. + * Did not find matching partition scheme. Create one usinng the + * relevant information copied from the relcache. */ part_scheme = (PartitionScheme) palloc0(sizeof(PartitionSchemeData)); part_scheme->strategy = partkey->strategy; part_scheme->partnatts = partkey->partnatts; - - part_scheme->partopfamily = (Oid *) palloc(sizeof(Oid) * partnatts); - memcpy(part_scheme->partopfamily, partkey->partopfamily, - sizeof(Oid) * partnatts); - - part_scheme->partopcintype = (Oid *) palloc(sizeof(Oid) * partnatts); - memcpy(part_scheme->partopcintype, partkey->partopcintype, - sizeof(Oid) * partnatts); - - part_scheme->partcollation = (Oid *) palloc(sizeof(Oid) * partnatts); - memcpy(part_scheme->partcollation, partkey->partcollation, - sizeof(Oid) * partnatts); - - part_scheme->parttyplen = (int16 *) palloc(sizeof(int16) * partnatts); - memcpy(part_scheme->parttyplen, partkey->parttyplen, - sizeof(int16) * partnatts); - - part_scheme->parttypbyval = (bool *) palloc(sizeof(bool) * partnatts); - memcpy(part_scheme->parttypbyval, partkey->parttypbyval, - sizeof(bool) * partnatts); - - part_scheme->partsupfunc = (FmgrInfo *) - palloc(sizeof(FmgrInfo) * partnatts); - for (i = 0; i < partnatts; i++) - fmgr_info_copy(&part_scheme->partsupfunc[i], &partkey->partsupfunc[i], - CurrentMemoryContext); + part_scheme->partopfamily = partkey->partopfamily; + part_scheme->partopcintype = partkey->partopcintype; + part_scheme->partcollation = partkey->partcollation; + part_scheme->parttyplen = partkey->parttyplen; + part_scheme->parttypbyval = partkey->parttypbyval; + part_scheme->partsupfunc = partkey->partsupfunc; /* Add the partitioning scheme to PlannerInfo. */ root->part_schemes = lappend(root->part_schemes, part_scheme); @@ -2000,10 +1976,9 @@ find_partition_scheme(PlannerInfo *root, Relation relation) * nodes. All Var nodes are restamped with the relid of given relation. */ static void -set_baserel_partition_key_exprs(Relation relation, +set_baserel_partition_key_exprs(PartitionKey partkey, RelOptInfo *rel) { - PartitionKey partkey = RelationGetPartitionKey(relation); int partnatts; int cnt; List **partexprs; diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index c6f3628def..7b505ad8aa 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -3557,7 +3557,7 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd) { case RELKIND_PARTITIONED_TABLE: /* transform the partition bound, if any */ - Assert(RelationGetPartitionKey(parentRel) != NULL); + Assert(parentRel->rd_partkey != NULL); if (cmd->bound != NULL) cxt->partbound = transformPartitionBound(cxt->pstate, parentRel, cmd->bound); @@ -3598,7 +3598,7 @@ transformPartitionBound(ParseState *pstate, Relation parent, PartitionBoundSpec *spec) { PartitionBoundSpec *result_spec; - PartitionKey key = RelationGetPartitionKey(parent); + PartitionKey key = RelationGetPartitionKey(parent); char strategy = get_partition_strategy(key); int partnatts = get_partition_natts(key); List *partexprs = get_partition_exprs(key); diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index 229ce3ff5c..0d2064d617 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -307,9 +307,10 @@ void check_new_partition_bound(char *relname, Relation parent, PartitionBoundSpec *spec) { - PartitionKey key = RelationGetPartitionKey(parent); - PartitionDesc partdesc = RelationGetPartitionDesc(parent); - PartitionBoundInfo boundinfo = partdesc->boundinfo; + PartitionKey key = RelationGetPartitionKey(parent); + int nparts = RelationGetPartitionCount(parent); + Oid *partoids = RelationGetPartitionOids(parent); + PartitionBoundInfo boundinfo = RelationGetPartitionBounds(parent); ParseState *pstate = make_parsestate(NULL); int with = -1; bool overlap = false; @@ -329,7 +330,7 @@ check_new_partition_bound(char *relname, Relation parent, ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("partition \"%s\" conflicts with existing default partition \"%s\"", - relname, get_rel_name(partdesc->oids[boundinfo->default_index])), + relname, get_rel_name(partoids[boundinfo->default_index])), parser_errposition(pstate, spec->location))); } @@ -340,7 +341,7 @@ check_new_partition_bound(char *relname, Relation parent, Assert(spec->strategy == PARTITION_STRATEGY_HASH); Assert(spec->remainder >= 0 && spec->remainder < spec->modulus); - if (partdesc->nparts > 0) + if (nparts > 0) { Datum **datums = boundinfo->datums; int ndatums = boundinfo->ndatums; @@ -421,7 +422,7 @@ check_new_partition_bound(char *relname, Relation parent, { Assert(spec->strategy == PARTITION_STRATEGY_LIST); - if (partdesc->nparts > 0) + if (nparts > 0) { ListCell *cell; @@ -491,7 +492,7 @@ check_new_partition_bound(char *relname, Relation parent, parser_errposition(pstate, spec->location))); } - if (partdesc->nparts > 0) + if (nparts > 0) { int offset; bool equal; @@ -583,7 +584,7 @@ check_new_partition_bound(char *relname, Relation parent, ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("partition \"%s\" would overlap partition \"%s\"", - relname, get_rel_name(partdesc->oids[with])), + relname, get_rel_name(partoids[with])), parser_errposition(pstate, spec->location))); } } @@ -1431,8 +1432,7 @@ get_qual_for_list(Relation parent, PartitionBoundSpec *spec) { int i; int ndatums = 0; - PartitionDesc pdesc = RelationGetPartitionDesc(parent); - PartitionBoundInfo boundinfo = pdesc->boundinfo; + PartitionBoundInfo boundinfo = RelationGetPartitionBounds(parent); if (boundinfo) { @@ -1631,11 +1631,11 @@ get_qual_for_range(Relation parent, PartitionBoundSpec *spec, if (spec->is_default) { List *or_expr_args = NIL; - PartitionDesc pdesc = RelationGetPartitionDesc(parent); - Oid *inhoids = pdesc->oids; - int nparts = pdesc->nparts, + Oid *inhoids = RelationGetPartitionOids(parent); + int nparts = RelationGetPartitionCount(parent), i; + Assert(inhoids != NULL || nparts == 0); for (i = 0; i < nparts; i++) { Oid inhrelid = inhoids[i]; @@ -2156,11 +2156,17 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) parent = try_relation_open(parentId, AccessShareLock); if (parent == NULL) PG_RETURN_NULL(); - key = RelationGetPartitionKey(parent); /* Reject parent table that is not hash-partitioned. */ - if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE || - key->strategy != PARTITION_STRATEGY_HASH) + if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\"%s\" is not a hash partitioned table", + get_rel_name(parentId)))); + key = RelationGetPartitionKey(parent); + Assert(key != NULL); + + if (key->strategy != PARTITION_STRATEGY_HASH) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"%s\" is not a hash partitioned table", diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index 7666c6c412..f047e6e827 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -54,7 +54,6 @@ #include "optimizer/predtest.h" #include "optimizer/prep.h" #include "partitioning/partprune.h" -#include "partitioning/partbounds.h" #include "rewrite/rewriteManip.h" #include "utils/lsyscache.h" @@ -1962,8 +1961,8 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context, * * 'nvalues', the number of Datums in the 'values' array. * - * 'partsupfunc' contains partition hashing functions that can produce correct - * hash for the type of the values contained in 'values'. + * 'partsupfunc' contains partition hashing functions that can produce + * correct hash for the type of the values contained in 'values'. * * 'nullkeys' is the set of partition keys that are null. */ @@ -2000,7 +1999,8 @@ get_matching_hash_bounds(PartitionPruneContext *context, isnull[i] = bms_is_member(i, nullkeys); greatest_modulus = get_hash_partition_greatest_modulus(boundinfo); - rowHash = compute_hash_value(partnatts, partsupfunc, values, isnull); + rowHash = compute_hash_value(partnatts, partsupfunc, values, + isnull); if (partindices[rowHash % greatest_modulus] >= 0) result->bound_offsets = @@ -2029,8 +2029,8 @@ get_matching_hash_bounds(PartitionPruneContext *context, * * 'nvalues', if non-zero, should be exactly 1, because of list partitioning. * - * 'partsupfunc' contains the list partitioning comparison function to be used - * to perform partition_list_bsearch + * 'partsupfunc' contains the list partitioning comparison function to be + * used to perform partition_list_bsearch * * 'nullkeys' is the set of partition keys that are null. */ @@ -2102,8 +2102,8 @@ get_matching_list_bounds(PartitionPruneContext *context, result->bound_offsets = bms_add_range(NULL, 0, boundinfo->ndatums - 1); - off = partition_list_bsearch(partsupfunc, partcollation, boundinfo, - value, &is_equal); + off = partition_list_bsearch(partsupfunc, partcollation, + boundinfo, value, &is_equal); if (off >= 0 && is_equal) { @@ -2231,9 +2231,9 @@ get_matching_list_bounds(PartitionPruneContext *context, * * 'nvalues', number of Datums in 'values' array. Must be <= context->partnatts. * - * 'partsupfunc' contains the range partitioning comparison functions to be - * used to perform partition_range_datum_bsearch or partition_rbound_datum_cmp - * using. + * 'partsupfunc' contains the range partitioning comparison functions to + * be used to perform partition_range_datum_bsearch or + * partition_rbound_datum_cmp using. * * 'nullkeys' is the set of partition keys that are null. */ @@ -2797,7 +2797,8 @@ perform_pruning_base_step(PartitionPruneContext *context, cmpfn = lfirst_oid(lc2); Assert(OidIsValid(cmpfn)); if (cmpfn != context->partsupfunc[keyno].fn_oid) - fmgr_info(cmpfn, &partsupfunc[keyno]); + fmgr_info_cxt(cmpfn, &partsupfunc[keyno], + CurrentMemoryContext); else fmgr_info_copy(&partsupfunc[keyno], &context->partsupfunc[keyno], diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c index e2f677a46a..0c8bbec12d 100644 --- a/src/backend/utils/cache/partcache.c +++ b/src/backend/utils/cache/partcache.c @@ -36,20 +36,19 @@ #include "utils/rel.h" #include "utils/syscache.h" - -static List *generate_partition_qual(Relation rel); static int32 qsort_partition_hbound_cmp(const void *a, const void *b); static int32 qsort_partition_list_value_cmp(const void *a, const void *b, void *arg); static int32 qsort_partition_rbound_cmp(const void *a, const void *b, void *arg); - +static PartitionKey partition_key_copy(PartitionKey fromkey); +static List *generate_partition_qual(Relation rel); /* * RelationBuildPartitionKey * Build and attach to relcache partition key data of relation * - * Partitioning key data is a complex structure; to avoid complicated logic to + * Partition key data is of complex structure; to avoid complicated logic to * free individual elements whenever the relcache entry is flushed, we give it * its own memory context, child of CacheMemoryContext, which can easily be * deleted on its own. To avoid leaking memory in that context in case of an @@ -165,6 +164,7 @@ RelationBuildPartitionKey(Relation relation) key->parttypbyval = (bool *) palloc0(key->partnatts * sizeof(bool)); key->parttypalign = (char *) palloc0(key->partnatts * sizeof(char)); key->parttypcoll = (Oid *) palloc0(key->partnatts * sizeof(Oid)); + MemoryContextSwitchTo(oldcxt); /* determine support function number to search for */ @@ -206,6 +206,11 @@ RelationBuildPartitionKey(Relation relation) procnum, format_type_be(opclassform->opcintype)))); + /* + * Actually, we never use one of these FmgrInfo's without copying + * first to the caller's memory context, so setting the memory context + * here may seem pointless. + */ fmgr_info_cxt(funcid, &key->partsupfunc[i], partkeycxt); /* Collation */ @@ -791,6 +796,73 @@ RelationBuildPartitionDesc(Relation rel) } /* + * Functions to get a copy of partitioning infomation cached in RelationData. + */ + +PartitionKey +RelationGetPartitionKey(Relation relation) +{ + PartitionKey partkey = relation->rd_partkey; + + return partkey ? partition_key_copy(partkey) : NULL; +} + +int +RelationGetPartitionCount(Relation relation) +{ + PartitionDesc partdesc = relation->rd_partdesc; + + return partdesc->nparts; +} + +Oid * +RelationGetPartitionOids(Relation relation) +{ + PartitionDesc partdesc = relation->rd_partdesc; + Oid *result = NULL; + + Assert(partdesc != NULL); + if (partdesc->nparts > 0) + { + result = palloc(partdesc->nparts * sizeof(Oid)); + memcpy(result, partdesc->oids, partdesc->nparts * sizeof(Oid)); + } + + return result; +} + +PartitionBoundInfo +RelationGetPartitionBounds(Relation relation) +{ + PartitionDesc partdesc = relation->rd_partdesc; + + return partdesc->boundinfo + ? partition_bounds_copy(partdesc->boundinfo, + relation->rd_partkey) + : NULL; +} + +/* + * RelationGetDefaultPartitionOid + * + * Return the OID of the default partition, if one exists; else InvalidOid. + */ +Oid +RelationGetDefaultPartitionOid(Relation rel) +{ + PartitionBoundInfo boundinfo; + + /* Shouldn't be here otherwise! */ + Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); + boundinfo = rel->rd_partdesc->boundinfo; + + if (boundinfo && partition_bound_has_default(boundinfo)) + return rel->rd_partdesc->oids[boundinfo->default_index]; + + return InvalidOid; +} + +/* * RelationGetPartitionQual * * Returns a list of partition quals @@ -839,6 +911,66 @@ get_partition_qual_relid(Oid relid) } /* + * partition_key_copy + * + * The copy is allocated in the current memory context. + */ +static PartitionKey +partition_key_copy(PartitionKey fromkey) +{ + PartitionKey newkey; + int n, + i; + + Assert(fromkey != NULL); + + newkey = (PartitionKey) palloc(sizeof(PartitionKeyData)); + + newkey->strategy = fromkey->strategy; + newkey->partnatts = n = fromkey->partnatts; + + newkey->partattrs = (AttrNumber *) palloc(n * sizeof(AttrNumber)); + memcpy(newkey->partattrs, fromkey->partattrs, n * sizeof(AttrNumber)); + + newkey->partexprs = copyObject(fromkey->partexprs); + + newkey->partopfamily = (Oid *) palloc(n * sizeof(Oid)); + memcpy(newkey->partopfamily, fromkey->partopfamily, n * sizeof(Oid)); + + newkey->partopcintype = (Oid *) palloc(n * sizeof(Oid)); + memcpy(newkey->partopcintype, fromkey->partopcintype, n * sizeof(Oid)); + + newkey->partsupfunc = (FmgrInfo *) palloc(n * sizeof(FmgrInfo)); + for (i = 0; i < fromkey->partnatts; i++) + fmgr_info_copy(&newkey->partsupfunc[i], + &fromkey->partsupfunc[i], + CurrentMemoryContext); + + newkey->partcollation = (Oid *) palloc(n * sizeof(Oid)); + memcpy(newkey->partcollation, fromkey->partcollation, n * sizeof(Oid)); + + newkey->parttypid = (Oid *) palloc(n * sizeof(Oid)); + memcpy(newkey->parttypid, fromkey->parttypid, n * sizeof(Oid)); + + newkey->parttypmod = (int32 *) palloc(n * sizeof(int32)); + memcpy(newkey->parttypmod, fromkey->parttypmod, n * sizeof(int32)); + + newkey->parttyplen = (int16 *) palloc(n * sizeof(int16)); + memcpy(newkey->parttyplen, fromkey->parttyplen, n * sizeof(int16)); + + newkey->parttypbyval = (bool *) palloc(n * sizeof(bool)); + memcpy(newkey->parttypbyval, fromkey->parttypbyval, n * sizeof(bool)); + + newkey->parttypalign = (char *) palloc(n * sizeof(bool)); + memcpy(newkey->parttypalign, fromkey->parttypalign, n * sizeof(char)); + + newkey->parttypcoll = (Oid *) palloc(n * sizeof(Oid)); + memcpy(newkey->parttypcoll, fromkey->parttypcoll, n * sizeof(Oid)); + + return newkey; +} + +/* * generate_partition_qual * * Generate partition predicate from rel's partition bound expression. The diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 22ff36714c..86bff9c53b 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -43,7 +43,6 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/namespace.h" -#include "catalog/partition.h" #include "catalog/pg_am.h" #include "catalog/pg_amproc.h" #include "catalog/pg_attrdef.h" @@ -287,9 +286,6 @@ static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport); static void RelationCacheInitFileRemoveInDir(const char *tblspcpath); static void unlink_initfile(const char *initfilename); -static bool equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1, - PartitionDesc partdesc2); - /* * ScanPgRelation @@ -1002,60 +998,6 @@ equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2) } /* - * equalPartitionDescs - * Compare two partition descriptors for logical equality - */ -static bool -equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1, - PartitionDesc partdesc2) -{ - int i; - - if (partdesc1 != NULL) - { - if (partdesc2 == NULL) - return false; - if (partdesc1->nparts != partdesc2->nparts) - return false; - - Assert(key != NULL || partdesc1->nparts == 0); - - /* - * Same oids? If the partitioning structure did not change, that is, - * no partitions were added or removed to the relation, the oids array - * should still match element-by-element. - */ - for (i = 0; i < partdesc1->nparts; i++) - { - if (partdesc1->oids[i] != partdesc2->oids[i]) - return false; - } - - /* - * Now compare partition bound collections. The logic to iterate over - * the collections is private to partition.c. - */ - if (partdesc1->boundinfo != NULL) - { - if (partdesc2->boundinfo == NULL) - return false; - - if (!partition_bounds_equal(key->partnatts, key->parttyplen, - key->parttypbyval, - partdesc1->boundinfo, - partdesc2->boundinfo)) - return false; - } - else if (partdesc2->boundinfo != NULL) - return false; - } - else if (partdesc2 != NULL) - return false; - - return true; -} - -/* * RelationBuildDesc * * Build a relation descriptor. The caller must hold at least @@ -1183,7 +1125,10 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) relation->rd_fkeylist = NIL; relation->rd_fkeyvalid = false; - /* if a partitioned table, initialize key and partition descriptor info */ + /* + * If we need to initialize partitioning info, do that in a dedicated + * context that's attached to the cache context. + */ if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { RelationBuildPartitionKey(relation); @@ -1193,8 +1138,8 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) { relation->rd_partkeycxt = NULL; relation->rd_partkey = NULL; - relation->rd_partdesc = NULL; relation->rd_pdcxt = NULL; + relation->rd_partdesc = NULL; } /* @@ -2369,8 +2314,6 @@ RelationClearRelation(Relation relation, bool rebuild) bool keep_tupdesc; bool keep_rules; bool keep_policies; - bool keep_partkey; - bool keep_partdesc; /* Build temporary entry, but don't link it into hashtable */ newrel = RelationBuildDesc(save_relid, false); @@ -2401,10 +2344,6 @@ RelationClearRelation(Relation relation, bool rebuild) keep_tupdesc = equalTupleDescs(relation->rd_att, newrel->rd_att); keep_rules = equalRuleLocks(relation->rd_rules, newrel->rd_rules); keep_policies = equalRSDesc(relation->rd_rsdesc, newrel->rd_rsdesc); - keep_partkey = (relation->rd_partkey != NULL); - keep_partdesc = equalPartitionDescs(relation->rd_partkey, - relation->rd_partdesc, - newrel->rd_partdesc); /* * Perform swapping of the relcache entry contents. Within this @@ -2459,18 +2398,6 @@ RelationClearRelation(Relation relation, bool rebuild) SWAPFIELD(Oid, rd_toastoid); /* pgstat_info must be preserved */ SWAPFIELD(struct PgStat_TableStatus *, pgstat_info); - /* partition key must be preserved, if we have one */ - if (keep_partkey) - { - SWAPFIELD(PartitionKey, rd_partkey); - SWAPFIELD(MemoryContext, rd_partkeycxt); - } - /* preserve old partdesc if no logical change */ - if (keep_partdesc) - { - SWAPFIELD(PartitionDesc, rd_partdesc); - SWAPFIELD(MemoryContext, rd_pdcxt); - } #undef SWAPFIELD @@ -3708,19 +3635,11 @@ RelationCacheInitializePhase3(void) /* * Reload the partition key and descriptor for a partitioned table. */ - if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && - relation->rd_partkey == NULL) + if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { RelationBuildPartitionKey(relation); - Assert(relation->rd_partkey != NULL); - - restart = true; - } - - if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && - relation->rd_partdesc == NULL) - { RelationBuildPartitionDesc(relation); + Assert(relation->rd_partkey != NULL); Assert(relation->rd_partdesc != NULL); restart = true; diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h index 1f49e5d3a9..2cda9c9cad 100644 --- a/src/include/catalog/partition.h +++ b/src/include/catalog/partition.h @@ -37,8 +37,6 @@ extern List *map_partition_varattnos(List *expr, int fromrel_varno, bool *found_whole_row); extern bool has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr); - -extern Oid get_default_oid_from_partdesc(PartitionDesc partdesc); extern Oid get_default_partition_oid(Oid parentId); extern void update_default_partition_oid(Oid parentId, Oid defaultPartId); extern List *get_proposed_default_constraint(List *new_part_constaints); diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h index e81bdc4a0a..b5dc53bfcb 100644 --- a/src/include/executor/execPartition.h +++ b/src/include/executor/execPartition.h @@ -25,14 +25,15 @@ * reldesc Relation descriptor of the table * key Partition key information of the table * keystate Execution state required for expressions in the partition key - * partdesc Partition descriptor of the table + * nparts Number of partitions of the table + * boundinfo PartitionBoundInfo of the table * tupslot A standalone TupleTableSlot initialized with this table's tuple * descriptor * tupmap TupleConversionMap to convert from the parent's rowtype to * this table's rowtype (when extracting the partition key of a * tuple just before routing it through this table) - * indexes Array with partdesc->nparts members (for details on what - * individual members represent, see how they are set in + * indexes Array with nparts members (for details on what individual + * members represent, see how they are set in * get_partition_dispatch_recurse()) *----------------------- */ @@ -41,7 +42,8 @@ typedef struct PartitionDispatchData Relation reldesc; PartitionKey key; List *keystate; /* list of ExprState */ - PartitionDesc partdesc; + int nparts; + PartitionBoundInfo boundinfo; TupleTableSlot *tupslot; TupleConversionMap *tupmap; int *indexes; diff --git a/src/include/partitioning/partbounds.h b/src/include/partitioning/partbounds.h index 71c04aa446..9cdfc04018 100644 --- a/src/include/partitioning/partbounds.h +++ b/src/include/partitioning/partbounds.h @@ -16,7 +16,7 @@ #include "nodes/pg_list.h" #include "partitioning/partdefs.h" #include "utils/relcache.h" - +#include "utils/partcache.h" /* * PartitionBoundInfoData encapsulates a set of partition bounds. It is diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h index a5568abce6..114a9594be 100644 --- a/src/include/partitioning/partprune.h +++ b/src/include/partitioning/partprune.h @@ -14,7 +14,7 @@ #ifndef PARTPRUNE_H #define PARTPRUNE_H -#include "nodes/execnodes.h" +#include "partitioning/partbounds.h" #include "nodes/relation.h" diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h index c1d029fdb3..b037bb00d5 100644 --- a/src/include/utils/partcache.h +++ b/src/include/utils/partcache.h @@ -48,6 +48,11 @@ typedef struct PartitionKeyData extern void RelationBuildPartitionKey(Relation relation); extern void RelationBuildPartitionDesc(Relation rel); +extern PartitionKey RelationGetPartitionKey(Relation relation); +extern int RelationGetPartitionCount(Relation relation); +extern Oid *RelationGetPartitionOids(Relation relation); +extern PartitionBoundInfo RelationGetPartitionBounds(Relation relation); +extern Oid RelationGetDefaultPartitionOid(Relation rel); extern List *RelationGetPartitionQual(Relation rel); extern Expr *get_partition_qual_relid(Oid relid); diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 1d0461d295..f5b84ed60a 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -582,18 +582,6 @@ typedef struct ViewOptions RelationNeedsWAL(relation) && \ !IsCatalogRelation(relation)) -/* - * RelationGetPartitionKey - * Returns the PartitionKey of a relation - */ -#define RelationGetPartitionKey(relation) ((relation)->rd_partkey) - -/* - * RelationGetPartitionDesc - * Returns partition descriptor for a relation. - */ -#define RelationGetPartitionDesc(relation) ((relation)->rd_partdesc) - /* routines in utils/cache/relcache.c */ extern void RelationIncrementReferenceCount(Relation rel); extern void RelationDecrementReferenceCount(Relation rel); -- 2.11.0