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 (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to