aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execExprInterp.c2
-rw-r--r--src/backend/executor/execMain.c79
-rw-r--r--src/backend/executor/execPartition.c101
-rw-r--r--src/backend/executor/nodeModifyTable.c24
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);