On 2026-Apr-01, Chao Li wrote: > 1 - 0001 > For table_tuple_delete(), options is added and changingPart is > removed, but the header comment should be updated to reflect the > change.
True, fixed. > 2 - 0002 > For table_tuple_update(), options is added, the header comment should > be updated as well. Done. > 3 - 0002 > Now TABLE_INSERT_SKIP_FSM, TABLE_INSERT_FROZEN, TABLE_INSERT_NO_LOGICAL > belong to the same options word as HEAP_INSERT_SPECULATIVE, but they are > still defined as: > ``` > #define TABLE_INSERT_SKIP_FSM 0x0002 > #define TABLE_INSERT_FROZEN 0x0004 > #define TABLE_INSERT_NO_LOGICAL 0x0008 > ``` > > Could it make sense to change them to the left-shift form? Yeah, I don't know. I don't like this style, but some people like it, and I don't want to get into an argument about this kind of thing. > 4 - 0002 > In heap_multi_insert(), heap_prepare_insert(), and heap_insert(), > options is defined as uint32, but in RelationGetBufferForTuple() and > raw_heap_insert() it is still defined as int. Would it make sense to > take this opportunity to change all “options" to uint32 for > consistency? Otherwise, if this is left for later, a trivial follow-up > patch just to change int to uint32 may be harder to get processed. Hmm, this is actually a problem in 1bd6f22f43ac. I added a preliminary patch that should fix this. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/ "No renuncies a nada. No te aferres a nada."
>From 368d46e17eaff4b79a8451713169c3580348c3fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Herrera?= <[email protected]> Date: Wed, 1 Apr 2026 15:06:15 +0200 Subject: [PATCH v5 1/3] Fix callers of heap_insert and siblings to use uint32 for options, not int Oversight in commit 1bd6f22f43ac: I was way too optimistic about the compiler letting me know what variables needed to be updated, and missed a few of them. Clean it up. Reported-by: Chao Li <[email protected]> Discussion: https://postgr.es/m/[email protected] --- src/backend/access/common/toast_internals.c | 2 +- src/backend/access/heap/heaptoast.c | 2 +- src/backend/access/heap/hio.c | 2 +- src/backend/access/heap/rewriteheap.c | 2 +- src/backend/access/table/toast_helper.c | 2 +- src/backend/commands/copyfrom.c | 8 ++++---- src/backend/commands/createas.c | 2 +- src/backend/commands/matview.c | 2 +- src/backend/commands/tablecmds.c | 8 ++++---- src/include/access/heaptoast.h | 2 +- src/include/access/hio.h | 2 +- src/include/access/toast_helper.h | 2 +- src/include/access/toast_internals.h | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/backend/access/common/toast_internals.c b/src/backend/access/common/toast_internals.c index 4d0da07135e..77d42e7ed65 100644 --- a/src/backend/access/common/toast_internals.c +++ b/src/backend/access/common/toast_internals.c @@ -117,7 +117,7 @@ toast_compress_datum(Datum value, char cmethod) */ Datum toast_save_datum(Relation rel, Datum value, - varlena *oldexternal, int options) + varlena *oldexternal, uint32 options) { Relation toastrel; Relation *toastidxs; diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c index ba541bd60c9..03f885a25b0 100644 --- a/src/backend/access/heap/heaptoast.c +++ b/src/backend/access/heap/heaptoast.c @@ -94,7 +94,7 @@ heap_toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative) */ HeapTuple heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, - int options) + uint32 options) { HeapTuple result_tuple; TupleDesc tupleDesc; diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c index 1097f44a74e..e96e0f77d92 100644 --- a/src/backend/access/heap/hio.c +++ b/src/backend/access/heap/hio.c @@ -498,7 +498,7 @@ RelationAddBlocks(Relation relation, BulkInsertState bistate, */ Buffer RelationGetBufferForTuple(Relation relation, Size len, - Buffer otherBuffer, int options, + Buffer otherBuffer, uint32 options, BulkInsertState bistate, Buffer *vmbuffer, Buffer *vmbuffer_other, int num_pages) diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 6b19ac3030d..f707b102c72 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -618,7 +618,7 @@ raw_heap_insert(RewriteState state, HeapTuple tup) } else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD) { - int options = HEAP_INSERT_SKIP_FSM; + uint32 options = HEAP_INSERT_SKIP_FSM; /* * While rewriting the heap for VACUUM FULL / CLUSTER, make sure data diff --git a/src/backend/access/table/toast_helper.c b/src/backend/access/table/toast_helper.c index 0d792a60ca0..2f2022d9951 100644 --- a/src/backend/access/table/toast_helper.c +++ b/src/backend/access/table/toast_helper.c @@ -253,7 +253,7 @@ toast_tuple_try_compression(ToastTupleContext *ttc, int attribute) * Move an attribute to external storage. */ void -toast_tuple_externalize(ToastTupleContext *ttc, int attribute, int options) +toast_tuple_externalize(ToastTupleContext *ttc, int attribute, uint32 options) { Datum *value = &ttc->ttc_values[attribute]; Datum old_value = *value; diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c index aa253b587aa..64ac3063c61 100644 --- a/src/backend/commands/copyfrom.c +++ b/src/backend/commands/copyfrom.c @@ -101,7 +101,7 @@ typedef struct CopyMultiInsertInfo CopyFromState cstate; /* Copy state for this CopyMultiInsertInfo */ EState *estate; /* Executor state used for COPY */ CommandId mycid; /* Command Id used for COPY */ - int ti_options; /* table insert options */ + uint32 ti_options; /* table insert options */ } CopyMultiInsertInfo; @@ -401,7 +401,7 @@ CopyMultiInsertInfoSetupBuffer(CopyMultiInsertInfo *miinfo, static void CopyMultiInsertInfoInit(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, CopyFromState cstate, EState *estate, CommandId mycid, - int ti_options) + uint32 ti_options) { miinfo->multiInsertBuffers = NIL; miinfo->bufferedTuples = 0; @@ -535,7 +535,7 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo, else { CommandId mycid = miinfo->mycid; - int ti_options = miinfo->ti_options; + uint32 ti_options = miinfo->ti_options; bool line_buf_valid = cstate->line_buf_valid; uint64 save_cur_lineno = cstate->cur_lineno; MemoryContext oldcontext; @@ -792,7 +792,7 @@ CopyFrom(CopyFromState cstate) PartitionTupleRouting *proute = NULL; ErrorContextCallback errcallback; CommandId mycid = GetCurrentCommandId(true); - int ti_options = 0; /* start with default options for insert */ + uint32 ti_options = 0; /* start with default options for insert */ BulkInsertState bistate = NULL; CopyInsertMethod insertMethod; CopyMultiInsertInfo multiInsertInfo = {0}; /* pacify compiler */ diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 270e9bf3110..6dbb831ca89 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -56,7 +56,7 @@ typedef struct Relation rel; /* relation to write to */ ObjectAddress reladdr; /* address of rel, for ExecCreateTableAs */ CommandId output_cid; /* cmin to insert in output tuples */ - int ti_options; /* table_tuple_insert performance options */ + uint32 ti_options; /* table_tuple_insert performance options */ BulkInsertState bistate; /* bulk insert state */ } DR_intorel; diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index 81a55a33ef2..d3be8939011 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -49,7 +49,7 @@ typedef struct /* These fields are filled by transientrel_startup: */ Relation transientrel; /* relation to write to */ CommandId output_cid; /* cmin to insert in output tuples */ - int ti_options; /* table_tuple_insert performance options */ + uint32 ti_options; /* table_tuple_insert performance options */ BulkInsertState bistate; /* bulk insert state */ } DR_transientrel; diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 8b4ebc6f226..0ce2e81f9c2 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -6195,7 +6195,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap) EState *estate; CommandId mycid; BulkInsertState bistate; - int ti_options; + uint32 ti_options; ExprState *partqualstate = NULL; /* @@ -22835,7 +22835,7 @@ MergePartitionsMoveRows(List **wqueue, List *mergingPartitions, Relation newPart ListCell *ltab; /* The FSM is empty, so don't bother using it. */ - int ti_options = TABLE_INSERT_SKIP_FSM; + uint32 ti_options = TABLE_INSERT_SKIP_FSM; BulkInsertState bistate; /* state of bulk inserts for partition */ TupleTableSlot *dstslot; @@ -23226,7 +23226,7 @@ createSplitPartitionContext(Relation partRel) * deleteSplitPartitionContext: delete context for partition */ static void -deleteSplitPartitionContext(SplitPartitionContext *pc, List **wqueue, int ti_options) +deleteSplitPartitionContext(SplitPartitionContext *pc, List **wqueue, uint32 ti_options) { ListCell *ltab; @@ -23268,7 +23268,7 @@ SplitPartitionMoveRows(List **wqueue, Relation rel, Relation splitRel, List *partlist, List *newPartRels) { /* The FSM is empty, so don't bother using it. */ - int ti_options = TABLE_INSERT_SKIP_FSM; + uint32 ti_options = TABLE_INSERT_SKIP_FSM; CommandId mycid; EState *estate; ListCell *listptr, diff --git a/src/include/access/heaptoast.h b/src/include/access/heaptoast.h index 725c0ce7554..631cb1836b9 100644 --- a/src/include/access/heaptoast.h +++ b/src/include/access/heaptoast.h @@ -95,7 +95,7 @@ * ---------- */ extern HeapTuple heap_toast_insert_or_update(Relation rel, HeapTuple newtup, - HeapTuple oldtup, int options); + HeapTuple oldtup, uint32 options); /* ---------- * heap_toast_delete - diff --git a/src/include/access/hio.h b/src/include/access/hio.h index d8e63a54ea5..60cfc375fd5 100644 --- a/src/include/access/hio.h +++ b/src/include/access/hio.h @@ -54,7 +54,7 @@ typedef struct BulkInsertStateData extern void RelationPutHeapTuple(Relation relation, Buffer buffer, HeapTuple tuple, bool token); extern Buffer RelationGetBufferForTuple(Relation relation, Size len, - Buffer otherBuffer, int options, + Buffer otherBuffer, uint32 options, BulkInsertStateData *bistate, Buffer *vmbuffer, Buffer *vmbuffer_other, int num_pages); diff --git a/src/include/access/toast_helper.h b/src/include/access/toast_helper.h index e8ecb995cb3..2ec92397f26 100644 --- a/src/include/access/toast_helper.h +++ b/src/include/access/toast_helper.h @@ -107,7 +107,7 @@ extern int toast_tuple_find_biggest_attribute(ToastTupleContext *ttc, bool check_main); extern void toast_tuple_try_compression(ToastTupleContext *ttc, int attribute); extern void toast_tuple_externalize(ToastTupleContext *ttc, int attribute, - int options); + uint32 options); extern void toast_tuple_cleanup(ToastTupleContext *ttc); extern void toast_delete_external(Relation rel, const Datum *values, const bool *isnull, diff --git a/src/include/access/toast_internals.h b/src/include/access/toast_internals.h index d382db34262..bf45889a642 100644 --- a/src/include/access/toast_internals.h +++ b/src/include/access/toast_internals.h @@ -50,7 +50,7 @@ extern Oid toast_get_valid_index(Oid toastoid, LOCKMODE lock); extern void toast_delete_datum(Relation rel, Datum value, bool is_speculative); extern Datum toast_save_datum(Relation rel, Datum value, - varlena *oldexternal, int options); + varlena *oldexternal, uint32 options); extern int toast_open_indexes(Relation toastrel, LOCKMODE lock, -- 2.47.3
>From c8e58c1a0c4aa3d946ceaa655c0ada793350fb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Herrera?= <[email protected]> Date: Mon, 30 Mar 2026 13:27:42 +0200 Subject: [PATCH v5 2/3] Give 'options' parameter to table_delete/table_update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The table_insert() method already has an equivalent argument, so this makes sense just on consistency grounds, for future growth. table_delete() can immediately use it to carry the 'changingPart' boolean (which is arguably misplaced in the current API); for table_update we don't have any options at present, but an upcoming patch would add one. Author: Álvaro Herrera <[email protected]> Reviewed-by: Zsolt Parragi <[email protected]> Reviewed-by: Chao Li <[email protected]> Discussion: https://postgr.es/m/[email protected] --- src/backend/access/heap/heapam.c | 16 +++++++----- src/backend/access/heap/heapam_handler.c | 13 ++++++---- src/backend/access/table/tableam.c | 6 ++--- src/backend/executor/nodeModifyTable.c | 9 +++++-- src/include/access/heapam.h | 7 +++--- src/include/access/tableam.h | 31 +++++++++++++++--------- 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index d34136d2e94..6bff0032db2 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2862,8 +2862,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, uint32 options, Snapshot crosscheck, + bool wait, TM_FailureData *tmfd) { TM_Result result; TransactionId xid = GetCurrentTransactionId(); @@ -2876,6 +2876,7 @@ heap_delete(Relation relation, const ItemPointerData *tid, TransactionId new_xmax; uint16 new_infomask, new_infomask2; + bool changingPart = (options & TABLE_DELETE_CHANGING_PARTITION) != 0; bool have_tuple_lock = false; bool iscombo; bool all_visible_cleared = false; @@ -3290,9 +3291,11 @@ simple_heap_delete(Relation relation, const ItemPointerData *tid) TM_FailureData tmfd; result = heap_delete(relation, tid, - GetCurrentCommandId(true), InvalidSnapshot, + GetCurrentCommandId(true), + 0, + InvalidSnapshot, true /* wait for commit */ , - &tmfd, false /* changingPart */ ); + &tmfd); switch (result) { case TM_SelfModified: @@ -3331,7 +3334,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, uint32 options pg_attribute_unused(), Snapshot crosscheck, bool wait, TM_FailureData *tmfd, LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) { @@ -4585,7 +4588,8 @@ simple_heap_update(Relation relation, const ItemPointerData *otid, HeapTuple tup LockTupleMode lockmode; result = heap_update(relation, otid, tup, - GetCurrentCommandId(true), InvalidSnapshot, + GetCurrentCommandId(true), 0, + InvalidSnapshot, true /* wait for commit */ , &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 cdd153c6b6d..1be8ea4845a 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -313,21 +313,23 @@ 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) + uint32 options, Snapshot snapshot, Snapshot crosscheck, + bool wait, 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, options, crosscheck, wait, + tmfd); } static TM_Result heapam_tuple_update(Relation relation, ItemPointer otid, TupleTableSlot *slot, - CommandId cid, Snapshot snapshot, Snapshot crosscheck, + CommandId cid, uint32 options, + Snapshot snapshot, Snapshot crosscheck, bool wait, TM_FailureData *tmfd, LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) { @@ -339,7 +341,8 @@ 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, options, + crosscheck, wait, 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 86481d7c029..68ff0966f1c 100644 --- a/src/backend/access/table/tableam.c +++ b/src/backend/access/table/tableam.c @@ -320,9 +320,9 @@ simple_table_tuple_delete(Relation rel, ItemPointer tid, Snapshot snapshot) result = table_tuple_delete(rel, tid, GetCurrentCommandId(true), - snapshot, InvalidSnapshot, + 0, snapshot, InvalidSnapshot, true /* wait for commit */ , - &tmfd, false /* changingPart */ ); + &tmfd); switch (result) { @@ -369,7 +369,7 @@ simple_table_tuple_update(Relation rel, ItemPointer otid, result = table_tuple_update(rel, otid, slot, GetCurrentCommandId(true), - snapshot, InvalidSnapshot, + 0, snapshot, InvalidSnapshot, true /* wait for commit */ , &tmfd, &lockmode, update_indexes); diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 582bcc367c0..76728f08734 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1522,14 +1522,18 @@ ExecDeleteAct(ModifyTableContext *context, ResultRelInfo *resultRelInfo, ItemPointer tupleid, bool changingPart) { EState *estate = context->estate; + uint32 options = 0; + + if (changingPart) + options |= TABLE_DELETE_CHANGING_PARTITION; return table_tuple_delete(resultRelInfo->ri_RelationDesc, tupleid, estate->es_output_cid, + options, estate->es_snapshot, estate->es_crosscheck_snapshot, true /* wait for commit */ , - &context->tmfd, - changingPart); + &context->tmfd); } /* @@ -2331,6 +2335,7 @@ lreplace: */ result = table_tuple_update(resultRelationDesc, tupleid, slot, estate->es_output_cid, + 0, estate->es_snapshot, estate->es_crosscheck_snapshot, true /* wait for commit */ , diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index f46c83e88f3..54067b828e4 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -382,13 +382,14 @@ extern void heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, CommandId cid, uint32 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, uint32 options, Snapshot crosscheck, + bool wait, 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, uint32 options, + Snapshot crosscheck, bool wait, 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 57892152957..9b5d7424dda 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -282,13 +282,18 @@ typedef struct TM_IndexDeleteOp #define TABLE_INSERT_FROZEN 0x0004 #define TABLE_INSERT_NO_LOGICAL 0x0008 +/* "options" flag bits for table_tuple_delete */ +#define TABLE_DELETE_CHANGING_PARTITION (1 << 0) + +/* "options" flag bits for table_tuple_update */ +/* XXX none at present */ + /* 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) /* Follow update chain and lock latest version of tuple */ #define TUPLE_LOCK_FLAG_FIND_LAST_VERSION (1 << 1) - /* Typedef for callback function for table_index_build_scan */ typedef void (*IndexBuildCallback) (Relation index, ItemPointer tid, @@ -559,17 +564,18 @@ typedef struct TableAmRoutine TM_Result (*tuple_delete) (Relation rel, ItemPointer tid, CommandId cid, + uint32 options, Snapshot snapshot, Snapshot crosscheck, bool wait, - TM_FailureData *tmfd, - bool changingPart); + TM_FailureData *tmfd); /* see table_tuple_update() for reference about parameters */ TM_Result (*tuple_update) (Relation rel, ItemPointer otid, TupleTableSlot *slot, CommandId cid, + uint32 options, Snapshot snapshot, Snapshot crosscheck, bool wait, @@ -1516,10 +1522,11 @@ table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots, * tid - TID of tuple to be deleted * cid - delete command ID (used for visibility test, and stored into * cmax if successful) + * options - bitmask of options. Supported values: + * TABLE_DELETE_CHANGING_PARTITION: the tuple is being moved to another + * partition table due to an update of the partition key. * 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. * * Output parameters: * tmfd - filled in failure cases (see below) @@ -1534,12 +1541,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) + uint32 options, Snapshot snapshot, Snapshot crosscheck, + bool wait, TM_FailureData *tmfd) { - return rel->rd_tableam->tuple_delete(rel, tid, cid, + return rel->rd_tableam->tuple_delete(rel, tid, cid, options, snapshot, crosscheck, - wait, tmfd, changingPart); + wait, tmfd); } /* @@ -1553,6 +1560,7 @@ table_tuple_delete(Relation rel, ItemPointer tid, CommandId cid, * otid - TID of old tuple to be replaced * cid - update command ID (used for visibility test, and stored into * cmax/cmin if successful) + * options - bitmask of options. No values are currently recognized. * crosscheck - if not InvalidSnapshot, also check old tuple against this * wait - true if should wait for any conflicting update to commit/abort * @@ -1579,12 +1587,13 @@ 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, + CommandId cid, uint32 options, + Snapshot snapshot, Snapshot crosscheck, bool wait, TM_FailureData *tmfd, LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) { return rel->rd_tableam->tuple_update(rel, otid, slot, - cid, snapshot, crosscheck, + cid, options, snapshot, crosscheck, wait, tmfd, lockmode, update_indexes); } -- 2.47.3
>From 6d527c234238cc2085fe7552fb840a59bb5ecf80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Herrera?= <[email protected]> Date: Sun, 29 Mar 2026 23:11:42 +0200 Subject: [PATCH v5 3/3] Define heap_insert to obey tableam.h option bits directly Redefining the bits at the heapam.h interface serves no purpose. Also, whenever somebody next defines a new TABLE_INSERT_* bit, the value value would collide with HEAP_INSERT_SPECULATIVE. Move the latter to the other end of the bits word. --- src/backend/access/heap/heapam.c | 20 ++++++++++---------- src/backend/access/heap/hio.c | 10 +++++----- src/backend/access/heap/rewriteheap.c | 4 ++-- src/backend/replication/logical/decode.c | 2 +- src/include/access/heapam.h | 11 ++++++----- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 6bff0032db2..efcde4e8094 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2138,9 +2138,9 @@ ReleaseBulkInsertStatePin(BulkInsertState bistate) * See table_tuple_insert for comments about most of the input flags, except * that this routine directly takes a tuple rather than a slot. * - * There's corresponding HEAP_INSERT_ options to all the TABLE_INSERT_ - * options, and there additionally is HEAP_INSERT_SPECULATIVE which is used to - * implement table_tuple_insert_speculative(). + * In addition to the TABLE_INSERT_ options, there additionally is + * HEAP_INSERT_SPECULATIVE which is used to implement + * table_tuple_insert_speculative(). * * On return the header fields of *tup are updated to match the stored tuple; * in particular tup->t_self receives the actual TID where the tuple was @@ -2228,7 +2228,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, * Don't set it if we are in bootstrap mode or we are inserting a frozen * tuple, as there is no further pruning/freezing needed in those cases. */ - if (TransactionIdIsNormal(xid) && !(options & HEAP_INSERT_FROZEN)) + if (TransactionIdIsNormal(xid) && !(options & TABLE_INSERT_FROZEN)) PageSetPrunable(page, xid); MarkBufferDirty(buffer); @@ -2275,7 +2275,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, * image. (XXX We could alternatively store a pointer into the FPW). */ if (RelationIsLogicallyLogged(relation) && - !(options & HEAP_INSERT_NO_LOGICAL)) + !(options & TABLE_INSERT_NO_LOGICAL)) { xlrec.flags |= XLH_INSERT_CONTAINS_NEW_TUPLE; bufflags |= REGBUF_KEEP_DATA; @@ -2364,7 +2364,7 @@ heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid, tup->t_data->t_infomask2 &= ~(HEAP2_XACT_MASK); tup->t_data->t_infomask |= HEAP_XMAX_INVALID; HeapTupleHeaderSetXmin(tup->t_data, xid); - if (options & HEAP_INSERT_FROZEN) + if (options & TABLE_INSERT_FROZEN) HeapTupleHeaderSetXminFrozen(tup->t_data); HeapTupleHeaderSetCmin(tup->t_data, cid); @@ -2445,7 +2445,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, int npages_used = 0; /* currently not needed (thus unsupported) for heap_multi_insert() */ - Assert(!(options & HEAP_INSERT_NO_LOGICAL)); + Assert(!(options & TABLE_INSERT_NO_LOGICAL)); AssertHasSnapshotForToast(relation); @@ -2535,7 +2535,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, starting_with_empty_page = PageGetMaxOffsetNumber(page) == 0; - if (starting_with_empty_page && (options & HEAP_INSERT_FROZEN)) + if (starting_with_empty_page && (options & TABLE_INSERT_FROZEN)) { all_frozen_set = true; /* Lock the vmbuffer before entering the critical section */ @@ -2583,7 +2583,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, * page, mark it as all-frozen and update the visibility map. We're * already holding a pin on the vmbuffer. */ - if (PageIsAllVisible(page) && !(options & HEAP_INSERT_FROZEN)) + if (PageIsAllVisible(page) && !(options & TABLE_INSERT_FROZEN)) { all_visible_cleared = true; PageClearAllVisible(page); @@ -2655,7 +2655,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, /* * We don't have to worry about including a conflict xid in the - * WAL record, as HEAP_INSERT_FROZEN intentionally violates + * WAL record, as TABLE_INSERT_FROZEN intentionally violates * visibility rules. */ if (all_frozen_set) diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c index e96e0f77d92..17f87f693ea 100644 --- a/src/backend/access/heap/hio.c +++ b/src/backend/access/heap/hio.c @@ -469,12 +469,12 @@ RelationAddBlocks(Relation relation, BulkInsertState bistate, * which is indicated by these arguments not being InvalidBuffer on entry. * * We normally use FSM to help us find free space. However, - * if HEAP_INSERT_SKIP_FSM is specified, we just append a new empty page to + * if TABLE_INSERT_SKIP_FSM is specified, we just append a new empty page to * the end of the relation if the tuple won't fit on the current target page. * This can save some cycles when we know the relation is new and doesn't * contain useful amounts of free space. * - * HEAP_INSERT_SKIP_FSM is also useful for non-WAL-logged additions to a + * TABLE_INSERT_SKIP_FSM is also useful for non-WAL-logged additions to a * relation, if the caller holds exclusive lock and is careful to invalidate * relation's smgr_targblock before the first insertion --- that ensures that * all insertions will occur into newly added pages and not be intermixed @@ -503,7 +503,7 @@ RelationGetBufferForTuple(Relation relation, Size len, Buffer *vmbuffer, Buffer *vmbuffer_other, int num_pages) { - bool use_fsm = !(options & HEAP_INSERT_SKIP_FSM); + bool use_fsm = !(options & TABLE_INSERT_SKIP_FSM); Buffer buffer = InvalidBuffer; Page page; Size nearlyEmptyFreeSpace, @@ -621,7 +621,7 @@ loop: /* * If the page is empty, pin vmbuffer to set all_frozen bit later. */ - if ((options & HEAP_INSERT_FROZEN) && + if ((options & TABLE_INSERT_FROZEN) && (PageGetMaxOffsetNumber(BufferGetPage(buffer)) == 0)) visibilitymap_pin(relation, targetBlock, vmbuffer); @@ -774,7 +774,7 @@ loop: * do IO while the buffer is locked, so we unlock the page first if IO is * needed (necessitating checks below). */ - if (options & HEAP_INSERT_FROZEN) + if (options & TABLE_INSERT_FROZEN) { Assert(PageGetMaxOffsetNumber(page) == 0); diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index f707b102c72..ce4f41672f9 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -618,14 +618,14 @@ raw_heap_insert(RewriteState state, HeapTuple tup) } else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD) { - uint32 options = HEAP_INSERT_SKIP_FSM; + uint32 options = TABLE_INSERT_SKIP_FSM; /* * While rewriting the heap for VACUUM FULL / CLUSTER, make sure data * for the TOAST table are not logically decoded. The main heap is * WAL-logged as XLOG FPI records, which are not logically decoded. */ - options |= HEAP_INSERT_NO_LOGICAL; + options |= TABLE_INSERT_NO_LOGICAL; heaptup = heap_toast_insert_or_update(state->rs_new_rel, tup, NULL, options); diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c index 3c027bcb2f7..d80a26ce88e 100644 --- a/src/backend/replication/logical/decode.c +++ b/src/backend/replication/logical/decode.c @@ -898,7 +898,7 @@ DecodeInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) /* * Ignore insert records without new tuples (this does happen when - * raw_heap_insert marks the TOAST record as HEAP_INSERT_NO_LOGICAL). + * raw_heap_insert marks the TOAST record as TABLE_INSERT_NO_LOGICAL). */ if (!(xlrec->flags & XLH_INSERT_CONTAINS_NEW_TUPLE)) return; diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 54067b828e4..20e952ec64f 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -32,11 +32,12 @@ #include "utils/snapshot.h" -/* "options" flag bits for heap_insert */ -#define HEAP_INSERT_SKIP_FSM TABLE_INSERT_SKIP_FSM -#define HEAP_INSERT_FROZEN TABLE_INSERT_FROZEN -#define HEAP_INSERT_NO_LOGICAL TABLE_INSERT_NO_LOGICAL -#define HEAP_INSERT_SPECULATIVE 0x0010 +/* + * "options" flag bits for heap_insert. That routine also obeys bits defined + * for table_tuple_insert; see tableam.h. We define these starting from the + * opposite end of the options word. + */ +#define HEAP_INSERT_SPECULATIVE (1 << 31) /* "options" flag bits for heap_page_prune_and_freeze */ #define HEAP_PAGE_PRUNE_MARK_UNUSED_NOW (1 << 0) -- 2.47.3
