Skip to content

Commit 764da77

Browse files
committed
Evade extra table_tuple_fetch_row_version() in ExecUpdate()/ExecDelete()
When we lock tuple using table_tuple_lock() then we at the same time fetch the locked tuple to the slot. In this case we can skip extra table_tuple_fetch_row_version() thank to we've already fetched the 'old' tuple and nobody can change it concurrently since it's locked. Discussion: https://postgr.es/m/CAPpHfdua-YFw3XTprfutzGp28xXLigFtzNbuFY8yPhqeq6X5kg%40mail.gmail.com Reviewed-by: Aleksander Alekseev, Pavel Borisov, Vignesh C, Mason Sharp Reviewed-by: Andres Freund, Chris Travers
1 parent c75a623 commit 764da77

File tree

1 file changed

+35
-13
lines changed

1 file changed

+35
-13
lines changed

src/backend/executor/nodeModifyTable.c

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,22 @@ ExecDelete(ModifyTableContext *context,
15591559
{
15601560
case TM_Ok:
15611561
Assert(context->tmfd.traversed);
1562+
1563+
/*
1564+
* Save locked tuple for further processing of
1565+
* RETURNING clause.
1566+
*/
1567+
if (processReturning &&
1568+
resultRelInfo->ri_projectReturning &&
1569+
!resultRelInfo->ri_FdwRoutine)
1570+
{
1571+
TupleTableSlot *returningSlot;
1572+
1573+
returningSlot = ExecGetReturningSlot(estate, resultRelInfo);
1574+
ExecCopySlot(returningSlot, inputslot);
1575+
ExecMaterializeSlot(returningSlot);
1576+
}
1577+
15621578
epqslot = EvalPlanQual(context->epqstate,
15631579
resultRelationDesc,
15641580
resultRelInfo->ri_RangeTableIndex,
@@ -1673,12 +1689,17 @@ ExecDelete(ModifyTableContext *context,
16731689
}
16741690
else
16751691
{
1692+
/*
1693+
* Tuple can be already fetched to the returning slot in case
1694+
* we've previously locked it. Fetch the tuple only if the slot
1695+
* is empty.
1696+
*/
16761697
slot = ExecGetReturningSlot(estate, resultRelInfo);
16771698
if (oldtuple != NULL)
16781699
{
16791700
ExecForceStoreHeapTuple(oldtuple, slot, false);
16801701
}
1681-
else
1702+
else if (TupIsNull(slot))
16821703
{
16831704
if (!table_tuple_fetch_row_version(resultRelationDesc, tupleid,
16841705
SnapshotAny, slot))
@@ -2393,6 +2414,19 @@ ExecUpdate(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
23932414
case TM_Ok:
23942415
Assert(context->tmfd.traversed);
23952416

2417+
/* Make sure ri_oldTupleSlot is initialized. */
2418+
if (unlikely(!resultRelInfo->ri_projectNewInfoValid))
2419+
ExecInitUpdateProjection(context->mtstate,
2420+
resultRelInfo);
2421+
2422+
/*
2423+
* Save the locked tuple for further calculation
2424+
* of the new tuple.
2425+
*/
2426+
oldSlot = resultRelInfo->ri_oldTupleSlot;
2427+
ExecCopySlot(oldSlot, inputslot);
2428+
ExecMaterializeSlot(oldSlot);
2429+
23962430
epqslot = EvalPlanQual(context->epqstate,
23972431
resultRelationDesc,
23982432
resultRelInfo->ri_RangeTableIndex,
@@ -2401,18 +2435,6 @@ ExecUpdate(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
24012435
/* Tuple not passing quals anymore, exiting... */
24022436
return NULL;
24032437

2404-
/* Make sure ri_oldTupleSlot is initialized. */
2405-
if (unlikely(!resultRelInfo->ri_projectNewInfoValid))
2406-
ExecInitUpdateProjection(context->mtstate,
2407-
resultRelInfo);
2408-
2409-
/* Fetch the most recent version of old tuple. */
2410-
oldSlot = resultRelInfo->ri_oldTupleSlot;
2411-
if (!table_tuple_fetch_row_version(resultRelationDesc,
2412-
tupleid,
2413-
SnapshotAny,
2414-
oldSlot))
2415-
elog(ERROR, "failed to fetch tuple being updated");
24162438
slot = ExecGetUpdateNewTuple(resultRelInfo,
24172439
epqslot, oldSlot);
24182440
goto redo_act;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy