diff options
Diffstat (limited to 'src/backend/executor/execPartition.c')
-rw-r--r-- | src/backend/executor/execPartition.c | 101 |
1 files changed, 36 insertions, 65 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index ec7a5267c34..832c79b41ea 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -57,7 +57,7 @@ typedef struct PartitionDispatchData List *keystate; /* list of ExprState */ PartitionDesc partdesc; TupleTableSlot *tupslot; - TupleConversionMap *tupmap; + AttrNumber *tupmap; int *indexes; } PartitionDispatchData; @@ -144,17 +144,9 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel) * We need an additional tuple slot for storing transient tuples that * are converted to the root table descriptor. */ - proute->root_tuple_slot = MakeTupleTableSlot(NULL); + proute->root_tuple_slot = MakeTupleTableSlot(RelationGetDescr(rel)); } - /* - * Initialize an empty slot that will be used to manipulate tuples of any - * given partition's rowtype. It is attached to the caller-specified node - * (such as ModifyTableState) and released when the node finishes - * processing. - */ - proute->partition_tuple_slot = MakeTupleTableSlot(NULL); - i = 0; foreach(cell, leaf_parts) { @@ -228,7 +220,6 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd, TupleTableSlot *ecxt_scantuple_old = ecxt->ecxt_scantuple; TupleTableSlot *myslot = NULL; MemoryContext oldcxt; - HeapTuple tuple; /* use per-tuple context here to avoid leaking memory */ oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); @@ -241,11 +232,10 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd, ExecPartitionCheck(resultRelInfo, slot, estate, true); /* start with the root partitioned table */ - tuple = ExecFetchSlotTuple(slot); dispatch = pd[0]; while (true) { - TupleConversionMap *map = dispatch->tupmap; + AttrNumber *map = dispatch->tupmap; int cur_index = -1; rel = dispatch->reldesc; @@ -256,11 +246,7 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd, */ myslot = dispatch->tupslot; if (myslot != NULL && map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecStoreHeapTuple(tuple, myslot, true); - slot = myslot; - } + slot = execute_attr_map_slot(map, slot, myslot); /* * Extract partition key from tuple. Expression evaluation machinery @@ -305,16 +291,6 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd, { /* move down one level */ dispatch = pd[-dispatch->indexes[cur_index]]; - - /* - * Release the dedicated slot, if it was used. Create a copy of - * the tuple first, for the next iteration. - */ - if (slot == myslot) - { - tuple = ExecCopySlotTuple(myslot); - ExecClearTuple(myslot); - } } } @@ -739,6 +715,35 @@ ExecInitRoutingInfo(ModifyTableState *mtstate, gettext_noop("could not convert row type")); /* + * If a partition has a different rowtype than the root parent, initialize + * a slot dedicated to storing this partition's tuples. The slot is used + * for various operations that are applied to tuples after routing, such + * as checking constraints. + */ + if (proute->parent_child_tupconv_maps[partidx] != NULL) + { + Relation partrel = partRelInfo->ri_RelationDesc; + + /* + * Initialize the array in proute where these slots are stored, if not + * already done. + */ + if (proute->partition_tuple_slots == NULL) + proute->partition_tuple_slots = (TupleTableSlot **) + palloc0(proute->num_partitions * + sizeof(TupleTableSlot *)); + + /* + * Initialize the slot itself setting its descriptor to this + * partition's TupleDesc; TupleDesc reference will be released at the + * end of the command. + */ + proute->partition_tuple_slots[partidx] = + ExecInitExtraTupleSlot(estate, + RelationGetDescr(partrel)); + } + + /* * If the partition is a foreign table, let the FDW init itself for * routing tuples to the partition. */ @@ -816,38 +821,6 @@ TupConvMapForLeaf(PartitionTupleRouting *proute, } /* - * ConvertPartitionTupleSlot -- convenience function for tuple conversion. - * The tuple, if converted, is stored in new_slot, and *p_my_slot is - * updated to point to it. new_slot typically should be one of the - * dedicated partition tuple slots. If map is NULL, *p_my_slot is not changed. - * - * Returns the converted tuple, unless map is NULL, in which case original - * tuple is returned unmodified. - */ -HeapTuple -ConvertPartitionTupleSlot(TupleConversionMap *map, - HeapTuple tuple, - TupleTableSlot *new_slot, - TupleTableSlot **p_my_slot, - bool shouldFree) -{ - if (!map) - return tuple; - - tuple = do_convert_tuple(tuple, map); - - /* - * Change the partition tuple slot descriptor, as per converted tuple. - */ - *p_my_slot = new_slot; - Assert(new_slot != NULL); - ExecSetSlotDescriptor(new_slot, map->outdesc); - ExecStoreHeapTuple(tuple, new_slot, shouldFree); - - return tuple; -} - -/* * ExecCleanupTupleRouting -- Clean up objects allocated for partition tuple * routing. * @@ -915,8 +888,6 @@ ExecCleanupTupleRouting(ModifyTableState *mtstate, /* Release the standalone partition tuple descriptors, if any */ if (proute->root_tuple_slot) ExecDropSingleTupleTableSlot(proute->root_tuple_slot); - if (proute->partition_tuple_slot) - ExecDropSingleTupleTableSlot(proute->partition_tuple_slot); } /* @@ -1004,9 +975,9 @@ get_partition_dispatch_recurse(Relation rel, Relation parent, * for tuple routing. */ pd->tupslot = MakeSingleTupleTableSlot(tupdesc); - pd->tupmap = convert_tuples_by_name(RelationGetDescr(parent), - tupdesc, - gettext_noop("could not convert row type")); + pd->tupmap = convert_tuples_by_name_map_if_req(RelationGetDescr(parent), + tupdesc, + gettext_noop("could not convert row type")); } else { |