diff options
Diffstat (limited to 'src/backend/catalog/partition.c')
-rw-r--r-- | src/backend/catalog/partition.c | 74 |
1 files changed, 61 insertions, 13 deletions
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 9980582b777..fca874752f5 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -923,13 +923,19 @@ RelationGetPartitionQual(Relation rel, bool recurse) return generate_partition_qual(rel, recurse); } -/* Turn an array of OIDs with N elements into a list */ -#define OID_ARRAY_TO_LIST(arr, N, list) \ +/* + * Append OIDs of rel's partitions to the list 'partoids' and for each OID, + * append pointer rel to the list 'parents'. + */ +#define APPEND_REL_PARTITION_OIDS(rel, partoids, parents) \ do\ {\ int i;\ - for (i = 0; i < (N); i++)\ - (list) = lappend_oid((list), (arr)[i]);\ + for (i = 0; i < (rel)->rd_partdesc->nparts; i++)\ + {\ + (partoids) = lappend_oid((partoids), (rel)->rd_partdesc->oids[i]);\ + (parents) = lappend((parents), (rel));\ + }\ } while(0) /* @@ -944,11 +950,13 @@ PartitionDispatch * RelationGetPartitionDispatchInfo(Relation rel, int lockmode, int *num_parted, List **leaf_part_oids) { - PartitionDesc rootpartdesc = RelationGetPartitionDesc(rel); PartitionDispatchData **pd; List *all_parts = NIL, - *parted_rels; - ListCell *lc; + *all_parents = NIL, + *parted_rels, + *parted_rel_parents; + ListCell *lc1, + *lc2; int i, k, offset; @@ -965,10 +973,13 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode, */ *num_parted = 1; parted_rels = list_make1(rel); - OID_ARRAY_TO_LIST(rootpartdesc->oids, rootpartdesc->nparts, all_parts); - foreach(lc, all_parts) + /* Root partitioned table has no parent, so NULL for parent */ + parted_rel_parents = list_make1(NULL); + APPEND_REL_PARTITION_OIDS(rel, all_parts, all_parents); + forboth(lc1, all_parts, lc2, all_parents) { - Relation partrel = heap_open(lfirst_oid(lc), lockmode); + Relation partrel = heap_open(lfirst_oid(lc1), lockmode); + Relation parent = lfirst(lc2); PartitionDesc partdesc = RelationGetPartitionDesc(partrel); /* @@ -979,7 +990,8 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode, { (*num_parted)++; parted_rels = lappend(parted_rels, partrel); - OID_ARRAY_TO_LIST(partdesc->oids, partdesc->nparts, all_parts); + parted_rel_parents = lappend(parted_rel_parents, parent); + APPEND_REL_PARTITION_OIDS(partrel, all_parts, all_parents); } else heap_close(partrel, NoLock); @@ -1004,10 +1016,12 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode, sizeof(PartitionDispatchData *)); *leaf_part_oids = NIL; i = k = offset = 0; - foreach(lc, parted_rels) + forboth(lc1, parted_rels, lc2, parted_rel_parents) { - Relation partrel = lfirst(lc); + Relation partrel = lfirst(lc1); + Relation parent = lfirst(lc2); PartitionKey partkey = RelationGetPartitionKey(partrel); + TupleDesc tupdesc = RelationGetDescr(partrel); PartitionDesc partdesc = RelationGetPartitionDesc(partrel); int j, m; @@ -1017,6 +1031,27 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode, pd[i]->key = partkey; pd[i]->keystate = NIL; pd[i]->partdesc = partdesc; + if (parent != NULL) + { + /* + * For every partitioned table other than root, we must store + * a tuple table slot initialized with its tuple descriptor and + * a tuple conversion map to convert a tuple from its parent's + * rowtype to its own. That is to make sure that we are looking + * at the correct row using the correct tuple descriptor when + * computing its partition key for tuple routing. + */ + pd[i]->tupslot = MakeSingleTupleTableSlot(tupdesc); + pd[i]->tupmap = convert_tuples_by_name(RelationGetDescr(parent), + tupdesc, + gettext_noop("could not convert row type")); + } + else + { + /* Not required for the root partitioned table */ + pd[i]->tupslot = NULL; + pd[i]->tupmap = NULL; + } pd[i]->indexes = (int *) palloc(partdesc->nparts * sizeof(int)); /* @@ -1610,6 +1645,8 @@ get_partition_for_tuple(PartitionDispatch *pd, { PartitionKey key = parent->key; PartitionDesc partdesc = parent->partdesc; + TupleTableSlot *myslot = parent->tupslot; + TupleConversionMap *map = parent->tupmap; /* Quick exit */ if (partdesc->nparts == 0) @@ -1618,6 +1655,17 @@ get_partition_for_tuple(PartitionDispatch *pd, return -1; } + if (myslot != NULL) + { + HeapTuple tuple = ExecFetchSlotTuple(slot); + + ExecClearTuple(myslot); + Assert(map != NULL); + tuple = do_convert_tuple(tuple, map); + ExecStoreTuple(tuple, myslot, InvalidBuffer, true); + slot = myslot; + } + /* Extract partition key from tuple */ FormPartitionKeyDatum(parent, slot, estate, values, isnull); |