For the regular satisfies routines this is needed in prepareation of logical decoding. I changed the non-regular ones for consistency as well.
The naming between htup, tuple and similar is rather confused, I could not find any consistent naming anywhere. This is preparatory work for the logical decoding feature which needs to be able to get to a valid relfilenode from when checking the visibility of a tuple. --- contrib/pgrowlocks/pgrowlocks.c | 2 +- src/backend/access/heap/heapam.c | 13 ++++++---- src/backend/access/heap/pruneheap.c | 16 ++++++++++-- src/backend/catalog/index.c | 2 +- src/backend/commands/analyze.c | 3 ++- src/backend/commands/cluster.c | 2 +- src/backend/commands/vacuumlazy.c | 3 ++- src/backend/storage/lmgr/predicate.c | 2 +- src/backend/utils/time/tqual.c | 50 +++++++++++++++++++++++++++++------- src/include/utils/snapshot.h | 4 +-- src/include/utils/tqual.h | 20 +++++++-------- 11 files changed, 83 insertions(+), 34 deletions(-)
diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c index 20beed2..8f9db55 100644 --- a/contrib/pgrowlocks/pgrowlocks.c +++ b/contrib/pgrowlocks/pgrowlocks.c @@ -120,7 +120,7 @@ pgrowlocks(PG_FUNCTION_ARGS) /* must hold a buffer lock to call HeapTupleSatisfiesUpdate */ LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE); - if (HeapTupleSatisfiesUpdate(tuple->t_data, + if (HeapTupleSatisfiesUpdate(tuple, GetCurrentCommandId(false), scan->rs_cbuf) == HeapTupleBeingUpdated) { diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 64aecf2..d025ff7 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -276,6 +276,7 @@ heapgetpage(HeapScanDesc scan, BlockNumber page) HeapTupleData loctup; bool valid; + loctup.t_tableOid = RelationGetRelid(scan->rs_rd); loctup.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp); loctup.t_len = ItemIdGetLength(lpp); ItemPointerSet(&(loctup.t_self), page, lineoff); @@ -1590,7 +1591,7 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer, heapTuple->t_data = (HeapTupleHeader) PageGetItem(dp, lp); heapTuple->t_len = ItemIdGetLength(lp); - heapTuple->t_tableOid = relation->rd_id; + heapTuple->t_tableOid = RelationGetRelid(relation); heapTuple->t_self = *tid; /* @@ -1638,7 +1639,7 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer, * transactions. */ if (all_dead && *all_dead && - !HeapTupleIsSurelyDead(heapTuple->t_data, RecentGlobalXmin)) + !HeapTupleIsSurelyDead(heapTuple, RecentGlobalXmin)) *all_dead = false; /* @@ -2418,12 +2419,13 @@ heap_delete(Relation relation, ItemPointer tid, lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid)); Assert(ItemIdIsNormal(lp)); + tp.t_tableOid = RelationGetRelid(relation); tp.t_data = (HeapTupleHeader) PageGetItem(page, lp); tp.t_len = ItemIdGetLength(lp); tp.t_self = *tid; l1: - result = HeapTupleSatisfiesUpdate(tp.t_data, cid, buffer); + result = HeapTupleSatisfiesUpdate(&tp, cid, buffer); if (result == HeapTupleInvisible) { @@ -2788,6 +2790,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, lp = PageGetItemId(page, ItemPointerGetOffsetNumber(otid)); Assert(ItemIdIsNormal(lp)); + oldtup.t_tableOid = RelationGetRelid(relation); oldtup.t_data = (HeapTupleHeader) PageGetItem(page, lp); oldtup.t_len = ItemIdGetLength(lp); oldtup.t_self = *otid; @@ -2800,7 +2803,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, */ l2: - result = HeapTupleSatisfiesUpdate(oldtup.t_data, cid, buffer); + result = HeapTupleSatisfiesUpdate(&oldtup, cid, buffer); if (result == HeapTupleInvisible) { @@ -3502,7 +3505,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, tuple->t_tableOid = RelationGetRelid(relation); l3: - result = HeapTupleSatisfiesUpdate(tuple->t_data, cid, *buffer); + result = HeapTupleSatisfiesUpdate(tuple, cid, *buffer); if (result == HeapTupleInvisible) { diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index 97a2868..edb3a09 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -340,6 +340,9 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum, OffsetNumber chainitems[MaxHeapTuplesPerPage]; int nchain = 0, i; + HeapTupleData tup; + + tup.t_tableOid = RelationGetRelid(relation); rootlp = PageGetItemId(dp, rootoffnum); @@ -349,6 +352,11 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum, if (ItemIdIsNormal(rootlp)) { htup = (HeapTupleHeader) PageGetItem(dp, rootlp); + + tup.t_data = htup; + tup.t_len = ItemIdGetLength(rootlp); + ItemPointerSet(&(tup.t_self), BufferGetBlockNumber(buffer), rootoffnum); + if (HeapTupleHeaderIsHeapOnly(htup)) { /* @@ -369,7 +377,7 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum, * either here or while following a chain below. Whichever path * gets there first will mark the tuple unused. */ - if (HeapTupleSatisfiesVacuum(htup, OldestXmin, buffer) + if (HeapTupleSatisfiesVacuum(&tup, OldestXmin, buffer) == HEAPTUPLE_DEAD && !HeapTupleHeaderIsHotUpdated(htup)) { heap_prune_record_unused(prstate, rootoffnum); @@ -432,6 +440,10 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum, Assert(ItemIdIsNormal(lp)); htup = (HeapTupleHeader) PageGetItem(dp, lp); + tup.t_data = htup; + tup.t_len = ItemIdGetLength(lp); + ItemPointerSet(&(tup.t_self), BufferGetBlockNumber(buffer), offnum); + /* * Check the tuple XMIN against prior XMAX, if any */ @@ -449,7 +461,7 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum, */ tupdead = recent_dead = false; - switch (HeapTupleSatisfiesVacuum(htup, OldestXmin, buffer)) + switch (HeapTupleSatisfiesVacuum(&tup, OldestXmin, buffer)) { case HEAPTUPLE_DEAD: tupdead = true; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index d2d91c1..18d0c5a 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2267,7 +2267,7 @@ IndexBuildHeapScan(Relation heapRelation, */ LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE); - switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin, + switch (HeapTupleSatisfiesVacuum(heapTuple, OldestXmin, scan->rs_cbuf)) { case HEAPTUPLE_DEAD: diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 9612a27..d9b971c 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -1134,10 +1134,11 @@ acquire_sample_rows(Relation onerel, int elevel, ItemPointerSet(&targtuple.t_self, targblock, targoffset); + targtuple.t_tableOid = RelationGetRelid(onerel); targtuple.t_data = (HeapTupleHeader) PageGetItem(targpage, itemid); targtuple.t_len = ItemIdGetLength(itemid); - switch (HeapTupleSatisfiesVacuum(targtuple.t_data, + switch (HeapTupleSatisfiesVacuum(&targtuple, OldestXmin, targbuffer)) { diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index de71a35..cc36f36 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -923,7 +923,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, LockBuffer(buf, BUFFER_LOCK_SHARE); - switch (HeapTupleSatisfiesVacuum(tuple->t_data, OldestXmin, buf)) + switch (HeapTupleSatisfiesVacuum(tuple, OldestXmin, buf)) { case HEAPTUPLE_DEAD: /* Definitely dead */ diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index c9253a9..0af174e 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -705,12 +705,13 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, Assert(ItemIdIsNormal(itemid)); + tuple.t_tableOid = RelationGetRelid(onerel); tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid); tuple.t_len = ItemIdGetLength(itemid); tupgone = false; - switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf)) + switch (HeapTupleSatisfiesVacuum(&tuple, OldestXmin, buf)) { case HEAPTUPLE_DEAD: diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index f164cfd..b376652 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -3894,7 +3894,7 @@ CheckForSerializableConflictOut(bool visible, Relation relation, * tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else * is going on with it. */ - htsvResult = HeapTupleSatisfiesVacuum(tuple->t_data, TransactionXmin, buffer); + htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer); switch (htsvResult) { case HEAPTUPLE_LIVE: diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c index b531db5..f64d52d 100644 --- a/src/backend/utils/time/tqual.c +++ b/src/backend/utils/time/tqual.c @@ -163,8 +163,12 @@ HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer, * Xmax is not committed))) that has not been committed */ bool -HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) +HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer) { + HeapTupleHeader tuple = htup->t_data; + Assert(ItemPointerIsValid(&htup->t_self)); + Assert(htup->t_tableOid != InvalidOid); + if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) @@ -326,8 +330,12 @@ HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) * */ bool -HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) +HeapTupleSatisfiesNow(HeapTuple htup, Snapshot snapshot, Buffer buffer) { + HeapTupleHeader tuple = htup->t_data; + Assert(ItemPointerIsValid(&htup->t_self)); + Assert(htup->t_tableOid != InvalidOid); + if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) @@ -471,7 +479,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) * Dummy "satisfies" routine: any tuple satisfies SnapshotAny. */ bool -HeapTupleSatisfiesAny(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) +HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer) { return true; } @@ -491,9 +499,13 @@ HeapTupleSatisfiesAny(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) * table. */ bool -HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot, +HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot, Buffer buffer) { + HeapTupleHeader tuple = htup->t_data; + Assert(ItemPointerIsValid(&htup->t_self)); + Assert(htup->t_tableOid != InvalidOid); + if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) @@ -572,9 +584,13 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot, * distinguish that case must test for it themselves.) */ HTSU_Result -HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid, +HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, Buffer buffer) { + HeapTupleHeader tuple = htup->t_data; + Assert(ItemPointerIsValid(&htup->t_self)); + Assert(htup->t_tableOid != InvalidOid); + if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) @@ -739,9 +755,13 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid, * for snapshot->xmax and the tuple's xmax. */ bool -HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot, +HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot, Buffer buffer) { + HeapTupleHeader tuple = htup->t_data; + Assert(ItemPointerIsValid(&htup->t_self)); + Assert(htup->t_tableOid != InvalidOid); + snapshot->xmin = snapshot->xmax = InvalidTransactionId; if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) @@ -902,9 +922,13 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot, * can't see it.) */ bool -HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot, +HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer) { + HeapTupleHeader tuple = htup->t_data; + Assert(ItemPointerIsValid(&htup->t_self)); + Assert(htup->t_tableOid != InvalidOid); + if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) @@ -1058,9 +1082,13 @@ HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot, * even if we see that the deleting transaction has committed. */ HTSV_Result -HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin, +HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer) { + HeapTupleHeader tuple = htup->t_data; + Assert(ItemPointerIsValid(&htup->t_self)); + Assert(htup->t_tableOid != InvalidOid); + /* * Has inserting transaction committed? * @@ -1233,8 +1261,12 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin, * just whether or not the tuple is surely dead). */ bool -HeapTupleIsSurelyDead(HeapTupleHeader tuple, TransactionId OldestXmin) +HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin) { + HeapTupleHeader tuple = htup->t_data; + Assert(ItemPointerIsValid(&htup->t_self)); + Assert(htup->t_tableOid != InvalidOid); + /* * If the inserting transaction is marked invalid, then it aborted, and * the tuple is definitely dead. If it's marked neither committed nor diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h index 900272e..0e86258 100644 --- a/src/include/utils/snapshot.h +++ b/src/include/utils/snapshot.h @@ -27,8 +27,8 @@ typedef struct SnapshotData *Snapshot; * The specific semantics of a snapshot are encoded by the "satisfies" * function. */ -typedef bool (*SnapshotSatisfiesFunc) (HeapTupleHeader tuple, - Snapshot snapshot, Buffer buffer); +typedef bool (*SnapshotSatisfiesFunc) (HeapTuple htup, + Snapshot snapshot, Buffer buffer); typedef struct SnapshotData { diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h index ff74f86..b129ae9 100644 --- a/src/include/utils/tqual.h +++ b/src/include/utils/tqual.h @@ -52,7 +52,7 @@ extern PGDLLIMPORT SnapshotData SnapshotToastData; * if so, the indicated buffer is marked dirty. */ #define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer) \ - ((*(snapshot)->satisfies) ((tuple)->t_data, snapshot, buffer)) + ((*(snapshot)->satisfies) (tuple, snapshot, buffer)) /* Result codes for HeapTupleSatisfiesVacuum */ typedef enum @@ -65,25 +65,25 @@ typedef enum } HTSV_Result; /* These are the "satisfies" test routines for the various snapshot types */ -extern bool HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, +extern bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer); -extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple, +extern bool HeapTupleSatisfiesNow(HeapTuple htup, Snapshot snapshot, Buffer buffer); -extern bool HeapTupleSatisfiesSelf(HeapTupleHeader tuple, +extern bool HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer); -extern bool HeapTupleSatisfiesAny(HeapTupleHeader tuple, +extern bool HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer); -extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple, +extern bool HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot, Buffer buffer); -extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple, +extern bool HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot, Buffer buffer); /* Special "satisfies" routines with different APIs */ -extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, +extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, Buffer buffer); -extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, +extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer); -extern bool HeapTupleIsSurelyDead(HeapTupleHeader tuple, +extern bool HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin); extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers