Andres Freund wrote:
> [09] Adjust all *Satisfies routines to take a HeapTuple instead of a
> HeapTupleHeader
>
> For timetravel access to the catalog we need to be able to lookup (cmin,
> cmax) pairs of catalog rows when were 'inside' that TX. This patch just
> adapts the signature of the *Satisfies routines to expect a HeapTuple
> instead of a HeapTupleHeader. The amount of changes for that is fairly
> low as the HeapTupleSatisfiesVisibility macro already expected the
> former.
>
> It also makes sure the HeapTuple fields are setup in the few places that
> didn't already do so.
I had a look at this part. Running the regression tests unveiled a case
where the tableOid wasn't being set (and thus caused an assertion to
fail), so I added that. I also noticed that the additions to
pruneheap.c are sometimes filling a tuple before it's strictly
necessary, leading to wasted work. Moved those too.
Looks good to me as attached.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
*** a/contrib/pgrowlocks/pgrowlocks.c
--- b/contrib/pgrowlocks/pgrowlocks.c
***************
*** 120,126 **** pgrowlocks(PG_FUNCTION_ARGS)
/* must hold a buffer lock to call HeapTupleSatisfiesUpdate */
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
! if (HeapTupleSatisfiesUpdate(tuple->t_data,
GetCurrentCommandId(false),
scan->rs_cbuf) == HeapTupleBeingUpdated)
{
--- 120,126 ----
/* must hold a buffer lock to call HeapTupleSatisfiesUpdate */
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
! if (HeapTupleSatisfiesUpdate(tuple,
GetCurrentCommandId(false),
scan->rs_cbuf) == HeapTupleBeingUpdated)
{
*** a/src/backend/access/heap/heapam.c
--- b/src/backend/access/heap/heapam.c
***************
*** 291,296 **** heapgetpage(HeapScanDesc scan, BlockNumber page)
--- 291,297 ----
loctup.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
loctup.t_len = ItemIdGetLength(lpp);
+ loctup.t_tableOid = RelationGetRelid(scan->rs_rd);
ItemPointerSet(&(loctup.t_self), page, lineoff);
if (all_visible)
***************
*** 1603,1609 **** 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_self = *tid;
/*
--- 1604,1610 ----
heapTuple->t_data = (HeapTupleHeader) PageGetItem(dp, lp);
heapTuple->t_len = ItemIdGetLength(lp);
! heapTuple->t_tableOid = RelationGetRelid(relation);
heapTuple->t_self = *tid;
/*
***************
*** 1651,1657 **** heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
* transactions.
*/
if (all_dead && *all_dead &&
! !HeapTupleIsSurelyDead(heapTuple->t_data, RecentGlobalXmin))
*all_dead = false;
/*
--- 1652,1658 ----
* transactions.
*/
if (all_dead && *all_dead &&
! !HeapTupleIsSurelyDead(heapTuple, RecentGlobalXmin))
*all_dead = false;
/*
***************
*** 1781,1786 **** heap_get_latest_tid(Relation relation,
--- 1782,1788 ----
tp.t_self = ctid;
tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
tp.t_len = ItemIdGetLength(lp);
+ tp.t_tableOid = RelationGetRelid(relation);
/*
* After following a t_ctid link, we might arrive at an unrelated
***************
*** 2447,2458 **** heap_delete(Relation relation, ItemPointer tid,
lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
Assert(ItemIdIsNormal(lp));
tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
tp.t_len = ItemIdGetLength(lp);
tp.t_self = *tid;
l1:
! result = HeapTupleSatisfiesUpdate(tp.t_data, cid, buffer);
if (result == HeapTupleInvisible)
{
--- 2449,2461 ----
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, cid, buffer);
if (result == HeapTupleInvisible)
{
***************
*** 2817,2822 **** heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
--- 2820,2826 ----
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;
***************
*** 2829,2835 **** heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
*/
l2:
! result = HeapTupleSatisfiesUpdate(oldtup.t_data, cid, buffer);
if (result == HeapTupleInvisible)
{
--- 2833,2839 ----
*/
l2:
! result = HeapTupleSatisfiesUpdate(&oldtup, cid, buffer);
if (result == HeapTupleInvisible)
{
***************
*** 3531,3537 **** heap_lock_tuple(Relation relation, HeapTuple tuple,
tuple->t_tableOid = RelationGetRelid(relation);
l3:
! result = HeapTupleSatisfiesUpdate(tuple->t_data, cid, *buffer);
if (result == HeapTupleInvisible)
{
--- 3535,3541 ----
tuple->t_tableOid = RelationGetRelid(relation);
l3:
! result = HeapTupleSatisfiesUpdate(tuple, cid, *buffer);
if (result == HeapTupleInvisible)
{
*** a/src/backend/access/heap/pruneheap.c
--- b/src/backend/access/heap/pruneheap.c
***************
*** 340,345 **** heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum,
--- 340,348 ----
OffsetNumber chainitems[MaxHeapTuplesPerPage];
int nchain = 0,
i;
+ HeapTupleData tup;
+
+ tup.t_tableOid = RelationGetRelid(relation);
rootlp = PageGetItemId(dp, rootoffnum);
***************
*** 349,356 **** heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum,
--- 352,365 ----
if (ItemIdIsNormal(rootlp))
{
htup = (HeapTupleHeader) PageGetItem(dp, rootlp);
+
if (HeapTupleHeaderIsHeapOnly(htup))
{
+ /* fill in the rest of the tuple */
+ tup.t_data = htup;
+ tup.t_len = ItemIdGetLength(rootlp);
+ ItemPointerSet(&(tup.t_self), BufferGetBlockNumber(buffer), rootoffnum);
+
/*
* If the tuple is DEAD and doesn't chain to anything else, mark
* it unused immediately. (If it does chain, we can only remove
***************
*** 369,375 **** 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)
== HEAPTUPLE_DEAD && !HeapTupleHeaderIsHotUpdated(htup))
{
heap_prune_record_unused(prstate, rootoffnum);
--- 378,384 ----
* either here or while following a chain below. Whichever path
* gets there first will mark the tuple unused.
*/
! if (HeapTupleSatisfiesVacuum(&tup, OldestXmin, buffer)
== HEAPTUPLE_DEAD && !HeapTupleHeaderIsHotUpdated(htup))
{
heap_prune_record_unused(prstate, rootoffnum);
***************
*** 448,455 **** heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum,
* Check tuple's visibility status.
*/
tupdead = recent_dead = false;
! switch (HeapTupleSatisfiesVacuum(htup, OldestXmin, buffer))
{
case HEAPTUPLE_DEAD:
tupdead = true;
--- 457,467 ----
* Check tuple's visibility status.
*/
tupdead = recent_dead = false;
+ tup.t_data = htup;
+ tup.t_len = ItemIdGetLength(lp);
+ ItemPointerSet(&(tup.t_self), BufferGetBlockNumber(buffer), offnum);
! switch (HeapTupleSatisfiesVacuum(&tup, OldestXmin, buffer))
{
case HEAPTUPLE_DEAD:
tupdead = true;
*** a/src/backend/catalog/index.c
--- b/src/backend/catalog/index.c
***************
*** 2269,2275 **** IndexBuildHeapScan(Relation heapRelation,
*/
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
! switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin,
scan->rs_cbuf))
{
case HEAPTUPLE_DEAD:
--- 2269,2275 ----
*/
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
! switch (HeapTupleSatisfiesVacuum(heapTuple, OldestXmin,
scan->rs_cbuf))
{
case HEAPTUPLE_DEAD:
*** a/src/backend/commands/analyze.c
--- b/src/backend/commands/analyze.c
***************
*** 1134,1143 **** acquire_sample_rows(Relation onerel, int elevel,
ItemPointerSet(&targtuple.t_self, targblock, targoffset);
targtuple.t_data = (HeapTupleHeader) PageGetItem(targpage, itemid);
targtuple.t_len = ItemIdGetLength(itemid);
! switch (HeapTupleSatisfiesVacuum(targtuple.t_data,
OldestXmin,
targbuffer))
{
--- 1134,1144 ----
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,
OldestXmin,
targbuffer))
{
*** a/src/backend/commands/cluster.c
--- b/src/backend/commands/cluster.c
***************
*** 931,937 **** copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
LockBuffer(buf, BUFFER_LOCK_SHARE);
! switch (HeapTupleSatisfiesVacuum(tuple->t_data, OldestXmin, buf))
{
case HEAPTUPLE_DEAD:
/* Definitely dead */
--- 931,937 ----
LockBuffer(buf, BUFFER_LOCK_SHARE);
! switch (HeapTupleSatisfiesVacuum(tuple, OldestXmin, buf))
{
case HEAPTUPLE_DEAD:
/* Definitely dead */
*** a/src/backend/commands/vacuumlazy.c
--- b/src/backend/commands/vacuumlazy.c
***************
*** 727,738 **** lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
Assert(ItemIdIsNormal(itemid));
tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
tuple.t_len = ItemIdGetLength(itemid);
tupgone = false;
! switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
{
case HEAPTUPLE_DEAD:
--- 727,739 ----
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, OldestXmin, buf))
{
case HEAPTUPLE_DEAD:
*** a/src/backend/storage/lmgr/predicate.c
--- b/src/backend/storage/lmgr/predicate.c
***************
*** 3894,3900 **** 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);
switch (htsvResult)
{
case HEAPTUPLE_LIVE:
--- 3894,3900 ----
* tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
* is going on with it.
*/
! htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
switch (htsvResult)
{
case HEAPTUPLE_LIVE:
*** a/src/backend/utils/time/tqual.c
--- b/src/backend/utils/time/tqual.c
***************
*** 163,170 **** HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
* Xmax is not committed))) that has not been committed
*/
bool
! HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
{
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
{
if (tuple->t_infomask & HEAP_XMIN_INVALID)
--- 163,174 ----
* Xmax is not committed))) that has not been committed
*/
bool
! 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,333 **** HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
*
*/
bool
! HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
{
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
{
if (tuple->t_infomask & HEAP_XMIN_INVALID)
--- 330,341 ----
*
*/
bool
! 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,477 **** HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
* Dummy "satisfies" routine: any tuple satisfies SnapshotAny.
*/
bool
! HeapTupleSatisfiesAny(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
{
return true;
}
--- 479,485 ----
* Dummy "satisfies" routine: any tuple satisfies SnapshotAny.
*/
bool
! HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer)
{
return true;
}
***************
*** 491,499 **** HeapTupleSatisfiesAny(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
* table.
*/
bool
! HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot,
Buffer buffer)
{
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
{
if (tuple->t_infomask & HEAP_XMIN_INVALID)
--- 499,511 ----
* table.
*/
bool
! 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,580 **** HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot,
* distinguish that case must test for it themselves.)
*/
HTSU_Result
! HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
Buffer buffer)
{
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
{
if (tuple->t_infomask & HEAP_XMIN_INVALID)
--- 584,596 ----
* distinguish that case must test for it themselves.)
*/
HTSU_Result
! 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,747 **** HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
* for snapshot->xmax and the tuple's xmax.
*/
bool
! HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot,
Buffer buffer)
{
snapshot->xmin = snapshot->xmax = InvalidTransactionId;
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
--- 755,767 ----
* for snapshot->xmax and the tuple's xmax.
*/
bool
! 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,910 **** HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot,
* can't see it.)
*/
bool
! HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot,
Buffer buffer)
{
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
{
if (tuple->t_infomask & HEAP_XMIN_INVALID)
--- 922,935 ----
* can't see it.)
*/
bool
! 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,1066 **** HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot,
* even if we see that the deleting transaction has committed.
*/
HTSV_Result
! HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
Buffer buffer)
{
/*
* Has inserting transaction committed?
*
--- 1083,1095 ----
* even if we see that the deleting transaction has committed.
*/
HTSV_Result
! 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,1240 **** HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
* just whether or not the tuple is surely dead).
*/
bool
! HeapTupleIsSurelyDead(HeapTupleHeader tuple, TransactionId OldestXmin)
{
/*
* If the inserting transaction is marked invalid, then it aborted, and
* the tuple is definitely dead. If it's marked neither committed nor
--- 1262,1273 ----
* just whether or not the tuple is surely dead).
*/
bool
! 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
*** a/src/include/utils/snapshot.h
--- b/src/include/utils/snapshot.h
***************
*** 27,34 **** 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 struct SnapshotData
{
--- 27,34 ----
* The specific semantics of a snapshot are encoded by the "satisfies"
* function.
*/
! typedef bool (*SnapshotSatisfiesFunc) (HeapTuple htup,
! Snapshot snapshot, Buffer buffer);
typedef struct SnapshotData
{
*** a/src/include/utils/tqual.h
--- b/src/include/utils/tqual.h
***************
*** 52,58 **** extern PGDLLIMPORT SnapshotData SnapshotToastData;
* if so, the indicated buffer is marked dirty.
*/
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer) \
! ((*(snapshot)->satisfies) ((tuple)->t_data, snapshot, buffer))
/* Result codes for HeapTupleSatisfiesVacuum */
typedef enum
--- 52,58 ----
* if so, the indicated buffer is marked dirty.
*/
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer) \
! ((*(snapshot)->satisfies) (tuple, snapshot, buffer))
/* Result codes for HeapTupleSatisfiesVacuum */
typedef enum
***************
*** 65,89 **** typedef enum
} HTSV_Result;
/* These are the "satisfies" test routines for the various snapshot types */
! extern bool HeapTupleSatisfiesMVCC(HeapTupleHeader tuple,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesSelf(HeapTupleHeader tuple,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesAny(HeapTupleHeader tuple,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple,
Snapshot snapshot, Buffer buffer);
/* Special "satisfies" routines with different APIs */
! extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTupleHeader tuple,
CommandId curcid, Buffer buffer);
! extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
TransactionId OldestXmin, Buffer buffer);
! extern bool HeapTupleIsSurelyDead(HeapTupleHeader tuple,
TransactionId OldestXmin);
extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
--- 65,89 ----
} HTSV_Result;
/* These are the "satisfies" test routines for the various snapshot types */
! extern bool HeapTupleSatisfiesMVCC(HeapTuple htup,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesNow(HeapTuple htup,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesSelf(HeapTuple htup,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesAny(HeapTuple htup,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesToast(HeapTuple htup,
Snapshot snapshot, Buffer buffer);
! extern bool HeapTupleSatisfiesDirty(HeapTuple htup,
Snapshot snapshot, Buffer buffer);
/* Special "satisfies" routines with different APIs */
! extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple htup,
CommandId curcid, Buffer buffer);
! extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup,
TransactionId OldestXmin, Buffer buffer);
! extern bool HeapTupleIsSurelyDead(HeapTuple htup,
TransactionId OldestXmin);
extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers