From 8966c8d2665e5a7955212472e5e0d7aa7fa48259 Mon Sep 17 00:00:00 2001 From: Amit Date: Sat, 14 Apr 2018 00:22:55 +0900 Subject: [PATCH v4 2/2] Reorganize partitioning cache info --- src/backend/catalog/heap.c | 2 +- src/backend/catalog/partition.c | 53 +++---- src/backend/catalog/pg_constraint.c | 8 +- src/backend/commands/indexcmds.c | 8 +- src/backend/commands/tablecmds.c | 75 +++++----- src/backend/commands/trigger.c | 22 +-- src/backend/executor/execMain.c | 1 - src/backend/executor/execPartition.c | 84 ++++++----- src/backend/optimizer/path/joinrels.c | 2 +- src/backend/optimizer/prep/prepunion.c | 13 +- src/backend/optimizer/util/plancat.c | 77 ++++------ src/backend/optimizer/util/relnode.c | 2 +- src/backend/parser/parse_utilcmd.c | 4 +- src/backend/partitioning/partbounds.c | 49 ++++--- src/backend/partitioning/partprune.c | 33 +++-- src/backend/utils/adt/ruleutils.c | 1 - src/backend/utils/cache/partcache.c | 252 ++++++++++++++++++++++++++++----- src/backend/utils/cache/relcache.c | 134 +++++------------- src/include/catalog/partition.h | 15 -- src/include/commands/tablecmds.h | 2 +- src/include/executor/execPartition.h | 12 +- src/include/partitioning/partbounds.h | 1 - src/include/partitioning/partprune.h | 4 +- src/include/utils/partcache.h | 17 ++- src/include/utils/rel.h | 33 +++-- 25 files changed, 520 insertions(+), 384 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 ad26adaf2f..e7e18d37da 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -274,28 +274,11 @@ has_partition_attrs(Relation rel, Bitmapset *attnums, return false; } -/* - * 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. Use get_default_partition_oid where possible, for efficiency. */ Oid get_default_partition_oid(Oid parentId) @@ -475,23 +458,39 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) if (my_extra == NULL || my_extra->relid != parentId) { Relation parent; - PartitionKey key; + PartitionKey key; + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; int j; /* Open parent relation and fetch partition keyinfo */ 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", + get_rel_name(parentId)))); + + /* Get partsupfunc FmgrInfo's. */ + for (j = 0; j < key->partnatts; j++) + { + fmgr_info_copy(&partsupfunc[j], + partition_getprocinfo(parent, key, j), + CurrentMemoryContext); + } + if (!get_fn_expr_variadic(fcinfo->flinfo)) { int nargs = PG_NARGS() - 3; @@ -506,7 +505,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) /* allocate space for our cache */ fcinfo->flinfo->fn_extra = MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, - offsetof(ColumnsHashData, partsupfunc) + + offsetof(ColumnsHashData, + partsupfunc) + sizeof(FmgrInfo) * nargs); my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra; my_extra->relid = parentId; @@ -524,7 +524,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) j + 1, format_type_be(key->parttypid[j]), format_type_be(argtype)))); fmgr_info_copy(&my_extra->partsupfunc[j], - &key->partsupfunc[j], + &partsupfunc[j], fcinfo->flinfo->fn_mcxt); } @@ -536,7 +536,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) /* allocate space for our cache -- just one FmgrInfo in this case */ fcinfo->flinfo->fn_extra = MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, - offsetof(ColumnsHashData, partsupfunc) + + offsetof(ColumnsHashData, + partsupfunc) + sizeof(FmgrInfo)); my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra; my_extra->relid = parentId; @@ -558,7 +559,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) format_type_be(my_extra->variadic_type)))); fmgr_info_copy(&my_extra->partsupfunc[0], - &key->partsupfunc[0], + &partsupfunc[0], fcinfo->flinfo->fn_mcxt); } diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 8ba9890ca6..32386b246f 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -623,12 +623,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 78302544db..913faddb55 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -877,15 +877,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++) @@ -901,6 +898,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 cc50691aa0..d4fdf1b556 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -1086,7 +1086,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; @@ -1118,7 +1119,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; @@ -1127,14 +1129,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; @@ -1143,7 +1145,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])); } /* @@ -1171,7 +1173,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); @@ -1854,14 +1856,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/execMain.c b/src/backend/executor/execMain.c index 4fa713bbe5..e885a16647 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -42,7 +42,6 @@ #include "access/transam.h" #include "access/xact.h" #include "catalog/namespace.h" -#include "catalog/partition.h" #include "catalog/pg_publication.h" #include "commands/matview.h" #include "commands/trigger.h" diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 1bf4412be5..e7652cbd25 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -22,6 +22,7 @@ #include "mb/pg_wchar.h" #include "miscadmin.h" #include "nodes/makefuncs.h" +#include "partitioning/partbounds.h" #include "utils/lsyscache.h" #include "utils/rls.h" #include "utils/ruleutils.h" @@ -35,7 +36,7 @@ static void FormPartitionKeyDatum(PartitionDispatch pd, EState *estate, Datum *values, bool *isnull); -static int get_partition_for_tuple(Relation relation, Datum *values, +static int get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull); static char *ExecBuildSlotPartitionKeyDescription(Relation rel, Datum *values, @@ -203,13 +204,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 @@ -240,13 +239,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. @@ -876,8 +875,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; @@ -889,7 +890,15 @@ get_partition_dispatch_recurse(Relation rel, Relation parent, pd->reldesc = rel; pd->key = partkey; pd->keystate = NIL; - pd->partdesc = partdesc; + /* Get partsupfunc FmgrInfo's. */ + for (i = 0; i < partkey->partnatts; i++) + { + fmgr_info_copy(&pd->partsupfunc[i], + partition_getprocinfo(rel, partkey, i), + CurrentMemoryContext); + } + pd->nparts = nparts; + pd->boundinfo = boundinfo; if (parent != NULL) { /* @@ -934,10 +943,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) { @@ -1029,26 +1038,26 @@ 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; + FmgrInfo *partsupfunc = pd->partsupfunc; + 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, + partsupfunc, values, isnull); part_index = boundinfo->indexes[rowHash % greatest_modulus]; @@ -1058,19 +1067,19 @@ 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 { bool equal = false; - bound_offset = partition_list_bsearch(key->partsupfunc, + bound_offset = partition_list_bsearch(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; @@ -1095,9 +1104,9 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull) if (!range_partkey_has_null) { - bound_offset = partition_range_datum_bsearch(key->partsupfunc, + bound_offset = partition_range_datum_bsearch(partsupfunc, key->partcollation, - partdesc->boundinfo, + boundinfo, key->partnatts, values, &equal); @@ -1108,7 +1117,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; @@ -1123,7 +1132,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; } @@ -1142,7 +1151,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); @@ -1390,10 +1399,12 @@ 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; + int j; pprune->present_parts = bms_copy(pinfo->present_parts); pprune->subnode_map = palloc(sizeof(int) * pinfo->nparts); @@ -1415,16 +1426,23 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) rel = relation_open(pinfo->reloid, NoLock); partkey = RelationGetPartitionKey(rel); - partdesc = RelationGetPartitionDesc(rel); + nparts = RelationGetPartitionCount(rel); + boundinfo = RelationGetPartitionBounds(rel); context->strategy = partkey->strategy; context->partnatts = partnatts = partkey->partnatts; context->partopfamily = partkey->partopfamily; context->partopcintype = partkey->partopcintype; context->partcollation = partkey->partcollation; - context->partsupfunc = partkey->partsupfunc; - context->nparts = pinfo->nparts; - context->boundinfo = partition_bounds_copy(partdesc->boundinfo, partkey); + /* Get partsupfunc FmgrInfo's. */ + for (j = 0; j < partkey->partnatts; j++) + { + fmgr_info_copy(&context->partsupfunc[j], + partition_getprocinfo(rel, partkey, j), + CurrentMemoryContext); + } + context->nparts = nparts; + context->boundinfo = boundinfo; context->planstate = planstate; context->safeparams = NULL; /* empty for now */ diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 2e289d475e..5d66cfb87b 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -15,12 +15,12 @@ #include "postgres.h" #include "miscadmin.h" -#include "catalog/partition.h" #include "optimizer/clauses.h" #include "optimizer/joininfo.h" #include "optimizer/pathnode.h" #include "optimizer/paths.h" #include "optimizer/prep.h" +#include "partitioning/partbounds.h" #include "utils/lsyscache.h" #include "utils/memutils.h" diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 8d86e98adc..23ce22a27e 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -1584,7 +1584,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 +1675,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 +1698,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 cb9cfc3729..23fed6a93e 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" @@ -45,8 +44,9 @@ #include "storage/bufmgr.h" #include "utils/builtins.h" #include "utils/lsyscache.h" -#include "utils/syscache.h" +#include "utils/partcache.h" #include "utils/rel.h" +#include "utils/syscache.h" #include "utils/snapmgr.h" @@ -70,8 +70,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); /* @@ -1869,18 +1870,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); } @@ -1890,9 +1892,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; @@ -1933,14 +1935,11 @@ 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++) - Assert(partkey->partsupfunc[i].fn_oid == + Assert(partkey->partsupfuncid[i] == part_scheme->partsupfunc[i].fn_oid); #endif @@ -1949,39 +1948,22 @@ 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->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 = (FmgrInfo *) palloc(sizeof(FmgrInfo) * partnatts); for (i = 0; i < partnatts; i++) - fmgr_info_copy(&part_scheme->partsupfunc[i], &partkey->partsupfunc[i], + fmgr_info_copy(&part_scheme->partsupfunc[i], + partition_getprocinfo(rel, partkey, i), CurrentMemoryContext); /* Add the partitioning scheme to PlannerInfo. */ @@ -1998,10 +1980,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/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index b9aa7486ba..fc19f892c5 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -17,7 +17,6 @@ #include #include "miscadmin.h" -#include "catalog/partition.h" #include "optimizer/clauses.h" #include "optimizer/cost.h" #include "optimizer/pathnode.h" @@ -27,6 +26,7 @@ #include "optimizer/prep.h" #include "optimizer/restrictinfo.h" #include "optimizer/tlist.h" +#include "partitioning/partbounds.h" #include "utils/hsearch.h" diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 9178139912..7889f8bfab 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -3556,7 +3556,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); @@ -3597,7 +3597,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 5c4fc90341..b25e74896b 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -311,8 +311,9 @@ check_new_partition_bound(char *relname, Relation parent, PartitionBoundSpec *spec) { PartitionKey key = RelationGetPartitionKey(parent); - PartitionDesc partdesc = RelationGetPartitionDesc(parent); - PartitionBoundInfo boundinfo = partdesc->boundinfo; + int nparts = RelationGetPartitionCount(parent); + Oid *partoids = RelationGetPartitionOids(parent); + PartitionBoundInfo boundinfo = RelationGetPartitionBounds(parent); ParseState *pstate = make_parsestate(NULL); int with = -1; bool overlap = false; @@ -332,7 +333,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))); } @@ -343,7 +344,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; @@ -422,9 +423,16 @@ check_new_partition_bound(char *relname, Relation parent, case PARTITION_STRATEGY_LIST: { + FmgrInfo partsupfunc; + Assert(spec->strategy == PARTITION_STRATEGY_LIST); - if (partdesc->nparts > 0) + /* Get partsupfunc FmgrInfo for the only key. */ + fmgr_info_copy(&partsupfunc, + partition_getprocinfo(parent, key, 0), + CurrentMemoryContext); + + if (nparts > 0) { ListCell *cell; @@ -443,7 +451,7 @@ check_new_partition_bound(char *relname, Relation parent, int offset; bool equal; - offset = partition_list_bsearch(&key->partsupfunc[0], + offset = partition_list_bsearch(&partsupfunc, key->partcollation, boundinfo, val->constvalue, @@ -471,6 +479,16 @@ check_new_partition_bound(char *relname, Relation parent, { PartitionRangeBound *lower, *upper; + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; + int i; + + /* Get partsupfunc FmgrInfo's. */ + for (i = 0; i < key->partnatts; i++) + { + fmgr_info_copy(&partsupfunc[i], + partition_getprocinfo(parent, key, i), + CurrentMemoryContext); + } Assert(spec->strategy == PARTITION_STRATEGY_RANGE); lower = make_one_range_bound(key, -1, spec->lowerdatums, true); @@ -480,7 +498,7 @@ check_new_partition_bound(char *relname, Relation parent, * First check if the resulting range would be empty with * specified lower and upper bounds */ - if (partition_rbound_cmp(key->partnatts, key->partsupfunc, + if (partition_rbound_cmp(key->partnatts, partsupfunc, key->partcollation, lower->datums, lower->kind, true, upper) >= 0) { @@ -494,7 +512,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; @@ -520,7 +538,7 @@ check_new_partition_bound(char *relname, Relation parent, * at the end. */ offset = partition_range_bsearch(key->partnatts, - key->partsupfunc, + partsupfunc, key->partcollation, boundinfo, lower, &equal); @@ -545,7 +563,7 @@ check_new_partition_bound(char *relname, Relation parent, is_lower = (boundinfo->indexes[offset + 1] == -1); cmpval = partition_rbound_cmp(key->partnatts, - key->partsupfunc, + partsupfunc, key->partcollation, datums, kind, is_lower, upper); @@ -586,7 +604,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))); } } @@ -1434,8 +1452,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) { @@ -1634,11 +1651,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]; diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index 7666c6c412..d506bc0264 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" @@ -437,7 +436,10 @@ prune_append_rel_partitions(RelOptInfo *rel) context.partopfamily = rel->part_scheme->partopfamily; context.partopcintype = rel->part_scheme->partopcintype; context.partcollation = rel->part_scheme->partcollation; - context.partsupfunc = rel->part_scheme->partsupfunc; + for (i = 0; i < context.partnatts; i++) + fmgr_info_copy(&context.partsupfunc[i], + &rel->part_scheme->partsupfunc[i], + CurrentMemoryContext); context.nparts = rel->nparts; context.boundinfo = rel->boundinfo; @@ -1413,7 +1415,8 @@ match_clause_to_partition_key(RelOptInfo *rel, partclause->op_is_ne = false; partclause->expr = expr; /* We know that expr is of Boolean type. */ - partclause->cmpfn = rel->part_scheme->partsupfunc[partkeyidx].fn_oid; + partclause->cmpfn = + rel->part_scheme->partsupfunc[partkeyidx].fn_oid; partclause->op_strategy = InvalidStrategy; *pc = partclause; @@ -1962,8 +1965,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 +2003,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 +2033,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 +2106,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 +2235,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 +2801,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/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 99643e83b2..ebcfa3b152 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -24,7 +24,6 @@ #include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" -#include "catalog/partition.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_am.h" #include "catalog/pg_authid.h" diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c index db91cde40a..c0a8be76bc 100644 --- a/src/backend/utils/cache/partcache.c +++ b/src/backend/utils/cache/partcache.c @@ -17,7 +17,6 @@ #include "access/hash.h" #include "access/htup_details.h" #include "access/nbtree.h" -#include "catalog/partition.h" #include "catalog/pg_inherits.h" #include "catalog/pg_opclass.h" #include "catalog/pg_operator.h" @@ -42,18 +41,37 @@ #include "utils/partcache.h" #include "utils/syscache.h" +/* + * Information about partitions of a partitioned table. + */ +typedef struct PartitionDescData +{ + int nparts; /* Number of partitions */ + Oid *oids; /* OIDs of partitions */ + PartitionBoundInfo boundinfo; /* collection of partition bounds */ +} PartitionDescData; + +typedef struct PartitionDescData *PartitionDesc; + +typedef struct PartitionBoundSortInfo +{ + FmgrInfo *partsupfunc; + PartitionKey key; +} PartitionBoundSortInfo; + 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 @@ -77,8 +95,7 @@ RelationBuildPartitionKey(Relation relation) oidvector *collation; ListCell *partexprs_item; Datum datum; - MemoryContext partkeycxt, - oldcxt; + MemoryContext oldcxt; int16 procnum; tuple = SearchSysCache1(PARTRELID, @@ -91,13 +108,7 @@ RelationBuildPartitionKey(Relation relation) if (!HeapTupleIsValid(tuple)) return; - partkeycxt = AllocSetContextCreate(CurTransactionContext, - "partition key", - ALLOCSET_SMALL_SIZES); - MemoryContextCopyAndSetIdentifier(partkeycxt, - RelationGetRelationName(relation)); - - key = (PartitionKey) MemoryContextAllocZero(partkeycxt, + key = (PartitionKey) MemoryContextAllocZero(relation->rd_partcxt, sizeof(PartitionKeyData)); /* Fixed-length attributes */ @@ -149,17 +160,16 @@ RelationBuildPartitionKey(Relation relation) expr = eval_const_expressions(NULL, expr); fix_opfuncids(expr); - oldcxt = MemoryContextSwitchTo(partkeycxt); + oldcxt = MemoryContextSwitchTo(relation->rd_partcxt); key->partexprs = (List *) copyObject(expr); MemoryContextSwitchTo(oldcxt); } - oldcxt = MemoryContextSwitchTo(partkeycxt); + oldcxt = MemoryContextSwitchTo(relation->rd_partcxt); key->partattrs = (AttrNumber *) palloc0(key->partnatts * sizeof(AttrNumber)); key->partopfamily = (Oid *) palloc0(key->partnatts * sizeof(Oid)); key->partopcintype = (Oid *) palloc0(key->partnatts * sizeof(Oid)); - key->partsupfunc = (FmgrInfo *) palloc0(key->partnatts * sizeof(FmgrInfo)); - + key->partsupfuncid = (Oid *) palloc0(key->partnatts * sizeof(Oid)); key->partcollation = (Oid *) palloc0(key->partnatts * sizeof(Oid)); /* Gather type and collation info as well */ @@ -169,6 +179,13 @@ 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)); + + /* + * Also allocate space for partition support procedure FmgrInfo's, but + * they won't be filled until somebody calls partition_get_procinfo. + */ + relation->rd_partsupfunc = (FmgrInfo *) + palloc0(key->partnatts * sizeof(FmgrInfo)); MemoryContextSwitchTo(oldcxt); /* determine support function number to search for */ @@ -210,7 +227,7 @@ RelationBuildPartitionKey(Relation relation) procnum, format_type_be(opclassform->opcintype)))); - fmgr_info_cxt(funcid, &key->partsupfunc[i], partkeycxt); + key->partsupfuncid[i] = funcid; /* Collation */ key->partcollation[i] = collation->values[i]; @@ -244,13 +261,6 @@ RelationBuildPartitionKey(Relation relation) } ReleaseSysCache(tuple); - - /* - * Success --- reparent our context and make the relcache point to the - * newly constructed key - */ - MemoryContextSetParent(partkeycxt, CacheMemoryContext); - relation->rd_partkeycxt = partkeycxt; relation->rd_partkey = key; } @@ -349,6 +359,20 @@ RelationBuildPartitionDesc(Relation rel) if (nparts > 0) { + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; + PartitionBoundSortInfo sortinfo; + + /* Get partsupfunc FmgrInfo's. */ + for (i = 0; i < key->partnatts; i++) + { + fmgr_info_copy(&partsupfunc[i], + partition_getprocinfo(rel, key, i), + CurrentMemoryContext); + } + + sortinfo.partsupfunc = partsupfunc; + sortinfo.key = key; + oids = (Oid *) palloc(nparts * sizeof(Oid)); i = 0; foreach(cell, partoids) @@ -466,7 +490,7 @@ RelationBuildPartitionDesc(Relation rel) } qsort_arg(all_values, ndatums, sizeof(PartitionListValue *), - qsort_partition_list_value_cmp, (void *) key); + qsort_partition_list_value_cmp, (void *) &sortinfo); } else if (key->strategy == PARTITION_STRATEGY_RANGE) { @@ -519,7 +543,7 @@ RelationBuildPartitionDesc(Relation rel) qsort_arg(all_bounds, ndatums, sizeof(PartitionRangeBound *), qsort_partition_rbound_cmp, - (void *) key); + (void *) &sortinfo); /* Save distinct bounds from all_bounds into rbounds. */ rbounds = (PartitionRangeBound **) @@ -551,7 +575,7 @@ RelationBuildPartitionDesc(Relation rel) if (cur->kind[j] != PARTITION_RANGE_DATUM_VALUE) break; - cmpval = FunctionCall2Coll(&key->partsupfunc[j], + cmpval = FunctionCall2Coll(&partsupfunc[j], key->partcollation[j], cur->datums[j], prev->datums[j]); @@ -582,12 +606,7 @@ RelationBuildPartitionDesc(Relation rel) } /* Now build the actual relcache partition descriptor */ - rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext, - "partition descriptor", - ALLOCSET_DEFAULT_SIZES); - MemoryContextCopyAndSetIdentifier(rel->rd_pdcxt, RelationGetRelationName(rel)); - - oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt); + oldcxt = MemoryContextSwitchTo(rel->rd_partcxt); result = (PartitionDescData *) palloc0(sizeof(PartitionDescData)); result->nparts = nparts; @@ -794,6 +813,107 @@ RelationBuildPartitionDesc(Relation rel) rel->rd_partdesc = result; } +/* + * 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; +} + +/* + * partition_getprocinfo + * Return fmgr lookup info of partition support procs from relcache + * + * If it's not been built yet by calling fmgr.c, do that and add it to + * relcache. + */ +FmgrInfo * +partition_getprocinfo(Relation rel, PartitionKey key, int partattoff) +{ + FmgrInfo *info; + + info = rel->rd_partsupfunc; + + Assert(info != NULL); + + info += partattoff; + + /* Initialize the lookup info if first time through */ + if (info->fn_oid == InvalidOid) + { + RegProcedure *func = key->partsupfuncid; + RegProcedure procId; + + Assert(func != NULL); + + procId = func[partattoff]; + Assert(RegProcedureIsValid(procId)); + fmgr_info_cxt(procId, info, rel->rd_partcxt); + } + + return info; +} + /* * RelationGetPartitionQual * @@ -867,9 +987,10 @@ qsort_partition_list_value_cmp(const void *a, const void *b, void *arg) { Datum val1 = (*(const PartitionListValue **) a)->value, val2 = (*(const PartitionListValue **) b)->value; - PartitionKey key = (PartitionKey) arg; + PartitionBoundSortInfo *sortinfo = (PartitionBoundSortInfo *) arg; + PartitionKey key = sortinfo->key; - return DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0], + return DatumGetInt32(FunctionCall2Coll(&sortinfo->partsupfunc[0], key->partcollation[0], val1, val2)); } @@ -880,13 +1001,70 @@ qsort_partition_rbound_cmp(const void *a, const void *b, void *arg) { PartitionRangeBound *b1 = (*(PartitionRangeBound *const *) a); PartitionRangeBound *b2 = (*(PartitionRangeBound *const *) b); - PartitionKey key = (PartitionKey) arg; + PartitionBoundSortInfo *sortinfo = (PartitionBoundSortInfo *) arg; + PartitionKey key = sortinfo->key; - return partition_rbound_cmp(key->partnatts, key->partsupfunc, + return partition_rbound_cmp(key->partnatts, sortinfo->partsupfunc, key->partcollation, b1->datums, b1->kind, b1->lower, b2); } +/* + * partition_key_copy + * + * The copy is allocated in the current memory context. + */ +static PartitionKey +partition_key_copy(PartitionKey fromkey) +{ + PartitionKey newkey; + int n; + + 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->partsupfuncid = (Oid *) palloc(n * sizeof(Oid)); + memcpy(newkey->partsupfuncid, fromkey->partsupfuncid, n * sizeof(Oid)); + + 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 * @@ -960,7 +1138,7 @@ generate_partition_qual(Relation rel) elog(ERROR, "unexpected whole-row reference found in partition key"); /* Save a copy in the relcache */ - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); + oldcxt = MemoryContextSwitchTo(rel->rd_partcxt); rel->rd_partcheck = copyObject(result); MemoryContextSwitchTo(oldcxt); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 5c17fe1742..aed32406f1 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" @@ -286,9 +285,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 @@ -1000,60 +996,6 @@ equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2) return true; } -/* - * 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 * @@ -1182,18 +1124,40 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) relation->rd_fkeylist = NIL; relation->rd_fkeyvalid = false; - /* if a partitioned table, initialize key and partition descriptor info */ - if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + /* + * 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 || + relation->rd_rel->relispartition) { - RelationBuildPartitionKey(relation); - RelationBuildPartitionDesc(relation); + relation->rd_partcxt = AllocSetContextCreate(CacheMemoryContext, + "partition info", + ALLOCSET_SMALL_SIZES); + MemoryContextCopyAndSetIdentifier(relation->rd_partcxt, + RelationGetRelationName(relation)); + + /* + * For a partitioned table, initialize partition key and partition + * descriptor. + */ + if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + { + RelationBuildPartitionKey(relation); + RelationBuildPartitionDesc(relation); + } + + /* + * Partition constraint of a partition itself is built only when + * needed. See RelationGetPartitionQual(). + */ } else { - relation->rd_partkeycxt = NULL; + relation->rd_partcxt = NULL; relation->rd_partkey = NULL; relation->rd_partdesc = NULL; - relation->rd_pdcxt = NULL; + relation->rd_partcheck = NIL; } /* @@ -2196,12 +2160,8 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc) MemoryContextDelete(relation->rd_rulescxt); if (relation->rd_rsdesc) MemoryContextDelete(relation->rd_rsdesc->rscxt); - if (relation->rd_partkeycxt) - MemoryContextDelete(relation->rd_partkeycxt); - if (relation->rd_pdcxt) - MemoryContextDelete(relation->rd_pdcxt); - if (relation->rd_partcheck) - pfree(relation->rd_partcheck); + if (relation->rd_partcxt) + MemoryContextDelete(relation->rd_partcxt); if (relation->rd_fdwroutine) pfree(relation->rd_fdwroutine); pfree(relation); @@ -2368,8 +2328,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); @@ -2400,10 +2358,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 @@ -2458,18 +2412,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 @@ -3707,19 +3649,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; @@ -5572,9 +5506,9 @@ load_relcache_init_file(bool shared) rel->rd_rulescxt = NULL; rel->trigdesc = NULL; rel->rd_rsdesc = NULL; - rel->rd_partkeycxt = NULL; + rel->rd_partcxt = NULL; rel->rd_partkey = NULL; - rel->rd_pdcxt = NULL; + rel->rd_partsupfunc = NULL; rel->rd_partdesc = NULL; rel->rd_partcheck = NIL; rel->rd_indexprs = NIL; diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h index 6ed013380b..6e468630b5 100644 --- a/src/include/catalog/partition.h +++ b/src/include/catalog/partition.h @@ -16,25 +16,12 @@ #include "fmgr.h" #include "executor/tuptable.h" #include "nodes/execnodes.h" -#include "partitioning/partbounds.h" #include "parser/parse_node.h" #include "utils/rel.h" /* Seed for the extended hash function */ #define HASH_PARTITION_SEED UINT64CONST(0x7A5B22367996DCFD) -/* - * Information about partitions of a partitioned table. - */ -typedef struct PartitionDescData -{ - int nparts; /* Number of partitions */ - Oid *oids; /* OIDs of partitions */ - PartitionBoundInfo boundinfo; /* collection of partition bounds */ -} PartitionDescData; - -typedef struct PartitionDescData *PartitionDesc; - extern Oid get_partition_parent(Oid relid); extern List *get_partition_ancestors(Oid relid); extern List *map_partition_varattnos(List *expr, int fromrel_varno, @@ -42,8 +29,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/commands/tablecmds.h b/src/include/commands/tablecmds.h index 70ee3da76b..eb3fd8a206 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -17,8 +17,8 @@ #include "access/htup.h" #include "catalog/dependency.h" #include "catalog/objectaddress.h" -#include "nodes/parsenodes.h" #include "catalog/partition.h" +#include "nodes/parsenodes.h" #include "storage/lock.h" #include "utils/relcache.h" diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h index e81bdc4a0a..47eedb91bb 100644 --- a/src/include/executor/execPartition.h +++ b/src/include/executor/execPartition.h @@ -25,14 +25,16 @@ * 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 + * partsupfunc fmgr lookup info of partition support functions + * 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 +43,9 @@ typedef struct PartitionDispatchData Relation reldesc; PartitionKey key; List *keystate; /* list of ExprState */ - PartitionDesc partdesc; + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; + 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 8bae4b2642..3e5f9dd920 100644 --- a/src/include/partitioning/partbounds.h +++ b/src/include/partitioning/partbounds.h @@ -11,7 +11,6 @@ #ifndef PARTBOUNDS_H #define PARTBOUNDS_H -#include "nodes/parsenodes.h" #include "utils/partcache.h" /* diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h index 2ae2fd16ed..5c44d9d212 100644 --- a/src/include/partitioning/partprune.h +++ b/src/include/partitioning/partprune.h @@ -14,7 +14,7 @@ #ifndef PARTPRUNE_H #define PARTPRUNE_H -#include "catalog/partition.h" +#include "partitioning/partbounds.h" #include "nodes/relation.h" /* @@ -30,7 +30,7 @@ typedef struct PartitionPruneContext Oid *partopfamily; Oid *partopcintype; Oid *partcollation; - FmgrInfo *partsupfunc; + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; /* Number of partitions */ int nparts; diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h index b9bde9fb7b..2a6f1ad700 100644 --- a/src/include/utils/partcache.h +++ b/src/include/utils/partcache.h @@ -27,7 +27,7 @@ typedef struct PartitionKeyData Oid *partopfamily; /* OIDs of operator families */ Oid *partopcintype; /* OIDs of opclass declared input data types */ - FmgrInfo *partsupfunc; /* lookup info for support funcs */ + Oid *partsupfuncid; /* partition support func OIDs */ /* Partitioning collation per attribute */ Oid *partcollation; @@ -43,8 +43,23 @@ typedef struct PartitionKeyData typedef struct PartitionKeyData *PartitionKey; +/* + * PartitionBoundInfo encapsulates a set of partition bounds. It is usually + * associated with partitioned tables as part of its partition descriptor. + * + * The internal structure appears in partbounds.h. + */ +typedef struct PartitionBoundInfoData *PartitionBoundInfo; + extern void RelationBuildPartitionKey(Relation relation); extern void RelationBuildPartitionDesc(Relation rel); +extern PartitionKey RelationGetPartitionKey(Relation relation); +extern FmgrInfo *partition_getprocinfo(Relation rel, PartitionKey key, + int partattoff); +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 bc74d04ce5..2c23704710 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -96,9 +96,11 @@ typedef struct RelationData List *rd_fkeylist; /* list of ForeignKeyCacheInfo (see below) */ bool rd_fkeyvalid; /* true if list has been computed */ - MemoryContext rd_partkeycxt; /* private memory cxt for the below */ + MemoryContext rd_partcxt; /* private memory cxt for the values contained + * in the fields related to partitioning */ struct PartitionKeyData *rd_partkey; /* partition key, or NULL */ - MemoryContext rd_pdcxt; /* private context for partdesc */ + FmgrInfo *rd_partsupfunc; /* lookup info for partition support + * procs */ struct PartitionDescData *rd_partdesc; /* partitions, or NULL */ List *rd_partcheck; /* partition CHECK quals */ @@ -218,6 +220,21 @@ typedef struct ForeignKeyCacheInfo Oid conpfeqop[INDEX_MAX_KEYS]; /* PK = FK operator OIDs */ } ForeignKeyCacheInfo; +/* + * PartitionInfo + * Information related to partitioning for a partitioned table + * + * This consists of the information from PartitionKey and PartitionDesc + * structs that are cached in the table's RelationData. + */ +typedef struct PartitionInfo +{ + PartitionKey key; + int nparts; + Oid *oids; + struct PartitionBoundInfoData *boundinfo; +} PartitionInfo; + /* * Options common for all all indexes */ @@ -583,12 +600,6 @@ typedef struct ViewOptions RelationNeedsWAL(relation) && \ !IsCatalogRelation(relation)) -/* - * RelationGetPartitionKey - * Returns the PartitionKey of a relation - */ -#define RelationGetPartitionKey(relation) ((relation)->rd_partkey) - /* * PartitionKey inquiry functions */ @@ -631,12 +642,6 @@ get_partition_col_typmod(PartitionKey key, int col) return key->parttypmod[col]; } -/* - * 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.15.1 (Apple Git-101)