From: =?UTF-8?q?=C3=81lvaro=20Herrera?= Date: Tue, 17 Mar 2026 17:21:14 +0100 Subject: [PATCH v1] table_tuple_update/_delete(): use an options bitmask This replaces a couple of booleans, making the interface more similar to what table_tuple_insert() uses, and better suited for future expansion. Discussion: https://postgr.es/m/202603171606.kf6pmhscqbqz@alvherre.pgsql --- src/backend/access/heap/heapam.c | 15 +++++---- src/backend/access/heap/heapam_handler.c | 10 +++--- src/backend/access/table/tableam.c | 3 +- src/backend/executor/nodeModifyTable.c | 11 ++++--- src/include/access/heapam.h | 6 ++-- src/include/access/tableam.h | 40 ++++++++++++++++-------- 6 files changed, 52 insertions(+), 33 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index e5bd062de77..1cf74ed8c46 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2852,8 +2852,8 @@ xmax_infomask_changed(uint16 new_infomask, uint16 old_infomask) */ TM_Result heap_delete(Relation relation, const ItemPointerData *tid, - CommandId cid, Snapshot crosscheck, bool wait, - TM_FailureData *tmfd, bool changingPart) + CommandId cid, Snapshot crosscheck, int options, + TM_FailureData *tmfd) { TM_Result result; TransactionId xid = GetCurrentTransactionId(); @@ -2863,6 +2863,8 @@ heap_delete(Relation relation, const ItemPointerData *tid, BlockNumber block; Buffer buffer; Buffer vmbuffer = InvalidBuffer; + bool wait = (options & TABLE_DELETE_WAIT) != 0; + bool changingPart = (options & TABLE_DELETE_CHANGING_PART) != 0; TransactionId new_xmax; uint16 new_infomask, new_infomask2; @@ -3281,8 +3283,8 @@ simple_heap_delete(Relation relation, const ItemPointerData *tid) result = heap_delete(relation, tid, GetCurrentCommandId(true), InvalidSnapshot, - true /* wait for commit */ , - &tmfd, false /* changingPart */ ); + TABLE_DELETE_WAIT, + &tmfd); switch (result) { case TM_SelfModified: @@ -3321,7 +3323,7 @@ simple_heap_delete(Relation relation, const ItemPointerData *tid) */ TM_Result heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup, - CommandId cid, Snapshot crosscheck, bool wait, + CommandId cid, Snapshot crosscheck, int options, TM_FailureData *tmfd, LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) { @@ -3340,6 +3342,7 @@ heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup, bool old_key_copied = false; Page page, newpage; + bool wait = (options & TABLE_UPDATE_WAIT) != 0; BlockNumber block; MultiXactStatus mxact_status; Buffer buffer, @@ -4576,7 +4579,7 @@ simple_heap_update(Relation relation, const ItemPointerData *otid, HeapTuple tup result = heap_update(relation, otid, tup, GetCurrentCommandId(true), InvalidSnapshot, - true /* wait for commit */ , + TABLE_UPDATE_WAIT, &tmfd, &lockmode, update_indexes); switch (result) { diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 253a735b6c1..3703d2d18a6 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -310,22 +310,22 @@ heapam_tuple_complete_speculative(Relation relation, TupleTableSlot *slot, static TM_Result heapam_tuple_delete(Relation relation, ItemPointer tid, CommandId cid, - Snapshot snapshot, Snapshot crosscheck, bool wait, - TM_FailureData *tmfd, bool changingPart) + Snapshot snapshot, Snapshot crosscheck, int options, + TM_FailureData *tmfd) { /* * Currently Deleting of index tuples are handled at vacuum, in case if * the storage itself is cleaning the dead tuples by itself, it is the * time to call the index tuple deletion also. */ - return heap_delete(relation, tid, cid, crosscheck, wait, tmfd, changingPart); + return heap_delete(relation, tid, cid, crosscheck, options, tmfd); } static TM_Result heapam_tuple_update(Relation relation, ItemPointer otid, TupleTableSlot *slot, CommandId cid, Snapshot snapshot, Snapshot crosscheck, - bool wait, TM_FailureData *tmfd, + int options, TM_FailureData *tmfd, LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) { bool shouldFree = true; @@ -336,7 +336,7 @@ heapam_tuple_update(Relation relation, ItemPointer otid, TupleTableSlot *slot, slot->tts_tableOid = RelationGetRelid(relation); tuple->t_tableOid = slot->tts_tableOid; - result = heap_update(relation, otid, tuple, cid, crosscheck, wait, + result = heap_update(relation, otid, tuple, cid, crosscheck, options, tmfd, lockmode, update_indexes); ItemPointerCopy(&tuple->t_self, &slot->tts_tid); diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c index dfda1af412e..4c759f29b3e 100644 --- a/src/backend/access/table/tableam.c +++ b/src/backend/access/table/tableam.c @@ -319,8 +319,7 @@ simple_table_tuple_delete(Relation rel, ItemPointer tid, Snapshot snapshot) result = table_tuple_delete(rel, tid, GetCurrentCommandId(true), snapshot, InvalidSnapshot, - true /* wait for commit */ , - &tmfd, false /* changingPart */ ); + TABLE_DELETE_WAIT, &tmfd); switch (result) { diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 4cd5e262e0f..680c29f35d5 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1522,14 +1522,17 @@ ExecDeleteAct(ModifyTableContext *context, ResultRelInfo *resultRelInfo, ItemPointer tupleid, bool changingPart) { EState *estate = context->estate; + int options = TABLE_DELETE_WAIT; + + if (changingPart) + options |= TABLE_DELETE_CHANGING_PART; return table_tuple_delete(resultRelInfo->ri_RelationDesc, tupleid, estate->es_output_cid, estate->es_snapshot, estate->es_crosscheck_snapshot, - true /* wait for commit */ , - &context->tmfd, - changingPart); + options, + &context->tmfd); } /* @@ -2333,7 +2336,7 @@ lreplace: estate->es_output_cid, estate->es_snapshot, estate->es_crosscheck_snapshot, - true /* wait for commit */ , + TABLE_UPDATE_WAIT, &context->tmfd, &updateCxt->lockmode, &updateCxt->updateIndexes); diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 2fdc50b865b..f74ba9817a7 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -385,13 +385,13 @@ extern void heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, CommandId cid, int options, BulkInsertState bistate); extern TM_Result heap_delete(Relation relation, const ItemPointerData *tid, - CommandId cid, Snapshot crosscheck, bool wait, - TM_FailureData *tmfd, bool changingPart); + CommandId cid, Snapshot crosscheck, int options, + TM_FailureData *tmfd); extern void heap_finish_speculative(Relation relation, const ItemPointerData *tid); extern void heap_abort_speculative(Relation relation, const ItemPointerData *tid); extern TM_Result heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup, - CommandId cid, Snapshot crosscheck, bool wait, + CommandId cid, Snapshot crosscheck, int options, TM_FailureData *tmfd, LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes); extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple, diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index 06084752245..15f6d6a3436 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -260,6 +260,13 @@ typedef struct TM_IndexDeleteOp #define TABLE_INSERT_FROZEN 0x0004 #define TABLE_INSERT_NO_LOGICAL 0x0008 +/* "options" flag bits for table_tuple_update */ +#define TABLE_UPDATE_WAIT 0x0001 + +/* "options" flag bits for table_tuple_delete */ +#define TABLE_DELETE_WAIT 0x0001 +#define TABLE_DELETE_CHANGING_PART 0x0002 + /* flag bits for table_tuple_lock */ /* Follow tuples whose update is in progress if lock modes don't conflict */ #define TUPLE_LOCK_FLAG_LOCK_UPDATE_IN_PROGRESS (1 << 0) @@ -535,9 +542,8 @@ typedef struct TableAmRoutine CommandId cid, Snapshot snapshot, Snapshot crosscheck, - bool wait, - TM_FailureData *tmfd, - bool changingPart); + int options, + TM_FailureData *tmfd); /* see table_tuple_update() for reference about parameters */ TM_Result (*tuple_update) (Relation rel, @@ -546,7 +552,7 @@ typedef struct TableAmRoutine CommandId cid, Snapshot snapshot, Snapshot crosscheck, - bool wait, + int options, TM_FailureData *tmfd, LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes); @@ -1459,9 +1465,14 @@ table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots, * cid - delete command ID (used for visibility test, and stored into * cmax if successful) * crosscheck - if not InvalidSnapshot, also check tuple against this - * wait - true if should wait for any conflicting update to commit/abort - * changingPart - true iff the tuple is being moved to another partition - * table due to an update of the partition key. Otherwise, false. + * options - These allow the caller to specify options that may change + * the behavior of the AM. The AM will ignore options that it does not + * support. + * TABLE_DELETE_WAIT -- set if should wait for any conflicting + * update/delete to commit/abort + * TABLE_DELETE_CHANGING_PART -- set iff the tuple is being moved to + * another partition table due to an update of the partition key. + * Otherwise, false. * * Output parameters: * tmfd - filled in failure cases (see below) @@ -1476,12 +1487,12 @@ table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots, */ static inline TM_Result table_tuple_delete(Relation rel, ItemPointer tid, CommandId cid, - Snapshot snapshot, Snapshot crosscheck, bool wait, - TM_FailureData *tmfd, bool changingPart) + Snapshot snapshot, Snapshot crosscheck, int options, + TM_FailureData *tmfd) { return rel->rd_tableam->tuple_delete(rel, tid, cid, snapshot, crosscheck, - wait, tmfd, changingPart); + options, tmfd); } /* @@ -1496,7 +1507,10 @@ table_tuple_delete(Relation rel, ItemPointer tid, CommandId cid, * cid - update command ID (used for visibility test, and stored into * cmax/cmin if successful) * crosscheck - if not InvalidSnapshot, also check old tuple against this - * wait - true if should wait for any conflicting update to commit/abort + * options - These allow the caller to specify options that may change the + * behavior of the AM. The AM will ignore options that it does not support. + * TABLE_UPDATE_WAIT -- set if should wait for any conflicting update to + * commit/abort * * Output parameters: * slot - newly constructed tuple data to store @@ -1522,12 +1536,12 @@ table_tuple_delete(Relation rel, ItemPointer tid, CommandId cid, static inline TM_Result table_tuple_update(Relation rel, ItemPointer otid, TupleTableSlot *slot, CommandId cid, Snapshot snapshot, Snapshot crosscheck, - bool wait, TM_FailureData *tmfd, LockTupleMode *lockmode, + int options, TM_FailureData *tmfd, LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) { return rel->rd_tableam->tuple_update(rel, otid, slot, cid, snapshot, crosscheck, - wait, tmfd, + options, tmfd, lockmode, update_indexes); } -- 2.47.3 --haawnpa7dlqdm5s2--