Re: HeapTupleHeader accessor macros

Поиск
Список
Период
Сортировка
Искать
От
Bruce Momjian
Тема
Re: HeapTupleHeader accessor macros
Дата
Msg-id
200206140507.g5E571l04275@candle.pha.pa.us
Ответ на
Список
Дерево обсуждения
HeapTupleHeader accessor macros Manfred Koizar <mkoi-pg@aon.at>
Re: HeapTupleHeader accessor macros Bruce Momjian <pgman@candle.pha.pa.us>
HeapTupleHeader accessor macros II Manfred Koizar <mkoi-pg@aon.at>
Re: HeapTupleHeader accessor macros II Bruce Momjian <pgman@candle.pha.pa.us>
Re: HeapTupleHeader accessor macros II Bruce Momjian <pgman@candle.pha.pa.us>

Your patch has been added to the PostgreSQL unapplied patches list at:

	http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------


Manfred Koizar wrote:
> This patch wraps all accesses to t_xmin, t_cmin, t_xmax, and t_cmax in
> HeapTupleHeaderData in setter and getter macros called
> HeapTupleHeaderGetXmin, HeapTupleHeaderSetXmin etc.
> 
> It also introduces a "virtual" field xvac by defining
> HeapTupleHeaderGetXvac and HeapTupleHeaderSetXvac.  Xvac is used by
> VACUUM, in fact it is stored in t_cmin.
> 
> This patch doesn't change any behaviour, it just (hopefully) makes the
> source code more readable.  It is meant as a first step toward an
> upcoming change in HeapTupleHeader, which will reduce on-disk tuple
> size by four bytes.
> 
> Regression tests have been passed (except geometry, which always fails
> on my machine).  Please apply this patch (after my bitmaplen patch)
> for 7.3.
> 
> It worked for 7.2 before I updated my cvs HEAD revision and recreated
> the patch.  If cosmetic changes are wanted for 7.2, I'll make a 7.2
> version available.
> 
> Servus
>  Manfred

> diff -c -r ../orig/src/backend/access/common/heaptuple.c src/backend/access/common/heaptuple.c
> *** ../orig/src/backend/access/common/heaptuple.c	Thu Oct 25 07:49:20 2001
> --- src/backend/access/common/heaptuple.c	Sat May 11 14:54:50 2002
> ***************
> *** 439,454 ****
>   			result = ObjectIdGetDatum(tup->t_data->t_oid);
>   			break;
>   		case MinTransactionIdAttributeNumber:
> ! 			result = TransactionIdGetDatum(tup->t_data->t_xmin);
>   			break;
>   		case MinCommandIdAttributeNumber:
> ! 			result = CommandIdGetDatum(tup->t_data->t_cmin);
>   			break;
>   		case MaxTransactionIdAttributeNumber:
> ! 			result = TransactionIdGetDatum(tup->t_data->t_xmax);
>   			break;
>   		case MaxCommandIdAttributeNumber:
> ! 			result = CommandIdGetDatum(tup->t_data->t_cmax);
>   			break;
>   		case TableOidAttributeNumber:
>   			result = ObjectIdGetDatum(tup->t_tableOid);
> --- 439,454 ----
>   			result = ObjectIdGetDatum(tup->t_data->t_oid);
>   			break;
>   		case MinTransactionIdAttributeNumber:
> ! 			result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
>   			break;
>   		case MinCommandIdAttributeNumber:
> ! 			result = CommandIdGetDatum(HeapTupleHeaderGetCmin(tup->t_data));
>   			break;
>   		case MaxTransactionIdAttributeNumber:
> ! 			result = TransactionIdGetDatum(HeapTupleHeaderGetXmax(tup->t_data));
>   			break;
>   		case MaxCommandIdAttributeNumber:
> ! 			result = CommandIdGetDatum(HeapTupleHeaderGetCmax(tup->t_data));
>   			break;
>   		case TableOidAttributeNumber:
>   			result = ObjectIdGetDatum(tup->t_tableOid);
> diff -c -r ../orig/src/backend/access/heap/heapam.c src/backend/access/heap/heapam.c
> *** ../orig/src/backend/access/heap/heapam.c	Wed May  1 03:23:37 2002
> --- src/backend/access/heap/heapam.c	Sat May 11 18:13:45 2002
> ***************
> *** 1118,1128 ****
>   			CheckMaxObjectId(tup->t_data->t_oid);
>   	}
>   
> - 	TransactionIdStore(GetCurrentTransactionId(), &(tup->t_data->t_xmin));
> - 	tup->t_data->t_cmin = GetCurrentCommandId();
> - 	StoreInvalidTransactionId(&(tup->t_data->t_xmax));
>   	tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
>   	tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
>   	tup->t_tableOid = relation->rd_id;
>   
>   #ifdef TUPLE_TOASTER_ACTIVE
> --- 1118,1128 ----
>   			CheckMaxObjectId(tup->t_data->t_oid);
>   	}
>   
>   	tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
>   	tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
> + 	HeapTupleHeaderSetXmin(tup->t_data, GetCurrentTransactionId());
> + 	HeapTupleHeaderSetCmin(tup->t_data, GetCurrentCommandId());
> + 	HeapTupleHeaderSetXmaxInvalid(tup->t_data);
>   	tup->t_tableOid = relation->rd_id;
>   
>   #ifdef TUPLE_TOASTER_ACTIVE
> ***************
> *** 1251,1257 ****
>   	}
>   	else if (result == HeapTupleBeingUpdated)
>   	{
> ! 		TransactionId xwait = tp.t_data->t_xmax;
>   
>   		/* sleep until concurrent transaction ends */
>   		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
> --- 1251,1257 ----
>   	}
>   	else if (result == HeapTupleBeingUpdated)
>   	{
> ! 		TransactionId xwait = HeapTupleHeaderGetXmax(tp.t_data);
>   
>   		/* sleep until concurrent transaction ends */
>   		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
> ***************
> *** 1266,1272 ****
>   		 * update then some other xaction could update this tuple before
>   		 * we got to this point.
>   		 */
> ! 		if (!TransactionIdEquals(tp.t_data->t_xmax, xwait))
>   			goto l1;
>   		if (!(tp.t_data->t_infomask & HEAP_XMAX_COMMITTED))
>   		{
> --- 1266,1272 ----
>   		 * update then some other xaction could update this tuple before
>   		 * we got to this point.
>   		 */
> ! 		if (!TransactionIdEquals(HeapTupleHeaderGetXmax(tp.t_data), xwait))
>   			goto l1;
>   		if (!(tp.t_data->t_infomask & HEAP_XMAX_COMMITTED))
>   		{
> ***************
> *** 1290,1299 ****
>   
>   	START_CRIT_SECTION();
>   	/* store transaction information of xact deleting the tuple */
> - 	TransactionIdStore(GetCurrentTransactionId(), &(tp.t_data->t_xmax));
> - 	tp.t_data->t_cmax = GetCurrentCommandId();
>   	tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   							 HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
>   	/* XLOG stuff */
>   	{
>   		xl_heap_delete xlrec;
> --- 1290,1299 ----
>   
>   	START_CRIT_SECTION();
>   	/* store transaction information of xact deleting the tuple */
>   	tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   							 HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
> + 	HeapTupleHeaderSetXmax(tp.t_data, GetCurrentTransactionId());
> + 	HeapTupleHeaderSetCmax(tp.t_data, GetCurrentCommandId());
>   	/* XLOG stuff */
>   	{
>   		xl_heap_delete xlrec;
> ***************
> *** 1443,1449 ****
>   	}
>   	else if (result == HeapTupleBeingUpdated)
>   	{
> ! 		TransactionId xwait = oldtup.t_data->t_xmax;
>   
>   		/* sleep untill concurrent transaction ends */
>   		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
> --- 1443,1449 ----
>   	}
>   	else if (result == HeapTupleBeingUpdated)
>   	{
> ! 		TransactionId xwait = HeapTupleHeaderGetXmax(oldtup.t_data);
>   
>   		/* sleep untill concurrent transaction ends */
>   		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
> ***************
> *** 1458,1464 ****
>   		 * update then some other xaction could update this tuple before
>   		 * we got to this point.
>   		 */
> ! 		if (!TransactionIdEquals(oldtup.t_data->t_xmax, xwait))
>   			goto l2;
>   		if (!(oldtup.t_data->t_infomask & HEAP_XMAX_COMMITTED))
>   		{
> --- 1458,1464 ----
>   		 * update then some other xaction could update this tuple before
>   		 * we got to this point.
>   		 */
> ! 		if (!TransactionIdEquals(HeapTupleHeaderGetXmax(oldtup.t_data), xwait))
>   			goto l2;
>   		if (!(oldtup.t_data->t_infomask & HEAP_XMAX_COMMITTED))
>   		{
> ***************
> *** 1482,1492 ****
>   
>   	/* Fill in OID and transaction status data for newtup */
>   	newtup->t_data->t_oid = oldtup.t_data->t_oid;
> - 	TransactionIdStore(GetCurrentTransactionId(), &(newtup->t_data->t_xmin));
> - 	newtup->t_data->t_cmin = GetCurrentCommandId();
> - 	StoreInvalidTransactionId(&(newtup->t_data->t_xmax));
>   	newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
>   	newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED);
>   
>   	/*
>   	 * If the toaster needs to be activated, OR if the new tuple will not
> --- 1482,1492 ----
>   
>   	/* Fill in OID and transaction status data for newtup */
>   	newtup->t_data->t_oid = oldtup.t_data->t_oid;
>   	newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
>   	newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED);
> + 	HeapTupleHeaderSetXmin(newtup->t_data, GetCurrentTransactionId());
> + 	HeapTupleHeaderSetCmin(newtup->t_data, GetCurrentCommandId());
> + 	HeapTupleHeaderSetXmaxInvalid(newtup->t_data);
>   
>   	/*
>   	 * If the toaster needs to be activated, OR if the new tuple will not
> ***************
> *** 1520,1532 ****
>   		_locked_tuple_.tid = oldtup.t_self;
>   		XactPushRollback(_heap_unlock_tuple, (void *) &_locked_tuple_);
>   
> - 		TransactionIdStore(GetCurrentTransactionId(),
> - 						   &(oldtup.t_data->t_xmax));
> - 		oldtup.t_data->t_cmax = GetCurrentCommandId();
>   		oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   									   HEAP_XMAX_INVALID |
>   									   HEAP_MARKED_FOR_UPDATE);
>   		oldtup.t_data->t_infomask |= HEAP_XMAX_UNLOGGED;
>   		already_marked = true;
>   		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
>   
> --- 1520,1531 ----
>   		_locked_tuple_.tid = oldtup.t_self;
>   		XactPushRollback(_heap_unlock_tuple, (void *) &_locked_tuple_);
>   
>   		oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   									   HEAP_XMAX_INVALID |
>   									   HEAP_MARKED_FOR_UPDATE);
>   		oldtup.t_data->t_infomask |= HEAP_XMAX_UNLOGGED;
> + 		HeapTupleHeaderSetXmax(oldtup.t_data, GetCurrentTransactionId());
> + 		HeapTupleHeaderSetCmax(oldtup.t_data, GetCurrentCommandId());
>   		already_marked = true;
>   		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
>   
> ***************
> *** 1612,1623 ****
>   	}
>   	else
>   	{
> - 		TransactionIdStore(GetCurrentTransactionId(),
> - 						   &(oldtup.t_data->t_xmax));
> - 		oldtup.t_data->t_cmax = GetCurrentCommandId();
>   		oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   									   HEAP_XMAX_INVALID |
>   									   HEAP_MARKED_FOR_UPDATE);
>   	}
>   
>   	/* record address of new tuple in t_ctid of old one */
> --- 1611,1621 ----
>   	}
>   	else
>   	{
>   		oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   									   HEAP_XMAX_INVALID |
>   									   HEAP_MARKED_FOR_UPDATE);
> + 		HeapTupleHeaderSetXmax(oldtup.t_data, GetCurrentTransactionId());
> + 		HeapTupleHeaderSetCmax(oldtup.t_data, GetCurrentCommandId());
>   	}
>   
>   	/* record address of new tuple in t_ctid of old one */
> ***************
> *** 1740,1746 ****
>   	}
>   	else if (result == HeapTupleBeingUpdated)
>   	{
> ! 		TransactionId xwait = tuple->t_data->t_xmax;
>   
>   		/* sleep untill concurrent transaction ends */
>   		LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
> --- 1738,1744 ----
>   	}
>   	else if (result == HeapTupleBeingUpdated)
>   	{
> ! 		TransactionId xwait = HeapTupleHeaderGetXmax(tuple->t_data);
>   
>   		/* sleep untill concurrent transaction ends */
>   		LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
> ***************
> *** 1755,1761 ****
>   		 * update then some other xaction could update this tuple before
>   		 * we got to this point.
>   		 */
> ! 		if (!TransactionIdEquals(tuple->t_data->t_xmax, xwait))
>   			goto l3;
>   		if (!(tuple->t_data->t_infomask & HEAP_XMAX_COMMITTED))
>   		{
> --- 1753,1759 ----
>   		 * update then some other xaction could update this tuple before
>   		 * we got to this point.
>   		 */
> ! 		if (!TransactionIdEquals(HeapTupleHeaderGetXmax(tuple->t_data), xwait))
>   			goto l3;
>   		if (!(tuple->t_data->t_infomask & HEAP_XMAX_COMMITTED))
>   		{
> ***************
> *** 1783,1792 ****
>   	((PageHeader) BufferGetPage(*buffer))->pd_sui = ThisStartUpID;
>   
>   	/* store transaction information of xact marking the tuple */
> - 	TransactionIdStore(GetCurrentTransactionId(), &(tuple->t_data->t_xmax));
> - 	tuple->t_data->t_cmax = GetCurrentCommandId();
>   	tuple->t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
>   	tuple->t_data->t_infomask |= HEAP_MARKED_FOR_UPDATE;
>   
>   	LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
>   
> --- 1781,1790 ----
>   	((PageHeader) BufferGetPage(*buffer))->pd_sui = ThisStartUpID;
>   
>   	/* store transaction information of xact marking the tuple */
>   	tuple->t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
>   	tuple->t_data->t_infomask |= HEAP_MARKED_FOR_UPDATE;
> + 	HeapTupleHeaderSetXmax(tuple->t_data, GetCurrentTransactionId());
> + 	HeapTupleHeaderSetCmax(tuple->t_data, GetCurrentCommandId());
>   
>   	LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
>   
> ***************
> *** 1962,1976 ****
>   	if (move)					/* remember xmin & xmax */
>   	{
>   		TransactionId xmax;
>   
>   		if (newtup->t_data->t_infomask & HEAP_XMAX_INVALID ||
>   			newtup->t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			xmax = InvalidTransactionId;
>   		else
> ! 			xmax = newtup->t_data->t_xmax;
>   		memcpy((char *) &xlhdr + hsize, &xmax, sizeof(TransactionId));
>   		memcpy((char *) &xlhdr + hsize + sizeof(TransactionId),
> ! 			   &(newtup->t_data->t_xmin), sizeof(TransactionId));
>   		hsize += 2 * sizeof(TransactionId);
>   	}
>   	rdata[2].buffer = newbuf;
> --- 1960,1976 ----
>   	if (move)					/* remember xmin & xmax */
>   	{
>   		TransactionId xmax;
> + 		TransactionId xmin;
>   
>   		if (newtup->t_data->t_infomask & HEAP_XMAX_INVALID ||
>   			newtup->t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			xmax = InvalidTransactionId;
>   		else
> ! 			xmax = HeapTupleHeaderGetXmax(newtup->t_data);
> ! 		xmin = HeapTupleHeaderGetXmin(newtup->t_data);
>   		memcpy((char *) &xlhdr + hsize, &xmax, sizeof(TransactionId));
>   		memcpy((char *) &xlhdr + hsize + sizeof(TransactionId),
> ! 			   &xmin, sizeof(TransactionId));
>   		hsize += 2 * sizeof(TransactionId);
>   	}
>   	rdata[2].buffer = newbuf;
> ***************
> *** 2107,2116 ****
>   
>   	if (redo)
>   	{
> - 		htup->t_xmax = record->xl_xid;
> - 		htup->t_cmax = FirstCommandId;
>   		htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   							  HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
>   		PageSetLSN(page, lsn);
>   		PageSetSUI(page, ThisStartUpID);
>   		UnlockAndWriteBuffer(buffer);
> --- 2107,2116 ----
>   
>   	if (redo)
>   	{
>   		htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   							  HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
> + 		HeapTupleHeaderSetXmax(htup, record->xl_xid);
> + 		HeapTupleHeaderSetCmax(htup, FirstCommandId);
>   		PageSetLSN(page, lsn);
>   		PageSetSUI(page, ThisStartUpID);
>   		UnlockAndWriteBuffer(buffer);
> ***************
> *** 2182,2192 ****
>   		htup->t_oid = xlhdr.t_oid;
>   		htup->t_natts = xlhdr.t_natts;
>   		htup->t_hoff = xlhdr.t_hoff;
> - 		htup->t_xmin = record->xl_xid;
> - 		htup->t_cmin = FirstCommandId;
> - 		htup->t_xmax = InvalidTransactionId;
> - 		htup->t_cmax = FirstCommandId;
>   		htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
>   
>   		offnum = PageAddItem(page, (Item) htup, newlen, offnum,
>   							 LP_USED | OverwritePageMode);
> --- 2182,2192 ----
>   		htup->t_oid = xlhdr.t_oid;
>   		htup->t_natts = xlhdr.t_natts;
>   		htup->t_hoff = xlhdr.t_hoff;
>   		htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
> + 		HeapTupleHeaderSetXmin(htup, record->xl_xid);
> + 		HeapTupleHeaderSetCmin(htup, FirstCommandId);
> + 		HeapTupleHeaderSetXmax(htup, InvalidTransactionId);
> + 		HeapTupleHeaderSetCmax(htup, FirstCommandId);
>   
>   		offnum = PageAddItem(page, (Item) htup, newlen, offnum,
>   							 LP_USED | OverwritePageMode);
> ***************
> *** 2267,2283 ****
>   	{
>   		if (move)
>   		{
> - 			TransactionIdStore(record->xl_xid, (TransactionId *) &(htup->t_cmin));
>   			htup->t_infomask &=
>   				~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
>   			htup->t_infomask |= HEAP_MOVED_OFF;
>   		}
>   		else
>   		{
> - 			htup->t_xmax = record->xl_xid;
> - 			htup->t_cmax = FirstCommandId;
>   			htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   							 HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
>   		}
>   		if (samepage)
>   			goto newsame;
> --- 2267,2283 ----
>   	{
>   		if (move)
>   		{
>   			htup->t_infomask &=
>   				~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
>   			htup->t_infomask |= HEAP_MOVED_OFF;
> + 			HeapTupleHeaderSetXvac(htup, record->xl_xid);
>   		}
>   		else
>   		{
>   			htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |
>   							 HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
> + 			HeapTupleHeaderSetXmax(htup, record->xl_xid);
> + 			HeapTupleHeaderSetCmax(htup, FirstCommandId);
>   		}
>   		if (samepage)
>   			goto newsame;
> ***************
> *** 2353,2378 ****
>   		htup->t_hoff = xlhdr.t_hoff;
>   		if (move)
>   		{
>   			hsize = SizeOfHeapUpdate + SizeOfHeapHeader;
> ! 			memcpy(&(htup->t_xmax),
> ! 				   (char *) xlrec + hsize,
> ! 				   sizeof(TransactionId));
> ! 			memcpy(&(htup->t_xmin),
> ! 				   (char *) xlrec + hsize + sizeof(TransactionId),
> ! 				   sizeof(TransactionId));
> ! 			TransactionIdStore(record->xl_xid, (TransactionId *) &(htup->t_cmin));
>   			htup->t_infomask = xlhdr.mask;
>   			htup->t_infomask &= ~(HEAP_XMIN_COMMITTED |
>   								  HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
>   			htup->t_infomask |= HEAP_MOVED_IN;
>   		}
>   		else
>   		{
> - 			htup->t_xmin = record->xl_xid;
> - 			htup->t_cmin = FirstCommandId;
> - 			htup->t_xmax = InvalidTransactionId;
> - 			htup->t_cmax = FirstCommandId;
>   			htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
>   		}
>   
>   		offnum = PageAddItem(page, (Item) htup, newlen, offnum,
> --- 2353,2379 ----
>   		htup->t_hoff = xlhdr.t_hoff;
>   		if (move)
>   		{
> + 			TransactionId xmax;
> + 			TransactionId xmin;
> + 			
>   			hsize = SizeOfHeapUpdate + SizeOfHeapHeader;
> ! 			memcpy(&xmax, (char *) xlrec + hsize, sizeof(TransactionId));
> ! 			memcpy(&xmin, (char *) xlrec + hsize + sizeof(TransactionId), sizeof(TransactionId));
>   			htup->t_infomask = xlhdr.mask;
>   			htup->t_infomask &= ~(HEAP_XMIN_COMMITTED |
>   								  HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
>   			htup->t_infomask |= HEAP_MOVED_IN;
> + 			HeapTupleHeaderSetXmin(htup, xmin);
> + 			HeapTupleHeaderSetXmax(htup, xmax);
> + 			HeapTupleHeaderSetXvac(htup, record->xl_xid);
>   		}
>   		else
>   		{
>   			htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
> + 			HeapTupleHeaderSetXmin(htup, record->xl_xid);
> + 			HeapTupleHeaderSetCmin(htup, FirstCommandId);
> + 			HeapTupleHeaderSetXmaxInvalid(htup);
> + 			HeapTupleHeaderSetCmax(htup, FirstCommandId);
>   		}
>   
>   		offnum = PageAddItem(page, (Item) htup, newlen, offnum,
> ***************
> *** 2426,2433 ****
>   
>   	htup = (HeapTupleHeader) PageGetItem(page, lp);
>   
> ! 	if (!TransactionIdEquals(htup->t_xmax, GetCurrentTransactionId()) ||
> ! 		htup->t_cmax != GetCurrentCommandId())
>   		elog(PANIC, "_heap_unlock_tuple: invalid xmax/cmax in rollback");
>   	htup->t_infomask &= ~HEAP_XMAX_UNLOGGED;
>   	htup->t_infomask |= HEAP_XMAX_INVALID;
> --- 2427,2434 ----
>   
>   	htup = (HeapTupleHeader) PageGetItem(page, lp);
>   
> ! 	if (!TransactionIdEquals(HeapTupleHeaderGetXmax(htup), GetCurrentTransactionId()) ||
> ! 		HeapTupleHeaderGetCmax(htup) != GetCurrentCommandId())
>   		elog(PANIC, "_heap_unlock_tuple: invalid xmax/cmax in rollback");
>   	htup->t_infomask &= ~HEAP_XMAX_UNLOGGED;
>   	htup->t_infomask |= HEAP_XMAX_INVALID;
> diff -c -r ../orig/src/backend/access/transam/xlogutils.c src/backend/access/transam/xlogutils.c
> *** ../orig/src/backend/access/transam/xlogutils.c	Sun Mar 31 08:26:29 2002
> --- src/backend/access/transam/xlogutils.c	Sat May 11 15:16:40 2002
> ***************
> *** 73,79 ****
>   	htup = (HeapTupleHeader) PageGetItem(page, lp);
>   
>   	Assert(PageGetSUI(page) == ThisStartUpID);
> ! 	if (!TransactionIdEquals(htup->t_xmin, xid) || htup->t_cmin != cid)
>   	{
>   		UnlockAndReleaseBuffer(buffer);
>   		return (-1);
> --- 73,80 ----
>   	htup = (HeapTupleHeader) PageGetItem(page, lp);
>   
>   	Assert(PageGetSUI(page) == ThisStartUpID);
> ! 	if (!TransactionIdEquals(HeapTupleHeaderGetXmin(htup), xid) ||
> ! 		HeapTupleHeaderGetCmin(htup) != cid)
>   	{
>   		UnlockAndReleaseBuffer(buffer);
>   		return (-1);
> ***************
> *** 137,144 ****
>   	{
>   		if (htup->t_infomask & HEAP_XMIN_INVALID ||
>   			(htup->t_infomask & HEAP_MOVED_IN &&
> ! 			 TransactionIdDidAbort((TransactionId) htup->t_cmin)) ||
> ! 			TransactionIdDidAbort(htup->t_xmin))
>   		{
>   			UnlockAndReleaseBuffer(buffer);
>   			return (false);
> --- 138,145 ----
>   	{
>   		if (htup->t_infomask & HEAP_XMIN_INVALID ||
>   			(htup->t_infomask & HEAP_MOVED_IN &&
> ! 			 TransactionIdDidAbort(HeapTupleHeaderGetXvac(htup))) ||
> ! 			TransactionIdDidAbort(HeapTupleHeaderGetXmin(htup)))
>   		{
>   			UnlockAndReleaseBuffer(buffer);
>   			return (false);
> diff -c -r ../orig/src/backend/catalog/index.c src/backend/catalog/index.c
> *** ../orig/src/backend/catalog/index.c	Sat Apr 27 23:24:34 2002
> --- src/backend/catalog/index.c	Sat May 11 15:34:12 2002
> ***************
> *** 1622,1628 ****
>   					 * (Consider INSERT followed by CREATE INDEX within a
>   					 * transaction.)
>   					 */
> ! 					if (!TransactionIdIsCurrentTransactionId(heapTuple->t_data->t_xmin))
>   						elog(ERROR, "IndexBuildHeapScan: concurrent insert in progress");
>   					indexIt = true;
>   					tupleIsAlive = true;
> --- 1622,1629 ----
>   					 * (Consider INSERT followed by CREATE INDEX within a
>   					 * transaction.)
>   					 */
> ! 					if (!TransactionIdIsCurrentTransactionId(
> ! 							HeapTupleHeaderGetXmin(heapTuple->t_data)))
>   						elog(ERROR, "IndexBuildHeapScan: concurrent insert in progress");
>   					indexIt = true;
>   					tupleIsAlive = true;
> ***************
> *** 1636,1642 ****
>   					 * (Consider DELETE followed by CREATE INDEX within a
>   					 * transaction.)
>   					 */
> ! 					if (!TransactionIdIsCurrentTransactionId(heapTuple->t_data->t_xmax))
>   						elog(ERROR, "IndexBuildHeapScan: concurrent delete in progress");
>   					indexIt = true;
>   					tupleIsAlive = false;
> --- 1637,1644 ----
>   					 * (Consider DELETE followed by CREATE INDEX within a
>   					 * transaction.)
>   					 */
> ! 					if (!TransactionIdIsCurrentTransactionId(
> ! 							HeapTupleHeaderGetXmax(heapTuple->t_data)))
>   						elog(ERROR, "IndexBuildHeapScan: concurrent delete in progress");
>   					indexIt = true;
>   					tupleIsAlive = false;
> diff -c -r ../orig/src/backend/commands/sequence.c src/backend/commands/sequence.c
> *** ../orig/src/backend/commands/sequence.c	Mon Apr 15 07:22:03 2002
> --- src/backend/commands/sequence.c	Sat May 11 15:36:05 2002
> ***************
> *** 233,242 ****
>   		itemId = PageGetItemId((Page) page, FirstOffsetNumber);
>   		item = PageGetItem((Page) page, itemId);
>   
> ! 		((HeapTupleHeader) item)->t_xmin = FrozenTransactionId;
>   		((HeapTupleHeader) item)->t_infomask |= HEAP_XMIN_COMMITTED;
>   
> ! 		tuple->t_data->t_xmin = FrozenTransactionId;
>   		tuple->t_data->t_infomask |= HEAP_XMIN_COMMITTED;
>   	}
>   
> --- 233,242 ----
>   		itemId = PageGetItemId((Page) page, FirstOffsetNumber);
>   		item = PageGetItem((Page) page, itemId);
>   
> ! 		HeapTupleHeaderSetXmin((HeapTupleHeader) item, FrozenTransactionId);
>   		((HeapTupleHeader) item)->t_infomask |= HEAP_XMIN_COMMITTED;
>   
> ! 		HeapTupleHeaderSetXmin(tuple->t_data, FrozenTransactionId);
>   		tuple->t_data->t_infomask |= HEAP_XMIN_COMMITTED;
>   	}
>   
> diff -c -r ../orig/src/backend/commands/vacuum.c src/backend/commands/vacuum.c
> *** ../orig/src/backend/commands/vacuum.c	Tue Apr 16 01:39:42 2002
> --- src/backend/commands/vacuum.c	Sat May 11 18:05:22 2002
> ***************
> *** 1062,1072 ****
>   					 * Tuple is good.  Consider whether to replace its
>   					 * xmin value with FrozenTransactionId.
>   					 */
> ! 					if (TransactionIdIsNormal(tuple.t_data->t_xmin) &&
> ! 						TransactionIdPrecedes(tuple.t_data->t_xmin,
>   											  FreezeLimit))
>   					{
> ! 						tuple.t_data->t_xmin = FrozenTransactionId;
>   						/* infomask should be okay already */
>   						Assert(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED);
>   						pgchanged = true;
> --- 1062,1072 ----
>   					 * Tuple is good.  Consider whether to replace its
>   					 * xmin value with FrozenTransactionId.
>   					 */
> ! 					if (TransactionIdIsNormal(HeapTupleHeaderGetXmin(tuple.t_data)) &&
> ! 						TransactionIdPrecedes(HeapTupleHeaderGetXmin(tuple.t_data),
>   											  FreezeLimit))
>   					{
> ! 						HeapTupleHeaderSetXmin(tuple.t_data, FrozenTransactionId);
>   						/* infomask should be okay already */
>   						Assert(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED);
>   						pgchanged = true;
> ***************
> *** 1109,1115 ****
>   					 * lock on the relation; shouldn't we raise an error?
>   					 */
>   					elog(WARNING, "Rel %s: TID %u/%u: InsertTransactionInProgress %u - can't shrink relation",
> ! 						 relname, blkno, offnum, tuple.t_data->t_xmin);
>   					do_shrinking = false;
>   					break;
>   				case HEAPTUPLE_DELETE_IN_PROGRESS:
> --- 1109,1115 ----
>   					 * lock on the relation; shouldn't we raise an error?
>   					 */
>   					elog(WARNING, "Rel %s: TID %u/%u: InsertTransactionInProgress %u - can't shrink relation",
> ! 						 relname, blkno, offnum, HeapTupleHeaderGetXmin(tuple.t_data));
>   					do_shrinking = false;
>   					break;
>   				case HEAPTUPLE_DELETE_IN_PROGRESS:
> ***************
> *** 1119,1125 ****
>   					 * lock on the relation; shouldn't we raise an error?
>   					 */
>   					elog(WARNING, "Rel %s: TID %u/%u: DeleteTransactionInProgress %u - can't shrink relation",
> ! 						 relname, blkno, offnum, tuple.t_data->t_xmax);
>   					do_shrinking = false;
>   					break;
>   				default:
> --- 1119,1125 ----
>   					 * lock on the relation; shouldn't we raise an error?
>   					 */
>   					elog(WARNING, "Rel %s: TID %u/%u: DeleteTransactionInProgress %u - can't shrink relation",
> ! 						 relname, blkno, offnum, HeapTupleHeaderGetXmax(tuple.t_data));
>   					do_shrinking = false;
>   					break;
>   				default:
> ***************
> *** 1495,1502 ****
>   
>   			if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
>   			{
> ! 				if ((TransactionId) tuple.t_data->t_cmin != myXID)
> ! 					elog(ERROR, "Invalid XID in t_cmin");
>   				if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
>   					elog(ERROR, "HEAP_MOVED_IN was not expected");
>   
> --- 1495,1502 ----
>   
>   			if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
>   			{
> ! 				if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
> ! 					elog(ERROR, "Invalid XVAC in tuple header");
>   				if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
>   					elog(ERROR, "HEAP_MOVED_IN was not expected");
>   
> ***************
> *** 1540,1546 ****
>   			 * tuples to another places.
>   			 */
>   			if ((tuple.t_data->t_infomask & HEAP_UPDATED &&
> ! 			 !TransactionIdPrecedes(tuple.t_data->t_xmin, OldestXmin)) ||
>   				(!(tuple.t_data->t_infomask & HEAP_XMAX_INVALID) &&
>   				 !(ItemPointerEquals(&(tuple.t_self),
>   									 &(tuple.t_data->t_ctid)))))
> --- 1540,1547 ----
>   			 * tuples to another places.
>   			 */
>   			if ((tuple.t_data->t_infomask & HEAP_UPDATED &&
> ! 			 !TransactionIdPrecedes(HeapTupleHeaderGetXmin(tuple.t_data),
> ! 			                        OldestXmin)) ||
>   				(!(tuple.t_data->t_infomask & HEAP_XMAX_INVALID) &&
>   				 !(ItemPointerEquals(&(tuple.t_self),
>   									 &(tuple.t_data->t_ctid)))))
> ***************
> *** 1657,1663 ****
>   
>   					/* All done ? */
>   					if (!(tp.t_data->t_infomask & HEAP_UPDATED) ||
> ! 					TransactionIdPrecedes(tp.t_data->t_xmin, OldestXmin))
>   						break;
>   
>   					/* Well, try to find tuple with old row version */
> --- 1658,1665 ----
>   
>   					/* All done ? */
>   					if (!(tp.t_data->t_infomask & HEAP_UPDATED) ||
> ! 					    TransactionIdPrecedes(HeapTupleHeaderGetXmin(tp.t_data),
> ! 					                          OldestXmin))
>   						break;
>   
>   					/* Well, try to find tuple with old row version */
> ***************
> *** 1705,1712 ****
>   						 * latter, and we are too close to 6.5 release. -
>   						 * vadim 06/11/99
>   						 */
> ! 						if (!(TransactionIdEquals(Ptp.t_data->t_xmax,
> ! 												  tp.t_data->t_xmin)))
>   						{
>   							if (freeCbuf)
>   								ReleaseBuffer(Cbuf);
> --- 1707,1714 ----
>   						 * latter, and we are too close to 6.5 release. -
>   						 * vadim 06/11/99
>   						 */
> ! 						if (!(TransactionIdEquals(HeapTupleHeaderGetXmax(Ptp.t_data),
> ! 												  HeapTupleHeaderGetXmin(tp.t_data))))
>   						{
>   							if (freeCbuf)
>   								ReleaseBuffer(Cbuf);
> ***************
> *** 1731,1744 ****
>   						 * removed.
>   						 */
>   						if (Ptp.t_data->t_infomask & HEAP_UPDATED &&
> ! 							TransactionIdEquals(Ptp.t_data->t_xmin,
> ! 												Ptp.t_data->t_xmax))
>   						{
> - 							TransactionIdStore(myXID,
> - 								(TransactionId *) &(Ptp.t_data->t_cmin));
>   							Ptp.t_data->t_infomask &=
>   								~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
>   							Ptp.t_data->t_infomask |= HEAP_MOVED_OFF;
>   							WriteBuffer(Pbuf);
>   							continue;
>   						}
> --- 1733,1745 ----
>   						 * removed.
>   						 */
>   						if (Ptp.t_data->t_infomask & HEAP_UPDATED &&
> ! 							TransactionIdEquals(HeapTupleHeaderGetXmin(Ptp.t_data),
> ! 												HeapTupleHeaderGetXmax(Ptp.t_data)))
>   						{
>   							Ptp.t_data->t_infomask &=
>   								~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
>   							Ptp.t_data->t_infomask |= HEAP_MOVED_OFF;
> + 							HeapTupleHeaderSetXvac(Ptp.t_data, myXID);
>   							WriteBuffer(Pbuf);
>   							continue;
>   						}
> ***************
> *** 1802,1811 ****
>   					/* NO ELOG(ERROR) TILL CHANGES ARE LOGGED */
>   					START_CRIT_SECTION();
>   
> - 					TransactionIdStore(myXID, (TransactionId *) &(tuple.t_data->t_cmin));
>   					tuple.t_data->t_infomask &=
>   						~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
>   					tuple.t_data->t_infomask |= HEAP_MOVED_OFF;
>   
>   					/*
>   					 * If this page was not used before - clean it.
> --- 1803,1812 ----
>   					/* NO ELOG(ERROR) TILL CHANGES ARE LOGGED */
>   					START_CRIT_SECTION();
>   
>   					tuple.t_data->t_infomask &=
>   						~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
>   					tuple.t_data->t_infomask |= HEAP_MOVED_OFF;
> + 					HeapTupleHeaderSetXvac(tuple.t_data, myXID);
>   
>   					/*
>   					 * If this page was not used before - clean it.
> ***************
> *** 1842,1851 ****
>   					 * Update the state of the copied tuple, and store it
>   					 * on the destination page.
>   					 */
> - 					TransactionIdStore(myXID, (TransactionId *) &(newtup.t_data->t_cmin));
>   					newtup.t_data->t_infomask &=
>   						~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
>   					newtup.t_data->t_infomask |= HEAP_MOVED_IN;
>   					newoff = PageAddItem(ToPage, (Item) newtup.t_data, tuple_len,
>   										 InvalidOffsetNumber, LP_USED);
>   					if (newoff == InvalidOffsetNumber)
> --- 1843,1852 ----
>   					 * Update the state of the copied tuple, and store it
>   					 * on the destination page.
>   					 */
>   					newtup.t_data->t_infomask &=
>   						~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
>   					newtup.t_data->t_infomask |= HEAP_MOVED_IN;
> + 					HeapTupleHeaderSetXvac(newtup.t_data, myXID);
>   					newoff = PageAddItem(ToPage, (Item) newtup.t_data, tuple_len,
>   										 InvalidOffsetNumber, LP_USED);
>   					if (newoff == InvalidOffsetNumber)
> ***************
> *** 1971,1980 ****
>   			 * Mark new tuple as moved_in by vacuum and store vacuum XID
>   			 * in t_cmin !!!
>   			 */
> - 			TransactionIdStore(myXID, (TransactionId *) &(newtup.t_data->t_cmin));
>   			newtup.t_data->t_infomask &=
>   				~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
>   			newtup.t_data->t_infomask |= HEAP_MOVED_IN;
>   
>   			/* add tuple to the page */
>   			newoff = PageAddItem(ToPage, (Item) newtup.t_data, tuple_len,
> --- 1972,1981 ----
>   			 * Mark new tuple as moved_in by vacuum and store vacuum XID
>   			 * in t_cmin !!!
>   			 */
>   			newtup.t_data->t_infomask &=
>   				~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
>   			newtup.t_data->t_infomask |= HEAP_MOVED_IN;
> + 			HeapTupleHeaderSetXvac(newtup.t_data, myXID);
>   
>   			/* add tuple to the page */
>   			newoff = PageAddItem(ToPage, (Item) newtup.t_data, tuple_len,
> ***************
> *** 1997,2006 ****
>   			 * Mark old tuple as moved_off by vacuum and store vacuum XID
>   			 * in t_cmin !!!
>   			 */
> - 			TransactionIdStore(myXID, (TransactionId *) &(tuple.t_data->t_cmin));
>   			tuple.t_data->t_infomask &=
>   				~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
>   			tuple.t_data->t_infomask |= HEAP_MOVED_OFF;
>   
>   			{
>   				XLogRecPtr	recptr =
> --- 1998,2007 ----
>   			 * Mark old tuple as moved_off by vacuum and store vacuum XID
>   			 * in t_cmin !!!
>   			 */
>   			tuple.t_data->t_infomask &=
>   				~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
>   			tuple.t_data->t_infomask |= HEAP_MOVED_OFF;
> + 			HeapTupleHeaderSetXvac(tuple.t_data, myXID);
>   
>   			{
>   				XLogRecPtr	recptr =
> ***************
> *** 2048,2055 ****
>   				tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
>   				if (tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED)
>   					continue;
> ! 				if ((TransactionId) tuple.t_data->t_cmin != myXID)
> ! 					elog(ERROR, "Invalid XID in t_cmin (4)");
>   				if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
>   					elog(ERROR, "HEAP_MOVED_IN was not expected (2)");
>   				if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
> --- 2049,2056 ----
>   				tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
>   				if (tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED)
>   					continue;
> ! 				if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
> ! 					elog(ERROR, "Invalid XVAC in tuple header (4)");
>   				if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
>   					elog(ERROR, "HEAP_MOVED_IN was not expected (2)");
>   				if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
> ***************
> *** 2186,2193 ****
>   			tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
>   			if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
>   			{
> ! 				if ((TransactionId) tuple.t_data->t_cmin != myXID)
> ! 					elog(ERROR, "Invalid XID in t_cmin (2)");
>   				if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
>   				{
>   					tuple.t_data->t_infomask |= HEAP_XMIN_COMMITTED;
> --- 2187,2194 ----
>   			tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
>   			if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
>   			{
> ! 				if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
> ! 					elog(ERROR, "Invalid XVAC in tuple header (2)");
>   				if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
>   				{
>   					tuple.t_data->t_infomask |= HEAP_XMIN_COMMITTED;
> ***************
> *** 2265,2272 ****
>   
>   				if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
>   				{
> ! 					if ((TransactionId) tuple.t_data->t_cmin != myXID)
> ! 						elog(ERROR, "Invalid XID in t_cmin (3)");
>   					if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
>   					{
>   						itemid->lp_flags &= ~LP_USED;
> --- 2266,2273 ----
>   
>   				if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
>   				{
> ! 					if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
> ! 						elog(ERROR, "Invalid XVAC in tuple header (3)");
>   					if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
>   					{
>   						itemid->lp_flags &= ~LP_USED;
> diff -c -r ../orig/src/backend/commands/vacuumlazy.c src/backend/commands/vacuumlazy.c
> *** ../orig/src/backend/commands/vacuumlazy.c	Tue Apr  2 03:03:05 2002
> --- src/backend/commands/vacuumlazy.c	Sat May 11 15:50:17 2002
> ***************
> *** 332,342 ****
>   					 * assumption by momentarily acquiring exclusive lock,
>   					 * but for the moment I see no need to.
>   					 */
> ! 					if (TransactionIdIsNormal(tuple.t_data->t_xmin) &&
> ! 						TransactionIdPrecedes(tuple.t_data->t_xmin,
>   											  FreezeLimit))
>   					{
> ! 						tuple.t_data->t_xmin = FrozenTransactionId;
>   						/* infomask should be okay already */
>   						Assert(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED);
>   						pgchanged = true;
> --- 332,342 ----
>   					 * assumption by momentarily acquiring exclusive lock,
>   					 * but for the moment I see no need to.
>   					 */
> ! 					if (TransactionIdIsNormal(HeapTupleHeaderGetXmin(tuple.t_data)) &&
> ! 						TransactionIdPrecedes(HeapTupleHeaderGetXmin(tuple.t_data),
>   											  FreezeLimit))
>   					{
> ! 						HeapTupleHeaderSetXmin(tuple.t_data, FrozenTransactionId);
>   						/* infomask should be okay already */
>   						Assert(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED);
>   						pgchanged = true;
> diff -c -r ../orig/src/backend/utils/time/tqual.c src/backend/utils/time/tqual.c
> *** ../orig/src/backend/utils/time/tqual.c	Mon May  6 18:27:02 2002
> --- src/backend/utils/time/tqual.c	Sun May 12 00:51:04 2002
> ***************
> *** 70,80 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   				return false;
> ! 			if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 70,80 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 84,94 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   					return false;
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 84,94 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 97,117 ****
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
>   		{
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
>   				return true;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return true;
>   
>   			return false;
>   		}
> ! 		else if (!TransactionIdDidCommit(tuple->t_xmin))
>   		{
> ! 			if (TransactionIdDidAbort(tuple->t_xmin))
>   				tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
>   			return false;
>   		}
> --- 97,117 ----
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
>   		{
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
>   				return true;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return true;
>   
>   			return false;
>   		}
> ! 		else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   		{
> ! 			if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
>   				tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
>   			return false;
>   		}
> ***************
> *** 131,146 ****
>   		return false;			/* updated by other */
>   	}
>   
> ! 	if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
>   	{
>   		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			return true;
>   		return false;
>   	}
>   
> ! 	if (!TransactionIdDidCommit(tuple->t_xmax))
>   	{
> ! 		if (TransactionIdDidAbort(tuple->t_xmax))
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;		/* aborted */
>   		return true;
>   	}
> --- 131,146 ----
>   		return false;			/* updated by other */
>   	}
>   
> ! 	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
>   	{
>   		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			return true;
>   		return false;
>   	}
>   
> ! 	if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   	{
> ! 		if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;		/* aborted */
>   		return true;
>   	}
> ***************
> *** 209,219 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   				return false;
> ! 			if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 209,219 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 223,233 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   					return false;
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 223,233 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 236,262 ****
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
>   		{
> ! 			if (CommandIdGEScanCommandId(tuple->t_cmin))
>   				return false;	/* inserted after scan started */
>   
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
>   				return true;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return true;
>   
> ! 			if (CommandIdGEScanCommandId(tuple->t_cmax))
>   				return true;	/* deleted after scan started */
>   			else
>   				return false;	/* deleted before scan started */
>   		}
> ! 		else if (!TransactionIdDidCommit(tuple->t_xmin))
>   		{
> ! 			if (TransactionIdDidAbort(tuple->t_xmin))
>   				tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
>   			return false;
>   		}
> --- 236,262 ----
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
>   		{
> ! 			if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmin(tuple)))
>   				return false;	/* inserted after scan started */
>   
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
>   				return true;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return true;
>   
> ! 			if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmax(tuple)))
>   				return true;	/* deleted after scan started */
>   			else
>   				return false;	/* deleted before scan started */
>   		}
> ! 		else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   		{
> ! 			if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
>   				tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
>   			return false;
>   		}
> ***************
> *** 276,294 ****
>   		return false;
>   	}
>   
> ! 	if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
>   	{
>   		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			return true;
> ! 		if (CommandIdGEScanCommandId(tuple->t_cmax))
>   			return true;		/* deleted after scan started */
>   		else
>   			return false;		/* deleted before scan started */
>   	}
>   
> ! 	if (!TransactionIdDidCommit(tuple->t_xmax))
>   	{
> ! 		if (TransactionIdDidAbort(tuple->t_xmax))
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;		/* aborted */
>   		return true;
>   	}
> --- 276,294 ----
>   		return false;
>   	}
>   
> ! 	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
>   	{
>   		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			return true;
> ! 		if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmax(tuple)))
>   			return true;		/* deleted after scan started */
>   		else
>   			return false;		/* deleted before scan started */
>   	}
>   
> ! 	if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   	{
> ! 		if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;		/* aborted */
>   		return true;
>   	}
> ***************
> *** 326,336 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   				return false;
> ! 			if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 326,336 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 340,350 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   					return false;
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 340,350 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 380,390 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   				return HeapTupleInvisible;
> ! 			if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return HeapTupleInvisible;
> --- 380,390 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HeapTupleInvisible;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return HeapTupleInvisible;
> ***************
> *** 394,404 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   					return HeapTupleInvisible;
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 394,404 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return HeapTupleInvisible;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 407,436 ****
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
>   		{
> ! 			if (CommandIdGEScanCommandId(tuple->t_cmin))
>   				return HeapTupleInvisible;		/* inserted after scan
>   												 * started */
>   
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)		/* xid invalid */
>   				return HeapTupleMayBeUpdated;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return HeapTupleMayBeUpdated;
>   
> ! 			if (CommandIdGEScanCommandId(tuple->t_cmax))
>   				return HeapTupleSelfUpdated;	/* updated after scan
>   												 * started */
>   			else
>   				return HeapTupleInvisible;		/* updated before scan
>   												 * started */
>   		}
> ! 		else if (!TransactionIdDidCommit(tuple->t_xmin))
>   		{
> ! 			if (TransactionIdDidAbort(tuple->t_xmin))
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;	/* aborted */
>   			return HeapTupleInvisible;
>   		}
> --- 407,436 ----
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
>   		{
> ! 			if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmin(tuple)))
>   				return HeapTupleInvisible;		/* inserted after scan
>   												 * started */
>   
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)		/* xid invalid */
>   				return HeapTupleMayBeUpdated;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return HeapTupleMayBeUpdated;
>   
> ! 			if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmax(tuple)))
>   				return HeapTupleSelfUpdated;	/* updated after scan
>   												 * started */
>   			else
>   				return HeapTupleInvisible;		/* updated before scan
>   												 * started */
>   		}
> ! 		else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   		{
> ! 			if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;	/* aborted */
>   			return HeapTupleInvisible;
>   		}
> ***************
> *** 450,469 ****
>   		return HeapTupleUpdated;	/* updated by other */
>   	}
>   
> ! 	if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
>   	{
>   		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			return HeapTupleMayBeUpdated;
> ! 		if (CommandIdGEScanCommandId(tuple->t_cmax))
>   			return HeapTupleSelfUpdated;		/* updated after scan
>   												 * started */
>   		else
>   			return HeapTupleInvisible;	/* updated before scan started */
>   	}
>   
> ! 	if (!TransactionIdDidCommit(tuple->t_xmax))
>   	{
> ! 		if (TransactionIdDidAbort(tuple->t_xmax))
>   		{
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;		/* aborted */
>   			return HeapTupleMayBeUpdated;
> --- 450,469 ----
>   		return HeapTupleUpdated;	/* updated by other */
>   	}
>   
> ! 	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
>   	{
>   		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			return HeapTupleMayBeUpdated;
> ! 		if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmax(tuple)))
>   			return HeapTupleSelfUpdated;		/* updated after scan
>   												 * started */
>   		else
>   			return HeapTupleInvisible;	/* updated before scan started */
>   	}
>   
> ! 	if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   	{
> ! 		if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
>   		{
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;		/* aborted */
>   			return HeapTupleMayBeUpdated;
> ***************
> *** 514,524 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   				return false;
> ! 			if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 514,524 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 528,538 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   					return false;
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 528,538 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 541,566 ****
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
>   		{
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
>   				return true;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return true;
>   
>   			return false;
>   		}
> ! 		else if (!TransactionIdDidCommit(tuple->t_xmin))
>   		{
> ! 			if (TransactionIdDidAbort(tuple->t_xmin))
>   			{
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   				return false;
>   			}
> ! 			SnapshotDirty->xmin = tuple->t_xmin;
>   			/* XXX shouldn't we fall through to look at xmax? */
>   			return true;		/* in insertion by other */
>   		}
> --- 541,566 ----
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
>   		{
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
>   				return true;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return true;
>   
>   			return false;
>   		}
> ! 		else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   		{
> ! 			if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
>   			{
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   				return false;
>   			}
> ! 			SnapshotDirty->xmin = HeapTupleHeaderGetXmin(tuple);
>   			/* XXX shouldn't we fall through to look at xmax? */
>   			return true;		/* in insertion by other */
>   		}
> ***************
> *** 581,602 ****
>   		return false;			/* updated by other */
>   	}
>   
> ! 	if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
>   	{
>   		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			return true;
>   		return false;
>   	}
>   
> ! 	if (!TransactionIdDidCommit(tuple->t_xmax))
>   	{
> ! 		if (TransactionIdDidAbort(tuple->t_xmax))
>   		{
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;		/* aborted */
>   			return true;
>   		}
>   		/* running xact */
> ! 		SnapshotDirty->xmax = tuple->t_xmax;
>   		return true;			/* in updation by other */
>   	}
>   
> --- 581,602 ----
>   		return false;			/* updated by other */
>   	}
>   
> ! 	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
>   	{
>   		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   			return true;
>   		return false;
>   	}
>   
> ! 	if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   	{
> ! 		if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
>   		{
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;		/* aborted */
>   			return true;
>   		}
>   		/* running xact */
> ! 		SnapshotDirty->xmax = HeapTupleHeaderGetXmax(tuple);
>   		return true;			/* in updation by other */
>   	}
>   
> ***************
> *** 648,658 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   				return false;
> ! 			if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 648,658 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 662,672 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   			{
> ! 				if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   					return false;
> ! 				if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 662,672 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 675,701 ****
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
>   		{
> ! 			if (CommandIdGEScanCommandId(tuple->t_cmin))
>   				return false;	/* inserted after scan started */
>   
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
>   				return true;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return true;
>   
> ! 			if (CommandIdGEScanCommandId(tuple->t_cmax))
>   				return true;	/* deleted after scan started */
>   			else
>   				return false;	/* deleted before scan started */
>   		}
> ! 		else if (!TransactionIdDidCommit(tuple->t_xmin))
>   		{
> ! 			if (TransactionIdDidAbort(tuple->t_xmin))
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   			return false;
>   		}
> --- 675,701 ----
>   				}
>   			}
>   		}
> ! 		else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
>   		{
> ! 			if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmin(tuple)))
>   				return false;	/* inserted after scan started */
>   
>   			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
>   				return true;
>   
> ! 			Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
>   
>   			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   				return true;
>   
> ! 			if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmax(tuple)))
>   				return true;	/* deleted after scan started */
>   			else
>   				return false;	/* deleted before scan started */
>   		}
> ! 		else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   		{
> ! 			if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   			return false;
>   		}
> ***************
> *** 707,721 ****
>   	 * By here, the inserting transaction has committed - have to check
>   	 * when...
>   	 */
> ! 	if (TransactionIdFollowsOrEquals(tuple->t_xmin, snapshot->xmin))
>   	{
>   		uint32		i;
>   
> ! 		if (TransactionIdFollowsOrEquals(tuple->t_xmin, snapshot->xmax))
>   			return false;
>   		for (i = 0; i < snapshot->xcnt; i++)
>   		{
> ! 			if (TransactionIdEquals(tuple->t_xmin, snapshot->xip[i]))
>   				return false;
>   		}
>   	}
> --- 707,725 ----
>   	 * By here, the inserting transaction has committed - have to check
>   	 * when...
>   	 */
> ! 	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),
> ! 	                                 snapshot->xmin))
>   	{
>   		uint32		i;
>   
> ! 		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),
> ! 										 snapshot->xmax))
>   			return false;
> + 
>   		for (i = 0; i < snapshot->xcnt; i++)
>   		{
> ! 			if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple),
> ! 			                        snapshot->xip[i]))
>   				return false;
>   		}
>   	}
> ***************
> *** 728,744 ****
>   
>   	if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
>   	{
> ! 		if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
>   		{
> ! 			if (CommandIdGEScanCommandId(tuple->t_cmax))
>   				return true;	/* deleted after scan started */
>   			else
>   				return false;	/* deleted before scan started */
>   		}
>   
> ! 		if (!TransactionIdDidCommit(tuple->t_xmax))
>   		{
> ! 			if (TransactionIdDidAbort(tuple->t_xmax))
>   				tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
>   			return true;
>   		}
> --- 732,748 ----
>   
>   	if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
>   	{
> ! 		if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
>   		{
> ! 			if (CommandIdGEScanCommandId(HeapTupleHeaderGetCmax(tuple)))
>   				return true;	/* deleted after scan started */
>   			else
>   				return false;	/* deleted before scan started */
>   		}
>   
> ! 		if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   		{
> ! 			if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
>   				tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
>   			return true;
>   		}
> ***************
> *** 750,764 ****
>   	/*
>   	 * OK, the deleting transaction committed too ... but when?
>   	 */
> ! 	if (TransactionIdFollowsOrEquals(tuple->t_xmax, snapshot->xmin))
>   	{
>   		uint32		i;
>   
> ! 		if (TransactionIdFollowsOrEquals(tuple->t_xmax, snapshot->xmax))
>   			return true;
>   		for (i = 0; i < snapshot->xcnt; i++)
>   		{
> ! 			if (TransactionIdEquals(tuple->t_xmax, snapshot->xip[i]))
>   				return true;
>   		}
>   	}
> --- 754,769 ----
>   	/*
>   	 * OK, the deleting transaction committed too ... but when?
>   	 */
> ! 	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple), snapshot->xmin))
>   	{
>   		uint32		i;
>   
> ! 		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),
> ! 		                                 snapshot->xmax))
>   			return true;
>   		for (i = 0; i < snapshot->xcnt; i++)
>   		{
> ! 			if (TransactionIdEquals(HeapTupleHeaderGetXmax(tuple), snapshot->xip[i]))
>   				return true;
>   		}
>   	}
> ***************
> *** 801,811 ****
>   			return HEAPTUPLE_DEAD;
>   		else if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   			{
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   				return HEAPTUPLE_DEAD;
> --- 806,816 ----
>   			return HEAPTUPLE_DEAD;
>   		else if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   			{
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   				return HEAPTUPLE_DEAD;
> ***************
> *** 814,824 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
>   				tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   			else
>   			{
> --- 819,829 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   			else
>   			{
> ***************
> *** 826,836 ****
>   				return HEAPTUPLE_DEAD;
>   			}
>   		}
> ! 		else if (TransactionIdIsInProgress(tuple->t_xmin))
>   			return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 		else if (TransactionIdDidCommit(tuple->t_xmin))
>   			tuple->t_infomask |= HEAP_XMIN_COMMITTED;
> ! 		else if (TransactionIdDidAbort(tuple->t_xmin))
>   		{
>   			tuple->t_infomask |= HEAP_XMIN_INVALID;
>   			return HEAPTUPLE_DEAD;
> --- 831,841 ----
>   				return HEAPTUPLE_DEAD;
>   			}
>   		}
> ! 		else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
>   			return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   			tuple->t_infomask |= HEAP_XMIN_COMMITTED;
> ! 		else if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
>   		{
>   			tuple->t_infomask |= HEAP_XMIN_INVALID;
>   			return HEAPTUPLE_DEAD;
> ***************
> *** 865,873 ****
>   		 */
>   		if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
>   		{
> ! 			if (TransactionIdIsInProgress(tuple->t_xmax))
>   				return HEAPTUPLE_LIVE;
> ! 			if (TransactionIdDidCommit(tuple->t_xmax))
>   				tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   			else				/* it's either aborted or crashed */
>   				tuple->t_infomask |= HEAP_XMAX_INVALID;
> --- 870,878 ----
>   		 */
>   		if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
>   		{
> ! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
>   				return HEAPTUPLE_LIVE;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   				tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   			else				/* it's either aborted or crashed */
>   				tuple->t_infomask |= HEAP_XMAX_INVALID;
> ***************
> *** 877,887 ****
>   
>   	if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
>   	{
> ! 		if (TransactionIdIsInProgress(tuple->t_xmax))
>   			return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 		else if (TransactionIdDidCommit(tuple->t_xmax))
>   			tuple->t_infomask |= HEAP_XMAX_COMMITTED;
> ! 		else if (TransactionIdDidAbort(tuple->t_xmax))
>   		{
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;
>   			return HEAPTUPLE_LIVE;
> --- 882,892 ----
>   
>   	if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
>   	{
> ! 		if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
>   			return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   			tuple->t_infomask |= HEAP_XMAX_COMMITTED;
> ! 		else if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
>   		{
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;
>   			return HEAPTUPLE_LIVE;
> ***************
> *** 903,909 ****
>   	 * Deleter committed, but check special cases.
>   	 */
>   
> ! 	if (TransactionIdEquals(tuple->t_xmin, tuple->t_xmax))
>   	{
>   		/*
>   		 * inserter also deleted it, so it was never visible to anyone
> --- 908,915 ----
>   	 * Deleter committed, but check special cases.
>   	 */
>   
> ! 	if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple),
> ! 	                        HeapTupleHeaderGetXmax(tuple)))
>   	{
>   		/*
>   		 * inserter also deleted it, so it was never visible to anyone
> ***************
> *** 912,918 ****
>   		return HEAPTUPLE_DEAD;
>   	}
>   
> ! 	if (!TransactionIdPrecedes(tuple->t_xmax, OldestXmin))
>   	{
>   		/* deleting xact is too recent, tuple could still be visible */
>   		return HEAPTUPLE_RECENTLY_DEAD;
> --- 918,924 ----
>   		return HEAPTUPLE_DEAD;
>   	}
>   
> ! 	if (!TransactionIdPrecedes(HeapTupleHeaderGetXmax(tuple), OldestXmin))
>   	{
>   		/* deleting xact is too recent, tuple could still be visible */
>   		return HEAPTUPLE_RECENTLY_DEAD;
> diff -c -r ../orig/src/include/access/htup.h src/include/access/htup.h
> *** ../orig/src/include/access/htup.h	Sat May 11 14:22:41 2002
> --- src/include/access/htup.h	Sat May 11 18:25:11 2002
> ***************
> *** 16,21 ****
> --- 16,22 ----
>   
>   #include "storage/bufpage.h"
>   #include "storage/relfilenode.h"
> + #include "access/transam.h"
>   
>   #define MinHeapTupleBitmapLen	1	/* in bytes, must be 2**n */
>   
> ***************
> *** 66,71 ****
> --- 67,152 ----
>   typedef HeapTupleHeaderData *HeapTupleHeader;
>   
>   /*
> +  * information stored in t_infomask:
> +  */
> + #define HEAP_HASNULL			0x0001	/* has null attribute(s) */
> + #define HEAP_HASVARLENA			0x0002	/* has variable length
> + 										 * attribute(s) */
> + #define HEAP_HASEXTERNAL		0x0004	/* has external stored
> + 										 * attribute(s) */
> + #define HEAP_HASCOMPRESSED		0x0008	/* has compressed stored
> + 										 * attribute(s) */
> + #define HEAP_HASEXTENDED		0x000C	/* the two above combined */
> + 
> + #define HEAP_XMAX_UNLOGGED		0x0080	/* to lock tuple for update */
> + 										/* without logging */
> + #define HEAP_XMIN_COMMITTED		0x0100	/* t_xmin committed */
> + #define HEAP_XMIN_INVALID		0x0200	/* t_xmin invalid/aborted */
> + #define HEAP_XMAX_COMMITTED		0x0400	/* t_xmax committed */
> + #define HEAP_XMAX_INVALID		0x0800	/* t_xmax invalid/aborted */
> + #define HEAP_MARKED_FOR_UPDATE	0x1000	/* marked for UPDATE */
> + #define HEAP_UPDATED			0x2000	/* this is UPDATEd version of row */
> + #define HEAP_MOVED_OFF			0x4000	/* removed or moved to another
> + 										 * place by vacuum */
> + #define HEAP_MOVED_IN			0x8000	/* moved from another place by
> + 										 * vacuum */
> + 
> + #define HEAP_XACT_MASK			0xFFF0	/* */
> + 
> + 
> + /* HeapTupleHeader accessor macros */
> + 
> + #define HeapTupleHeaderGetXmin(tup) \
> + 	((tup)->t_xmin)
> + 
> + #define HeapTupleHeaderGetXmax(tup) \
> + 	((tup)->t_xmax)
> + 
> + /* no AssertMacro, because this is read as a system-defined attribute also */
> + #define HeapTupleHeaderGetCmin(tup) \
> + ( \
> + 	(tup)->t_cmin \
> + )
> + 
> + #define HeapTupleHeaderGetCmax(tup) \
> + 	((tup)->t_cmax)
> + 
> + #define HeapTupleHeaderGetXvac(tup) \
> + ( \
> + 	AssertMacro((tup)->t_infomask & (HEAP_MOVED_IN | HEAP_MOVED_OFF)), \
> + 	(TransactionId) (tup)->t_cmin \
> + )
> + 
> + 
> + #define HeapTupleHeaderSetXmin(tup, xid) \
> + 	(TransactionIdStore((xid), &(tup)->t_xmin))
> + 
> + #define HeapTupleHeaderSetXminInvalid(tup) \
> + 	(StoreInvalidTransactionId(&(tup)->t_xmin))
> + 
> + #define HeapTupleHeaderSetXmax(tup, xid) \
> + 	(TransactionIdStore((xid), &(tup)->t_xmax))
> + 
> + #define HeapTupleHeaderSetXmaxInvalid(tup) \
> + 	(StoreInvalidTransactionId(&(tup)->t_xmax))
> + 
> + #define HeapTupleHeaderSetCmin(tup, cid) \
> + ( \
> + 	AssertMacro(!((tup)->t_infomask & (HEAP_MOVED_IN | HEAP_MOVED_OFF))), \
> + 	(tup)->t_cmin = (cid) \
> + )
> + 
> + #define HeapTupleHeaderSetCmax(tup, cid) \
> + 	((tup)->t_cmax = (cid))
> + 
> + #define HeapTupleHeaderSetXvac(tup, xid) \
> + ( \
> + 	AssertMacro((tup)->t_infomask & (HEAP_MOVED_IN | HEAP_MOVED_OFF)), \
> + 	TransactionIdStore((xid), (TransactionId *) &((tup)->t_cmin)) \
> + )
> + 
> + 
> + /*
>    * XLOG allows to store some information in high 4 bits of log
>    * record xl_info field
>    */
> ***************
> *** 234,265 ****
>    */
>   #define HeapTupleIsValid(tuple) PointerIsValid(tuple)
>   
> - /*
> -  * information stored in t_infomask:
> -  */
> - #define HEAP_HASNULL			0x0001	/* has null attribute(s) */
> - #define HEAP_HASVARLENA			0x0002	/* has variable length
> - 										 * attribute(s) */
> - #define HEAP_HASEXTERNAL		0x0004	/* has external stored */
> -  /* attribute(s) */
> - #define HEAP_HASCOMPRESSED		0x0008	/* has compressed stored */
> -  /* attribute(s) */
> - #define HEAP_HASEXTENDED		0x000C	/* the two above combined */
> - 
> - #define HEAP_XMAX_UNLOGGED		0x0080	/* to lock tuple for update */
> -  /* without logging */
> - #define HEAP_XMIN_COMMITTED		0x0100	/* t_xmin committed */
> - #define HEAP_XMIN_INVALID		0x0200	/* t_xmin invalid/aborted */
> - #define HEAP_XMAX_COMMITTED		0x0400	/* t_xmax committed */
> - #define HEAP_XMAX_INVALID		0x0800	/* t_xmax invalid/aborted */
> - #define HEAP_MARKED_FOR_UPDATE	0x1000	/* marked for UPDATE */
> - #define HEAP_UPDATED			0x2000	/* this is UPDATEd version of row */
> - #define HEAP_MOVED_OFF			0x4000	/* removed or moved to another
> - 										 * place by vacuum */
> - #define HEAP_MOVED_IN			0x8000	/* moved from another place by
> - 										 * vacuum */
> - 
> - #define HEAP_XACT_MASK			0xFFF0	/* */
>   
>   #define HeapTupleNoNulls(tuple) \
>   		(!(((HeapTuple) (tuple))->t_data->t_infomask & HEAP_HASNULL))
> --- 315,320 ----
> diff -c -r ../orig/src/pl/plperl/plperl.c src/pl/plperl/plperl.c
> *** ../orig/src/pl/plperl/plperl.c	Sun May  5 02:03:29 2002
> --- src/pl/plperl/plperl.c	Sun May 12 00:53:20 2002
> ***************
> *** 552,559 ****
>   		 * This is needed because CREATE OR REPLACE FUNCTION can modify the
>   		 * function's pg_proc entry without changing its OID.
>   		 ************************************************************/
> ! 		uptodate = (prodesc->fn_xmin == procTup->t_data->t_xmin &&
> ! 					prodesc->fn_cmin == procTup->t_data->t_cmin);
>   
>   		if (!uptodate)
>   		{
> --- 552,559 ----
>   		 * This is needed because CREATE OR REPLACE FUNCTION can modify the
>   		 * function's pg_proc entry without changing its OID.
>   		 ************************************************************/
> ! 		uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
> ! 					prodesc->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
>   
>   		if (!uptodate)
>   		{
> ***************
> *** 586,593 ****
>   			elog(ERROR, "plperl: out of memory");
>   		MemSet(prodesc, 0, sizeof(plperl_proc_desc));
>   		prodesc->proname = strdup(internal_proname);
> ! 		prodesc->fn_xmin = procTup->t_data->t_xmin;
> ! 		prodesc->fn_cmin = procTup->t_data->t_cmin;
>   
>   		/************************************************************
>   		 * Lookup the pg_language tuple by Oid
> --- 586,593 ----
>   			elog(ERROR, "plperl: out of memory");
>   		MemSet(prodesc, 0, sizeof(plperl_proc_desc));
>   		prodesc->proname = strdup(internal_proname);
> ! 		prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
> ! 		prodesc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
>   
>   		/************************************************************
>   		 * Lookup the pg_language tuple by Oid
> diff -c -r ../orig/src/pl/plpgsql/src/pl_comp.c src/pl/plpgsql/src/pl_comp.c
> *** ../orig/src/pl/plpgsql/src/pl_comp.c	Fri May  3 02:32:18 2002
> --- src/pl/plpgsql/src/pl_comp.c	Sun May 12 00:54:11 2002
> ***************
> *** 188,195 ****
>   
>   	function->fn_name = strdup(NameStr(procStruct->proname));
>   	function->fn_oid = fn_oid;
> ! 	function->fn_xmin = procTup->t_data->t_xmin;
> ! 	function->fn_cmin = procTup->t_data->t_cmin;
>   	function->fn_functype = functype;
>   
>   	switch (functype)
> --- 188,195 ----
>   
>   	function->fn_name = strdup(NameStr(procStruct->proname));
>   	function->fn_oid = fn_oid;
> ! 	function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
> ! 	function->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
>   	function->fn_functype = functype;
>   
>   	switch (functype)
> diff -c -r ../orig/src/pl/plpgsql/src/pl_handler.c src/pl/plpgsql/src/pl_handler.c
> *** ../orig/src/pl/plpgsql/src/pl_handler.c	Thu Oct 25 07:50:20 2001
> --- src/pl/plpgsql/src/pl_handler.c	Sat May 11 16:23:10 2002
> ***************
> *** 167,174 ****
>   		elog(ERROR, "plpgsql: cache lookup for proc %u failed",
>   			 func->fn_oid);
>   
> ! 	result = (func->fn_xmin == procTup->t_data->t_xmin &&
> ! 			  func->fn_cmin == procTup->t_data->t_cmin);
>   
>   	ReleaseSysCache(procTup);
>   
> --- 167,174 ----
>   		elog(ERROR, "plpgsql: cache lookup for proc %u failed",
>   			 func->fn_oid);
>   
> ! 	result = (func->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
> ! 			  func->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
>   
>   	ReleaseSysCache(procTup);
>   
> diff -c -r ../orig/src/pl/plpython/plpython.c src/pl/plpython/plpython.c
> *** ../orig/src/pl/plpython/plpython.c	Fri Mar 29 20:06:27 2002
> --- src/pl/plpython/plpython.c	Sat May 11 16:25:25 2002
> ***************
> *** 1030,1037 ****
>   		if (proc->me != plproc)
>   			elog(FATAL, "plpython: Aiieee, proc->me != plproc");
>   		/* did we find an up-to-date cache entry? */
> ! 		if (proc->fn_xmin != procTup->t_data->t_xmin ||
> ! 			proc->fn_cmin != procTup->t_data->t_cmin)
>   		{
>   			Py_DECREF(plproc);
>   			proc = NULL;
> --- 1030,1037 ----
>   		if (proc->me != plproc)
>   			elog(FATAL, "plpython: Aiieee, proc->me != plproc");
>   		/* did we find an up-to-date cache entry? */
> ! 		if (proc->fn_xmin != HeapTupleHeaderGetXmin(procTup->t_data) ||
> ! 			proc->fn_cmin != HeapTupleHeaderGetCmin(procTup->t_data))
>   		{
>   			Py_DECREF(plproc);
>   			proc = NULL;
> ***************
> *** 1075,1082 ****
>   	proc = PLy_malloc(sizeof(PLyProcedure));
>   	proc->proname = PLy_malloc(strlen(procName) + 1);
>   	strcpy(proc->proname, procName);
> ! 	proc->fn_xmin = procTup->t_data->t_xmin;
> ! 	proc->fn_cmin = procTup->t_data->t_cmin;
>   	PLy_typeinfo_init(&proc->result);
>   	for (i = 0; i < FUNC_MAX_ARGS; i++)
>   		PLy_typeinfo_init(&proc->args[i]);
> --- 1075,1082 ----
>   	proc = PLy_malloc(sizeof(PLyProcedure));
>   	proc->proname = PLy_malloc(strlen(procName) + 1);
>   	strcpy(proc->proname, procName);
> ! 	proc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
> ! 	proc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
>   	PLy_typeinfo_init(&proc->result);
>   	for (i = 0; i < FUNC_MAX_ARGS; i++)
>   		PLy_typeinfo_init(&proc->args[i]);
> diff -c -r ../orig/src/pl/tcl/pltcl.c src/pl/tcl/pltcl.c
> *** ../orig/src/pl/tcl/pltcl.c	Fri Mar 29 20:06:28 2002
> --- src/pl/tcl/pltcl.c	Sat May 11 16:28:51 2002
> ***************
> *** 985,992 ****
>   
>   		prodesc = (pltcl_proc_desc *) Tcl_GetHashValue(hashent);
>   
> ! 		uptodate = (prodesc->fn_xmin == procTup->t_data->t_xmin &&
> ! 					prodesc->fn_cmin == procTup->t_data->t_cmin);
>   
>   		if (!uptodate)
>   		{
> --- 985,992 ----
>   
>   		prodesc = (pltcl_proc_desc *) Tcl_GetHashValue(hashent);
>   
> ! 		uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
> ! 					prodesc->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
>   
>   		if (!uptodate)
>   		{
> ***************
> *** 1023,1030 ****
>   			elog(ERROR, "pltcl: out of memory");
>   		MemSet(prodesc, 0, sizeof(pltcl_proc_desc));
>   		prodesc->proname = strdup(internal_proname);
> ! 		prodesc->fn_xmin = procTup->t_data->t_xmin;
> ! 		prodesc->fn_cmin = procTup->t_data->t_cmin;
>   
>   		/************************************************************
>   		 * Lookup the pg_language tuple by Oid
> --- 1023,1030 ----
>   			elog(ERROR, "pltcl: out of memory");
>   		MemSet(prodesc, 0, sizeof(pltcl_proc_desc));
>   		prodesc->proname = strdup(internal_proname);
> ! 		prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
> ! 		prodesc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
>   
>   		/************************************************************
>   		 * Lookup the pg_language tuple by Oid

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
В списке pgsql-patches по дате отправления
От: Bruce Momjian
Дата:
От: Bruce Momjian
Дата:
FAQ