diff options
Diffstat (limited to 'src/backend/executor/nodeModifyTable.c')
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 70 |
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 */ |