=== Applying patches on top of PostgreSQL commit ID 5142f0093e648d1a32fdcc7c835d17fa103e1239 === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Sun Apr 19 22:50:24 UTC 2026 On branch cf/5556 nothing to commit, working tree clean === using 'git am' to apply patch ./v38-0001-Add-tests-to-cover-a-variety-of-heap-HOT-update-.patch === Applying: Add tests to cover a variety of heap HOT update behaviors === using 'git am' to apply patch ./v38-0002-Identify-modified-indexed-attributes-in-the-exec.patch === Applying: Identify modified indexed attributes in the executor on UPDATE Using index info to reconstruct a base tree... M src/backend/access/heap/heapam.c M src/backend/access/heap/heapam_handler.c M src/backend/access/table/tableam.c M src/backend/executor/execReplication.c M src/backend/executor/execTuples.c M src/backend/executor/nodeModifyTable.c M src/backend/utils/cache/relcache.c M src/include/access/heapam.h M src/include/access/tableam.h M src/include/executor/executor.h M src/include/utils/rel.h M src/test/regress/expected/generated_virtual.out M src/test/regress/expected/triggers.out M src/test/regress/expected/updatable_views.out M src/test/regress/sql/generated_virtual.sql M src/test/regress/sql/updatable_views.sql Falling back to patching base and 3-way merge... Auto-merging src/test/regress/sql/updatable_views.sql Auto-merging src/test/regress/sql/generated_virtual.sql Auto-merging src/test/regress/expected/updatable_views.out Auto-merging src/test/regress/expected/triggers.out Auto-merging src/test/regress/expected/generated_virtual.out Auto-merging src/include/utils/rel.h Auto-merging src/include/executor/executor.h Auto-merging src/include/access/tableam.h CONFLICT (content): Merge conflict in src/include/access/tableam.h Auto-merging src/include/access/heapam.h CONFLICT (content): Merge conflict in src/include/access/heapam.h Auto-merging src/backend/utils/cache/relcache.c Auto-merging src/backend/executor/nodeModifyTable.c Auto-merging src/backend/executor/execTuples.c Auto-merging src/backend/executor/execReplication.c Auto-merging src/backend/access/table/tableam.c Auto-merging src/backend/access/heap/heapam_handler.c CONFLICT (content): Merge conflict in src/backend/access/heap/heapam_handler.c Auto-merging src/backend/access/heap/heapam.c CONFLICT (content): Merge conflict in src/backend/access/heap/heapam.c error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 Identify modified indexed attributes in the executor on UPDATE When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". === using patch(1) to apply patch ./v38-0002-Identify-modified-indexed-attributes-in-the-exec.patch === patching file src/backend/access/heap/heapam.c Hunk #1 FAILED at 37. Hunk #2 succeeded at 70 (offset 2 lines). Hunk #3 succeeded at 3187 (offset -122 lines). Hunk #4 FAILED at 3319. Hunk #5 succeeded at 3228 (offset -121 lines). Hunk #6 succeeded at 3264 (offset -121 lines). Hunk #7 succeeded at 3329 (offset -121 lines). Hunk #8 succeeded at 3350 (offset -121 lines). Hunk #9 succeeded at 3415 (offset -121 lines). Hunk #10 succeeded at 3433 (offset -121 lines). Hunk #11 succeeded at 3512 (offset -121 lines). Hunk #12 succeeded at 3521 (offset -121 lines). Hunk #13 succeeded at 3606 (offset -121 lines). Hunk #14 succeeded at 3666 (offset -121 lines). Hunk #15 succeeded at 3703 (offset -121 lines). Hunk #16 succeeded at 3820 (offset -121 lines). Hunk #17 succeeded at 3993 (offset -121 lines). Hunk #18 succeeded at 4010 (offset -121 lines). Hunk #19 succeeded at 4140 (offset -120 lines). Hunk #20 succeeded at 4154 (offset -120 lines). Hunk #21 succeeded at 4332 (offset -120 lines). Hunk #22 succeeded at 4456 (offset -120 lines). Hunk #23 succeeded at 4469 (offset -120 lines). Hunk #24 succeeded at 4485 (offset -120 lines). Hunk #25 FAILED at 4628. Hunk #26 succeeded at 4523 (offset -119 lines). 3 out of 26 hunks FAILED -- saving rejects to file src/backend/access/heap/heapam.c.rej patching file src/backend/access/heap/heapam_handler.c Hunk #2 FAILED at 324. Hunk #3 succeeded at 249 (offset -100 lines). 1 out of 3 hunks FAILED -- saving rejects to file src/backend/access/heap/heapam_handler.c.rej patching file src/backend/access/table/tableam.c Hunk #1 succeeded at 361 (offset 2 lines). Hunk #2 succeeded at 372 with fuzz 2 (offset 2 lines). patching file src/backend/executor/execReplication.c Hunk #2 succeeded at 911 (offset 4 lines). Hunk #3 succeeded at 950 (offset 4 lines). patching file src/backend/executor/execTuples.c patching file src/backend/executor/nodeModifyTable.c Hunk #3 succeeded at 200 with fuzz 2 (offset 8 lines). Hunk #4 succeeded at 2501 (offset 245 lines). Hunk #5 succeeded at 2628 (offset 245 lines). Hunk #6 succeeded at 2652 (offset 246 lines). Hunk #7 succeeded at 2880 (offset 251 lines). Hunk #8 succeeded at 3731 (offset 251 lines). Hunk #9 succeeded at 4869 (offset 251 lines). patching file src/backend/utils/cache/relcache.c Hunk #1 succeeded at 2470 (offset 1 line). Hunk #2 succeeded at 5272 (offset 1 line). Hunk #3 succeeded at 5296 (offset 1 line). Hunk #4 succeeded at 5316 (offset 1 line). Hunk #5 succeeded at 5362 (offset 1 line). Hunk #6 succeeded at 5422 (offset 1 line). Hunk #7 succeeded at 5431 (offset 1 line). Hunk #8 succeeded at 5494 (offset 1 line). Hunk #9 succeeded at 5516 (offset 1 line). Hunk #10 succeeded at 5532 (offset 1 line). Hunk #11 succeeded at 5546 (offset 1 line). patching file src/include/access/heapam.h Hunk #1 FAILED at 403. Hunk #2 succeeded at 464 with fuzz 1 (offset -5 lines). 1 out of 2 hunks FAILED -- saving rejects to file src/include/access/heapam.h.rej patching file src/include/access/tableam.h Hunk #1 succeeded at 586 (offset 37 lines). Hunk #2 FAILED at 1524. Hunk #3 succeeded at 2092 (offset 82 lines). 1 out of 3 hunks FAILED -- saving rejects to file src/include/access/tableam.h.rej patching file src/include/executor/executor.h Hunk #2 succeeded at 618 (offset 7 lines). Hunk #3 succeeded at 821 (offset 9 lines). patching file src/include/utils/rel.h patching file src/include/utils/relcache.h patching file src/test/modules/injection_points/expected/syscache-update-pruned.out patching file src/test/modules/injection_points/specs/syscache-update-pruned.spec patching file src/test/regress/expected/generated_virtual.out patching file src/test/regress/expected/triggers.out patching file src/test/regress/expected/tsearch.out patching file src/test/regress/expected/updatable_views.out patching file src/test/regress/sql/generated_virtual.sql patching file src/test/regress/sql/triggers.sql patching file src/test/regress/sql/tsearch.sql patching file src/test/regress/sql/updatable_views.sql Unstaged changes after reset: M src/backend/access/heap/heapam.c M src/backend/access/heap/heapam_handler.c M src/backend/access/table/tableam.c M src/backend/executor/execReplication.c M src/backend/executor/execTuples.c M src/backend/executor/nodeModifyTable.c M src/backend/utils/cache/relcache.c M src/include/access/heapam.h M src/include/access/tableam.h M src/include/executor/executor.h M src/include/utils/rel.h M src/include/utils/relcache.h M src/test/modules/injection_points/expected/syscache-update-pruned.out M src/test/modules/injection_points/specs/syscache-update-pruned.spec M src/test/regress/expected/generated_virtual.out M src/test/regress/expected/triggers.out M src/test/regress/expected/tsearch.out M src/test/regress/expected/updatable_views.out M src/test/regress/sql/generated_virtual.sql M src/test/regress/sql/triggers.sql M src/test/regress/sql/tsearch.sql M src/test/regress/sql/updatable_views.sql Removing src/backend/access/heap/heapam.c.rej Removing src/backend/access/heap/heapam_handler.c.rej Removing src/include/access/heapam.h.rej Removing src/include/access/tableam.h.rej === using 'git apply' to apply patch ./v38-0002-Identify-modified-indexed-attributes-in-the-exec.patch === Applied patch to 'src/backend/access/heap/heapam.c' with conflicts. Applied patch to 'src/backend/access/heap/heapam_handler.c' with conflicts. Applied patch to 'src/backend/access/table/tableam.c' cleanly. Applied patch to 'src/backend/executor/execReplication.c' cleanly. Applied patch to 'src/backend/executor/execTuples.c' cleanly. Applied patch to 'src/backend/executor/nodeModifyTable.c' cleanly. Applied patch to 'src/backend/utils/cache/relcache.c' cleanly. Applied patch to 'src/include/access/heapam.h' with conflicts. Applied patch to 'src/include/access/tableam.h' with conflicts. Applied patch to 'src/include/executor/executor.h' cleanly. Applied patch to 'src/include/utils/rel.h' cleanly. Applied patch to 'src/include/utils/relcache.h' cleanly. Applied patch to 'src/test/modules/injection_points/expected/syscache-update-pruned.out' cleanly. Applied patch to 'src/test/modules/injection_points/specs/syscache-update-pruned.spec' cleanly. Applied patch to 'src/test/regress/expected/generated_virtual.out' cleanly. Applied patch to 'src/test/regress/expected/triggers.out' cleanly. Applied patch to 'src/test/regress/expected/tsearch.out' cleanly. Applied patch to 'src/test/regress/expected/updatable_views.out' cleanly. Applied patch to 'src/test/regress/sql/generated_virtual.sql' cleanly. Applied patch to 'src/test/regress/sql/triggers.sql' cleanly. Applied patch to 'src/test/regress/sql/tsearch.sql' cleanly. Applied patch to 'src/test/regress/sql/updatable_views.sql' cleanly. U src/backend/access/heap/heapam.c U src/backend/access/heap/heapam_handler.c U src/include/access/heapam.h U src/include/access/tableam.h diff --cc src/backend/access/heap/heapam.c index abfd8e8970a,dcb8a34b7bf..00000000000 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@@ -43,12 -45,13 +45,17 @@@ #include "catalog/pg_database.h" #include "catalog/pg_database_d.h" #include "commands/vacuum.h" ++<<<<<<< ours +#include "executor/instrument_node.h" ++======= + #include "executor/tuptable.h" + #include "nodes/lockoptions.h" ++>>>>>>> theirs #include "pgstat.h" #include "port/pg_bitutils.h" + #include "storage/buf.h" #include "storage/lmgr.h" #include "storage/predicate.h" - #include "storage/proc.h" #include "storage/procarray.h" #include "utils/datum.h" #include "utils/injection_point.h" @@@ -3199,9 -3323,9 +3204,15 @@@ simple_heap_delete(Relation relation, c */ TM_Result heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup, ++<<<<<<< ours + CommandId cid, uint32 options pg_attribute_unused(), Snapshot crosscheck, bool wait, + TM_FailureData *tmfd, LockTupleMode *lockmode, + TU_UpdateIndexes *update_indexes) ++======= + CommandId cid, Snapshot crosscheck, bool wait, + TM_FailureData *tmfd, const LockTupleMode lockmode, + const Bitmapset *modified_idx_attrs, const bool hot_allowed) ++>>>>>>> theirs { TM_Result result; TransactionId xid = GetCurrentTransactionId(); @@@ -4453,12 -4629,106 +4518,114 @@@ simple_heap_update(Relation relation, c TM_Result result; TM_FailureData tmfd; LockTupleMode lockmode; + TupleTableSlot *slot; + BufferHeapTupleTableSlot *bslot; + HeapTuple oldtup; + bool shouldFree = true; + Bitmapset *idx_attrs, + *modified_idx_attrs; + bool hot_allowed, + summarized_only; + Buffer buffer; ++<<<<<<< ours + result = heap_update(relation, otid, tup, + GetCurrentCommandId(true), 0, + InvalidSnapshot, + true /* wait for commit */ , + &tmfd, &lockmode, update_indexes); ++======= + Assert(ItemPointerIsValid(otid)); + + /* + * Fetch this bitmap of interesting attributes from relcache before + * obtaining a buffer lock because if we are doing an update on one of the + * relevant system catalogs we could deadlock if we try to fetch them + * later on. Relcache will return copies of each bitmap, so we need not + * worry about relcache flush happening midway through this operation. + */ + idx_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_INDEXED); + + INJECTION_POINT("simple_heap_update-before-pin", NULL); + + /* + * To update a heap tuple we need to find the set of modified indexed + * attributes ("modified_idx_attrs") and use that to determine if a HOT + * update is allowable or not. When updating heap tuples via execution of + * UPDATE statements this set is constructed before calling into the table + * AM's update function by ExecUpdateModifiedIdxAttrs() which compares the + * old/new TupleTableSlots. + * + * Here things are a bit different, we have the old TID and the new tuple, + * not two TupleTableSlots, but we still need to construct a similar + * bitmap so as to be able to know if HOT updates are allowed or not. + * + * To do that we first have to fetch the old tuple itself, but because + * heapam_fetch_row_version() is static, we replicate in part that code + * here. + * + * This is a bit repetitive because heap_update() will again find and form + * the old HeapTuple from the old TID and in most cases the callers + * (ignoring extensions, are always catalog tuple updates) already had the + * set of changed attributes (the "replaces" array), but for now this + * minor repetition of work is necessary. + */ + slot = MakeTupleTableSlot(RelationGetDescr(relation), &TTSOpsBufferHeapTuple, 0); + bslot = (BufferHeapTupleTableSlot *) slot; + + /* + * Set the TID in the slot and then fetch the old tuple so we can examine + * it + */ + bslot->base.tupdata.t_self = *otid; + if (!heap_fetch(relation, SnapshotAny, &bslot->base.tupdata, &buffer, false)) + { + /* + * heap_update() checks for !ItemIdIsNormal(lp) and will return false + * in those cases. + */ + Assert(RelationSupportsSysCache(RelationGetRelid(relation))); + + *update_indexes = TU_None; + + /* modified_idx_attrs not yet initialized */ + bms_free(idx_attrs); + ExecDropSingleTupleTableSlot(slot); + + elog(ERROR, "tuple concurrently deleted"); + + return; + } + + Assert(buffer != InvalidBuffer); + + /* Store in slot, transferring existing pin */ + ExecStorePinnedBufferHeapTuple(&bslot->base.tupdata, slot, buffer); + oldtup = ExecFetchSlotHeapTuple(slot, false, &shouldFree); + + modified_idx_attrs = HeapUpdateModifiedIdxAttrs(relation, oldtup, tup); + lockmode = HeapUpdateDetermineLockmode(relation, modified_idx_attrs); + hot_allowed = HeapUpdateHotAllowable(relation, modified_idx_attrs, &summarized_only); + + result = heap_update(relation, otid, tup, GetCurrentCommandId(true), + InvalidSnapshot, true /* wait for commit */ , + &tmfd, lockmode, modified_idx_attrs, hot_allowed); + + if (shouldFree) + heap_freetuple(oldtup); + + ExecDropSingleTupleTableSlot(slot); + bms_free(idx_attrs); + + /* + * Decide whether new index entries are needed for the tuple + * + * If the update is not HOT, we must update all indexes. If the update is + * HOT, it could be that we updated summarized columns, so we either + * update only summarized indexes, or none at all. + */ + *update_indexes = TU_None; ++>>>>>>> theirs switch (result) { case TM_SelfModified: diff --cc src/backend/access/heap/heapam_handler.c index 20d3b46e062,3726c867c65..00000000000 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@@ -222,10 -323,9 +221,16 @@@ heapam_tuple_delete(Relation relation, static TM_Result heapam_tuple_update(Relation relation, ItemPointer otid, TupleTableSlot *slot, ++<<<<<<< ours + CommandId cid, uint32 options, + Snapshot snapshot, Snapshot crosscheck, + bool wait, TM_FailureData *tmfd, + LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes) ++======= + CommandId cid, Snapshot snapshot, Snapshot crosscheck, + bool wait, TM_FailureData *tmfd, LockTupleMode *lockmode, + const Bitmapset *modified_idx_attrs, TU_UpdateIndexes *update_indexes) ++>>>>>>> theirs { bool shouldFree = true; HeapTuple tuple = ExecFetchSlotHeapTuple(slot, true, &shouldFree); @@@ -235,9 -342,8 +247,14 @@@ slot->tts_tableOid = RelationGetRelid(relation); tuple->t_tableOid = slot->tts_tableOid; ++<<<<<<< ours + result = heap_update(relation, otid, tuple, cid, options, + crosscheck, wait, + tmfd, lockmode, update_indexes); ++======= + result = heap_update(relation, otid, tuple, cid, crosscheck, wait, + tmfd, *lockmode, modified_idx_attrs, hot_allowed); ++>>>>>>> theirs ItemPointerCopy(&tuple->t_self, &slot->tts_tid); /* diff --cc src/include/access/heapam.h index 5176478c295,31a688cf05b..00000000000 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@@ -385,11 -403,9 +385,17 @@@ extern TM_Result heap_delete(Relation r 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, ++<<<<<<< ours + HeapTuple newtup, + CommandId cid, uint32 options, + Snapshot crosscheck, bool wait, + TM_FailureData *tmfd, LockTupleMode *lockmode, + TU_UpdateIndexes *update_indexes); ++======= + HeapTuple newtup, CommandId cid, Snapshot crosscheck, bool wait, + TM_FailureData *tmfd, const LockTupleMode lockmode, + const Bitmapset *modified_idx_attrs, const bool hot_allowed); ++>>>>>>> theirs extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, bool follow_updates, @@@ -464,16 -468,15 +470,22 @@@ extern void log_heap_prune_and_freeze(R OffsetNumber *dead, int ndead, OffsetNumber *unused, int nunused); + /* in heap/heapam.c */ + extern bool HeapUpdateHotAllowable(Relation relation, const Bitmapset *modified_idx_attrs, + bool *summarized_only); + extern LockTupleMode HeapUpdateDetermineLockmode(Relation relation, + const Bitmapset *modified_idx_attrs); + /* in heap/vacuumlazy.c */ extern void heap_vacuum_rel(Relation rel, - const VacuumParams params, BufferAccessStrategy bstrategy); + const VacuumParams *params, BufferAccessStrategy bstrategy); +#ifdef USE_ASSERT_CHECKING +extern bool heap_page_is_all_visible(Relation rel, Buffer buf, + GlobalVisState *vistest, + bool *all_frozen, + TransactionId *newest_live_xid, + OffsetNumber *logging_offnum); +#endif /* in heap/heapam_visibility.c */ extern bool HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot, diff --cc src/include/access/tableam.h index c13f05d39db,8ec20dcfc11..00000000000 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@@ -1598,15 -1522,14 +1599,21 @@@ table_tuple_delete(Relation rel, ItemPo */ 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) + const Bitmapset *modified_idx_attrs, TU_UpdateIndexes *update_indexes) { return rel->rd_tableam->tuple_update(rel, otid, slot, ++<<<<<<< ours + cid, options, snapshot, crosscheck, + wait, tmfd, + lockmode, update_indexes); ++======= + cid, snapshot, crosscheck, + wait, tmfd, lockmode, + modified_idx_attrs, update_indexes); ++>>>>>>> theirs } /*