aboutsummaryrefslogtreecommitdiff
path: root/src/backend/catalog/partition.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/partition.c')
-rw-r--r--src/backend/catalog/partition.c74
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);