@@ -1304,6 +1304,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
1304
1304
ExprContext * econtext = mtstate -> ps .ps_ExprContext ;
1305
1305
Relation relation = resultRelInfo -> ri_RelationDesc ;
1306
1306
ExprState * onConflictSetWhere = resultRelInfo -> ri_onConflict -> oc_WhereClause ;
1307
+ TupleTableSlot * existing = resultRelInfo -> ri_onConflict -> oc_Existing ;
1307
1308
HeapTupleData tuple ;
1308
1309
HeapUpdateFailureData hufd ;
1309
1310
LockTupleMode lockmode ;
@@ -1413,7 +1414,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
1413
1414
ExecCheckHeapTupleVisible (estate , & tuple , buffer );
1414
1415
1415
1416
/* Store target's existing tuple in the state's dedicated slot */
1416
- ExecStoreBufferHeapTuple (& tuple , mtstate -> mt_existing , buffer );
1417
+ ExecStorePinnedBufferHeapTuple (& tuple , existing , buffer );
1417
1418
1418
1419
/*
1419
1420
* Make tuple and any needed join variables available to ExecQual and
@@ -1422,13 +1423,13 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
1422
1423
* has been made to reference INNER_VAR in setrefs.c, but there is no
1423
1424
* other redirection.
1424
1425
*/
1425
- econtext -> ecxt_scantuple = mtstate -> mt_existing ;
1426
+ econtext -> ecxt_scantuple = existing ;
1426
1427
econtext -> ecxt_innertuple = excludedSlot ;
1427
1428
econtext -> ecxt_outertuple = NULL ;
1428
1429
1429
1430
if (!ExecQual (onConflictSetWhere , econtext ))
1430
1431
{
1431
- ReleaseBuffer ( buffer );
1432
+ ExecClearTuple ( existing ); /* see return below */
1432
1433
InstrCountFiltered1 (& mtstate -> ps , 1 );
1433
1434
return true; /* done with the tuple */
1434
1435
}
@@ -1451,7 +1452,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
1451
1452
* INSERT or UPDATE path.
1452
1453
*/
1453
1454
ExecWithCheckOptions (WCO_RLS_CONFLICT_CHECK , resultRelInfo ,
1454
- mtstate -> mt_existing ,
1455
+ existing ,
1455
1456
mtstate -> ps .state );
1456
1457
}
1457
1458
@@ -1469,11 +1470,17 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
1469
1470
1470
1471
/* Execute UPDATE with projection */
1471
1472
* returning = ExecUpdate (mtstate , & tuple .t_self , NULL ,
1472
- mtstate -> mt_conflproj , planSlot ,
1473
+ resultRelInfo -> ri_onConflict -> oc_ProjSlot ,
1474
+ planSlot ,
1473
1475
& mtstate -> mt_epqstate , mtstate -> ps .state ,
1474
1476
canSetTag );
1475
1477
1476
- ReleaseBuffer (buffer );
1478
+ /*
1479
+ * Clear out existing tuple, as there might not be another conflict among
1480
+ * the next input rows. Don't want to hold resources till the end of the
1481
+ * query.
1482
+ */
1483
+ ExecClearTuple (existing );
1477
1484
return true;
1478
1485
}
1479
1486
@@ -1633,7 +1640,6 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
1633
1640
ResultRelInfo * targetRelInfo ,
1634
1641
TupleTableSlot * slot )
1635
1642
{
1636
- ModifyTable * node ;
1637
1643
ResultRelInfo * partrel ;
1638
1644
PartitionRoutingInfo * partrouteinfo ;
1639
1645
TupleConversionMap * map ;
@@ -1698,19 +1704,6 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
1698
1704
slot = execute_attr_map_slot (map -> attrMap , slot , new_slot );
1699
1705
}
1700
1706
1701
- /* Initialize information needed to handle ON CONFLICT DO UPDATE. */
1702
- Assert (mtstate != NULL );
1703
- node = (ModifyTable * ) mtstate -> ps .plan ;
1704
- if (node -> onConflictAction == ONCONFLICT_UPDATE )
1705
- {
1706
- Assert (mtstate -> mt_existing != NULL );
1707
- ExecSetSlotDescriptor (mtstate -> mt_existing ,
1708
- RelationGetDescr (partrel -> ri_RelationDesc ));
1709
- Assert (mtstate -> mt_conflproj != NULL );
1710
- ExecSetSlotDescriptor (mtstate -> mt_conflproj ,
1711
- partrel -> ri_onConflict -> oc_ProjTupdesc );
1712
- }
1713
-
1714
1707
return slot ;
1715
1708
}
1716
1709
@@ -2319,43 +2312,28 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
2319
2312
econtext = mtstate -> ps .ps_ExprContext ;
2320
2313
relationDesc = resultRelInfo -> ri_RelationDesc -> rd_att ;
2321
2314
2322
- /*
2323
- * Initialize slot for the existing tuple. If we'll be performing
2324
- * tuple routing, the tuple descriptor to use for this will be
2325
- * determined based on which relation the update is actually applied
2326
- * to, so we don't set its tuple descriptor here.
2327
- */
2328
- mtstate -> mt_existing =
2329
- ExecInitExtraTupleSlot (mtstate -> ps .state ,
2330
- mtstate -> mt_partition_tuple_routing ?
2331
- NULL : relationDesc , & TTSOpsBufferHeapTuple );
2332
-
2333
2315
/* carried forward solely for the benefit of explain */
2334
2316
mtstate -> mt_excludedtlist = node -> exclRelTlist ;
2335
2317
2336
2318
/* create state for DO UPDATE SET operation */
2337
2319
resultRelInfo -> ri_onConflict = makeNode (OnConflictSetState );
2338
2320
2339
- /*
2340
- * Create the tuple slot for the UPDATE SET projection.
2341
- *
2342
- * Just like mt_existing above, we leave it without a tuple descriptor
2343
- * in the case of partitioning tuple routing, so that it can be
2344
- * changed by ExecPrepareTupleRouting. In that case, we still save
2345
- * the tupdesc in the parent's state: it can be reused by partitions
2346
- * with an identical descriptor to the parent.
2347
- */
2321
+ /* initialize slot for the existing tuple */
2322
+ resultRelInfo -> ri_onConflict -> oc_Existing =
2323
+ ExecInitExtraTupleSlot (mtstate -> ps .state , relationDesc ,
2324
+ & TTSOpsBufferHeapTuple );
2325
+
2326
+ /* create the tuple slot for the UPDATE SET projection */
2348
2327
tupDesc = ExecTypeFromTL ((List * ) node -> onConflictSet );
2349
- mtstate -> mt_conflproj =
2350
- ExecInitExtraTupleSlot (mtstate -> ps .state ,
2351
- mtstate -> mt_partition_tuple_routing ?
2352
- NULL : tupDesc , & TTSOpsHeapTuple );
2353
- resultRelInfo -> ri_onConflict -> oc_ProjTupdesc = tupDesc ;
2328
+ resultRelInfo -> ri_onConflict -> oc_ProjSlot =
2329
+ ExecInitExtraTupleSlot (mtstate -> ps .state , tupDesc ,
2330
+ & TTSOpsVirtual );
2354
2331
2355
2332
/* build UPDATE SET projection state */
2356
2333
resultRelInfo -> ri_onConflict -> oc_ProjInfo =
2357
2334
ExecBuildProjectionInfo (node -> onConflictSet , econtext ,
2358
- mtstate -> mt_conflproj , & mtstate -> ps ,
2335
+ resultRelInfo -> ri_onConflict -> oc_ProjSlot ,
2336
+ & mtstate -> ps ,
2359
2337
relationDesc );
2360
2338
2361
2339
/* initialize state to evaluate the WHERE clause, if any */
0 commit comments