diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execExprInterp.c | 2 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 79 | ||||
-rw-r--r-- | src/backend/executor/execPartition.c | 101 | ||||
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 24 |
4 files changed, 94 insertions, 112 deletions
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index f597363eb10..c549e3db5d9 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -3285,7 +3285,7 @@ ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext if (op->d.convert_rowtype.map != NULL) { /* Full conversion with attribute rearrangement needed */ - result = do_convert_tuple(&tmptup, op->d.convert_rowtype.map); + result = execute_attr_map_tuple(&tmptup, op->d.convert_rowtype.map); /* Result already has appropriate composite-datum header fields */ *op->resvalue = HeapTupleGetDatum(result); } diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 2b7cf263803..c28750e0753 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -1955,21 +1955,22 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, */ if (resultRelInfo->ri_PartitionRoot) { - HeapTuple tuple = ExecFetchSlotTuple(slot); TupleDesc old_tupdesc = RelationGetDescr(rel); - TupleConversionMap *map; + AttrNumber *map; rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); /* a reverse map */ - map = convert_tuples_by_name(old_tupdesc, tupdesc, - gettext_noop("could not convert row type")); + map = convert_tuples_by_name_map_if_req(old_tupdesc, tupdesc, + gettext_noop("could not convert row type")); + + /* + * Partition-specific slot's tupdesc can't be changed, so allocate a + * new one. + */ if (map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecSetSlotDescriptor(slot, tupdesc); - ExecStoreHeapTuple(tuple, slot, false); - } + slot = execute_attr_map_slot(map, slot, + MakeTupleTableSlot(tupdesc)); } insertedCols = GetInsertedColumns(resultRelInfo, estate); @@ -2035,20 +2036,22 @@ ExecConstraints(ResultRelInfo *resultRelInfo, */ if (resultRelInfo->ri_PartitionRoot) { - HeapTuple tuple = ExecFetchSlotTuple(slot); - TupleConversionMap *map; + AttrNumber *map; rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); /* a reverse map */ - map = convert_tuples_by_name(orig_tupdesc, tupdesc, - gettext_noop("could not convert row type")); + map = convert_tuples_by_name_map_if_req(orig_tupdesc, + tupdesc, + gettext_noop("could not convert row type")); + + /* + * Partition-specific slot's tupdesc can't be changed, so + * allocate a new one. + */ if (map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecSetSlotDescriptor(slot, tupdesc); - ExecStoreHeapTuple(tuple, slot, false); - } + slot = execute_attr_map_slot(map, slot, + MakeTupleTableSlot(tupdesc)); } insertedCols = GetInsertedColumns(resultRelInfo, estate); @@ -2082,21 +2085,23 @@ ExecConstraints(ResultRelInfo *resultRelInfo, /* See the comment above. */ if (resultRelInfo->ri_PartitionRoot) { - HeapTuple tuple = ExecFetchSlotTuple(slot); TupleDesc old_tupdesc = RelationGetDescr(rel); - TupleConversionMap *map; + AttrNumber *map; rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); /* a reverse map */ - map = convert_tuples_by_name(old_tupdesc, tupdesc, - gettext_noop("could not convert row type")); + map = convert_tuples_by_name_map_if_req(old_tupdesc, + tupdesc, + gettext_noop("could not convert row type")); + + /* + * Partition-specific slot's tupdesc can't be changed, so + * allocate a new one. + */ if (map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecSetSlotDescriptor(slot, tupdesc); - ExecStoreHeapTuple(tuple, slot, false); - } + slot = execute_attr_map_slot(map, slot, + MakeTupleTableSlot(tupdesc)); } insertedCols = GetInsertedColumns(resultRelInfo, estate); @@ -2188,21 +2193,23 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, /* See the comment in ExecConstraints(). */ if (resultRelInfo->ri_PartitionRoot) { - HeapTuple tuple = ExecFetchSlotTuple(slot); TupleDesc old_tupdesc = RelationGetDescr(rel); - TupleConversionMap *map; + AttrNumber *map; rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); /* a reverse map */ - map = convert_tuples_by_name(old_tupdesc, tupdesc, - gettext_noop("could not convert row type")); + map = convert_tuples_by_name_map_if_req(old_tupdesc, + tupdesc, + gettext_noop("could not convert row type")); + + /* + * Partition-specific slot's tupdesc can't be changed, + * so allocate a new one. + */ if (map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecSetSlotDescriptor(slot, tupdesc); - ExecStoreHeapTuple(tuple, slot, false); - } + slot = execute_attr_map_slot(map, slot, + MakeTupleTableSlot(tupdesc)); } insertedCols = GetInsertedColumns(resultRelInfo, estate); 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 { diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index bf0d5e8edb5..24beb40435e 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1161,11 +1161,9 @@ lreplace:; map_index = resultRelInfo - mtstate->resultRelInfo; Assert(map_index >= 0 && map_index < mtstate->mt_nplans); tupconv_map = tupconv_map_for_subplan(mtstate, map_index); - tuple = ConvertPartitionTupleSlot(tupconv_map, - tuple, - proute->root_tuple_slot, - &slot, - true); + if (tupconv_map != NULL) + slot = execute_attr_map_slot(tupconv_map->attrMap, + slot, proute->root_tuple_slot); /* * Prepare for tuple routing, making it look like we're inserting @@ -1703,6 +1701,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, int partidx; ResultRelInfo *partrel; HeapTuple tuple; + TupleConversionMap *map; /* * Determine the target partition. If ExecFindPartition does not find a @@ -1790,11 +1789,16 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, /* * Convert the tuple, if necessary. */ - ConvertPartitionTupleSlot(proute->parent_child_tupconv_maps[partidx], - tuple, - proute->partition_tuple_slot, - &slot, - true); + map = proute->parent_child_tupconv_maps[partidx]; + if (map != NULL) + { + TupleTableSlot *new_slot; + + Assert(proute->partition_tuple_slots != NULL && + proute->partition_tuple_slots[partidx] != NULL); + new_slot = proute->partition_tuple_slots[partidx]; + slot = execute_attr_map_slot(map->attrMap, slot, new_slot); + } /* Initialize information needed to handle ON CONFLICT DO UPDATE. */ Assert(mtstate != NULL); |