aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeModifyTable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeModifyTable.c')
-rw-r--r--src/backend/executor/nodeModifyTable.c70
1 files changed, 24 insertions, 46 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 14d25fd2aa8..b9bd86ff8fd 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1304,6 +1304,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
ExprContext *econtext = mtstate->ps.ps_ExprContext;
Relation relation = resultRelInfo->ri_RelationDesc;
ExprState *onConflictSetWhere = resultRelInfo->ri_onConflict->oc_WhereClause;
+ TupleTableSlot *existing = resultRelInfo->ri_onConflict->oc_Existing;
HeapTupleData tuple;
HeapUpdateFailureData hufd;
LockTupleMode lockmode;
@@ -1413,7 +1414,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
ExecCheckHeapTupleVisible(estate, &tuple, buffer);
/* Store target's existing tuple in the state's dedicated slot */
- ExecStoreBufferHeapTuple(&tuple, mtstate->mt_existing, buffer);
+ ExecStorePinnedBufferHeapTuple(&tuple, existing, buffer);
/*
* Make tuple and any needed join variables available to ExecQual and
@@ -1422,13 +1423,13 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
* has been made to reference INNER_VAR in setrefs.c, but there is no
* other redirection.
*/
- econtext->ecxt_scantuple = mtstate->mt_existing;
+ econtext->ecxt_scantuple = existing;
econtext->ecxt_innertuple = excludedSlot;
econtext->ecxt_outertuple = NULL;
if (!ExecQual(onConflictSetWhere, econtext))
{
- ReleaseBuffer(buffer);
+ ExecClearTuple(existing); /* see return below */
InstrCountFiltered1(&mtstate->ps, 1);
return true; /* done with the tuple */
}
@@ -1451,7 +1452,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
* INSERT or UPDATE path.
*/
ExecWithCheckOptions(WCO_RLS_CONFLICT_CHECK, resultRelInfo,
- mtstate->mt_existing,
+ existing,
mtstate->ps.state);
}
@@ -1469,11 +1470,17 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
/* Execute UPDATE with projection */
*returning = ExecUpdate(mtstate, &tuple.t_self, NULL,
- mtstate->mt_conflproj, planSlot,
+ resultRelInfo->ri_onConflict->oc_ProjSlot,
+ planSlot,
&mtstate->mt_epqstate, mtstate->ps.state,
canSetTag);
- ReleaseBuffer(buffer);
+ /*
+ * Clear out existing tuple, as there might not be another conflict among
+ * the next input rows. Don't want to hold resources till the end of the
+ * query.
+ */
+ ExecClearTuple(existing);
return true;
}
@@ -1633,7 +1640,6 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
ResultRelInfo *targetRelInfo,
TupleTableSlot *slot)
{
- ModifyTable *node;
ResultRelInfo *partrel;
PartitionRoutingInfo *partrouteinfo;
TupleConversionMap *map;
@@ -1698,19 +1704,6 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
slot = execute_attr_map_slot(map->attrMap, slot, new_slot);
}
- /* Initialize information needed to handle ON CONFLICT DO UPDATE. */
- Assert(mtstate != NULL);
- node = (ModifyTable *) mtstate->ps.plan;
- if (node->onConflictAction == ONCONFLICT_UPDATE)
- {
- Assert(mtstate->mt_existing != NULL);
- ExecSetSlotDescriptor(mtstate->mt_existing,
- RelationGetDescr(partrel->ri_RelationDesc));
- Assert(mtstate->mt_conflproj != NULL);
- ExecSetSlotDescriptor(mtstate->mt_conflproj,
- partrel->ri_onConflict->oc_ProjTupdesc);
- }
-
return slot;
}
@@ -2319,43 +2312,28 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
econtext = mtstate->ps.ps_ExprContext;
relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
- /*
- * Initialize slot for the existing tuple. If we'll be performing
- * tuple routing, the tuple descriptor to use for this will be
- * determined based on which relation the update is actually applied
- * to, so we don't set its tuple descriptor here.
- */
- mtstate->mt_existing =
- ExecInitExtraTupleSlot(mtstate->ps.state,
- mtstate->mt_partition_tuple_routing ?
- NULL : relationDesc, &TTSOpsBufferHeapTuple);
-
/* carried forward solely for the benefit of explain */
mtstate->mt_excludedtlist = node->exclRelTlist;
/* create state for DO UPDATE SET operation */
resultRelInfo->ri_onConflict = makeNode(OnConflictSetState);
- /*
- * Create the tuple slot for the UPDATE SET projection.
- *
- * Just like mt_existing above, we leave it without a tuple descriptor
- * in the case of partitioning tuple routing, so that it can be
- * changed by ExecPrepareTupleRouting. In that case, we still save
- * the tupdesc in the parent's state: it can be reused by partitions
- * with an identical descriptor to the parent.
- */
+ /* initialize slot for the existing tuple */
+ resultRelInfo->ri_onConflict->oc_Existing =
+ ExecInitExtraTupleSlot(mtstate->ps.state, relationDesc,
+ &TTSOpsBufferHeapTuple);
+
+ /* create the tuple slot for the UPDATE SET projection */
tupDesc = ExecTypeFromTL((List *) node->onConflictSet);
- mtstate->mt_conflproj =
- ExecInitExtraTupleSlot(mtstate->ps.state,
- mtstate->mt_partition_tuple_routing ?
- NULL : tupDesc, &TTSOpsHeapTuple);
- resultRelInfo->ri_onConflict->oc_ProjTupdesc = tupDesc;
+ resultRelInfo->ri_onConflict->oc_ProjSlot =
+ ExecInitExtraTupleSlot(mtstate->ps.state, tupDesc,
+ &TTSOpsVirtual);
/* build UPDATE SET projection state */
resultRelInfo->ri_onConflict->oc_ProjInfo =
ExecBuildProjectionInfo(node->onConflictSet, econtext,
- mtstate->mt_conflproj, &mtstate->ps,
+ resultRelInfo->ri_onConflict->oc_ProjSlot,
+ &mtstate->ps,
relationDesc);
/* initialize state to evaluate the WHERE clause, if any */