diff -cpr pgsql-orig/src/backend/storage/ipc/procarray.c pgsql/src/backend/storage/ipc/procarray.c
*** pgsql-orig/src/backend/storage/ipc/procarray.c	Mon Aug 28 09:36:08 2006
--- pgsql/src/backend/storage/ipc/procarray.c	Mon Aug 28 17:38:05 2006
*************** GetSnapshotData(Snapshot snapshot, bool 
*** 499,504 ****
--- 499,505 ----
  	TransactionId globalxmin;
  	int			index;
  	int			count = 0;
+ 	int			subcount = 0;
  
  	Assert(snapshot != NULL);
  
*************** GetSnapshotData(Snapshot snapshot, bool 
*** 599,604 ****
--- 600,642 ----
  		if (TransactionIdIsNormal(xid))
  			if (TransactionIdPrecedes(xid, globalxmin))
  				globalxmin = xid;
+ 
+ 		/* Query subtransaction ids */
+ 		if (subcount >= 0)
+ 		{
+ 			if (proc->subxids.overflowed)
+ 			{
+ 				subcount = -1;	/* overflowed */
+ 			}
+ 			else if (proc->subxids.nxids > 0)
+ 			{
+ 				int		sub;
+ 
+ 				/* XXX: or use some multiplied value? */
+ 				int		maxSubCount = arrayP->maxProcs;
+ 
+ 				if (snapshot->subxip == NULL)
+ 				{
+ 					snapshot->subxip = (TransactionId *)
+ 						malloc(maxSubCount * sizeof(TransactionId));
+ 					if (snapshot->subxip == NULL)
+ 						ereport(ERROR,
+ 								(errcode(ERRCODE_OUT_OF_MEMORY),
+ 								errmsg("out of memory")));
+ 				}
+ 				
+ 				for (sub = 0; sub < proc->subxids.nxids; sub++)
+ 				{
+ 					snapshot->subxip[subcount] = proc->subxids.xids[sub];
+ 					subcount++;
+ 					if (subcount >= maxSubCount)
+ 					{
+ 						subcount = -1;	/* overflowed */
+ 						break;
+ 					}
+ 				}
+ 			}
+ 		}
  	}
  
  	if (serializable)
*************** GetSnapshotData(Snapshot snapshot, bool 
*** 621,626 ****
--- 659,665 ----
  	snapshot->xmin = xmin;
  	snapshot->xmax = xmax;
  	snapshot->xcnt = count;
+ 	snapshot->subxcnt = subcount;
  
  	snapshot->curcid = GetCurrentCommandId();
  
diff -cpr pgsql-orig/src/backend/utils/time/tqual.c pgsql/src/backend/utils/time/tqual.c
*** pgsql-orig/src/backend/utils/time/tqual.c	Mon Aug 28 09:36:10 2006
--- pgsql/src/backend/utils/time/tqual.c	Mon Aug 28 17:55:58 2006
*************** TransactionId TransactionXmin = InvalidT
*** 72,77 ****
--- 72,78 ----
  TransactionId RecentXmin = InvalidTransactionId;
  TransactionId RecentGlobalXmin = InvalidTransactionId;
  
+ static bool XidInSnapshot(TransactionId xid, Snapshot snapshot);
  
  /*
   * HeapTupleSatisfiesItself
*************** HeapTupleSatisfiesSnapshot(HeapTupleHead
*** 954,979 ****
  	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),
  									 snapshot->xmin))
  	{
- 		TransactionId parentXid;
- 
  		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),
  										 snapshot->xmax))
  			return false;
  
! 		parentXid = SubTransGetTopmostTransaction(HeapTupleHeaderGetXmin(tuple));
! 
! 		if (TransactionIdFollowsOrEquals(parentXid, snapshot->xmin))
! 		{
! 			uint32		i;
! 
! 			/* no point in checking parentXid against xmax here */
! 
! 			for (i = 0; i < snapshot->xcnt; i++)
! 			{
! 				if (TransactionIdEquals(parentXid, snapshot->xip[i]))
! 					return false;
! 			}
! 		}
  	}
  
  	if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid or aborted */
--- 955,966 ----
  	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),
  									 snapshot->xmin))
  	{
  		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),
  										 snapshot->xmax))
  			return false;
  
! 		if (XidInSnapshot(HeapTupleHeaderGetXmin(tuple), snapshot))
! 			return false;
  	}
  
  	if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid or aborted */
*************** HeapTupleSatisfiesSnapshot(HeapTupleHead
*** 1023,1048 ****
  	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),
  									 snapshot->xmin))
  	{
- 		TransactionId parentXid;
- 
  		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),
  										 snapshot->xmax))
  			return true;
  
! 		parentXid = SubTransGetTopmostTransaction(HeapTupleHeaderGetXmax(tuple));
! 
! 		if (TransactionIdFollowsOrEquals(parentXid, snapshot->xmin))
! 		{
! 			uint32		i;
! 
! 			/* no point in checking parentXid against xmax here */
! 
! 			for (i = 0; i < snapshot->xcnt; i++)
! 			{
! 				if (TransactionIdEquals(parentXid, snapshot->xip[i]))
! 					return true;
! 			}
! 		}
  	}
  
  /* This is to be used only for disaster recovery and requires serious analysis. */
--- 1010,1021 ----
  	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),
  									 snapshot->xmin))
  	{
  		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),
  										 snapshot->xmax))
  			return true;
  
! 		if (XidInSnapshot(HeapTupleHeaderGetXmax(tuple), snapshot))
! 			return true;
  	}
  
  /* This is to be used only for disaster recovery and requires serious analysis. */
*************** Snapshot
*** 1299,1309 ****
  CopySnapshot(Snapshot snapshot)
  {
  	Snapshot	newsnap;
  
  	/* We allocate any XID array needed in the same palloc block. */
! 	newsnap = (Snapshot) palloc(sizeof(SnapshotData) +
! 								snapshot->xcnt * sizeof(TransactionId));
  	memcpy(newsnap, snapshot, sizeof(SnapshotData));
  	if (snapshot->xcnt > 0)
  	{
  		newsnap->xip = (TransactionId *) (newsnap + 1);
--- 1272,1290 ----
  CopySnapshot(Snapshot snapshot)
  {
  	Snapshot	newsnap;
+ 	Size		subxipoff;
+ 	Size		size;
+ 
+ 	size = subxipoff = sizeof(SnapshotData) +
+ 		snapshot->xcnt * sizeof(TransactionId);
+ 	if (snapshot->subxcnt > 0)
+ 		size += snapshot->subxcnt * sizeof(TransactionId);
  
  	/* We allocate any XID array needed in the same palloc block. */
! 	newsnap = (Snapshot) palloc(size);
  	memcpy(newsnap, snapshot, sizeof(SnapshotData));
+ 
+ 	/* setup XID array */
  	if (snapshot->xcnt > 0)
  	{
  		newsnap->xip = (TransactionId *) (newsnap + 1);
*************** CopySnapshot(Snapshot snapshot)
*** 1313,1318 ****
--- 1294,1309 ----
  	else
  		newsnap->xip = NULL;
  
+ 	/* setup sub XID array */
+ 	if (snapshot->subxcnt > 0)
+ 	{
+ 		newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
+ 		memcpy(newsnap->subxip, snapshot->subxip,
+ 			   snapshot->subxcnt * sizeof(TransactionId));
+ 	}
+ 	else
+ 		newsnap->subxip = NULL;
+ 
  	return newsnap;
  }
  
*************** FreeXactSnapshot(void)
*** 1346,1349 ****
--- 1337,1386 ----
  	SerializableSnapshot = NULL;
  	LatestSnapshot = NULL;
  	ActiveSnapshot = NULL;		/* just for cleanliness */
+ }
+ 
+ static bool
+ XidInSnapshot(TransactionId xid, Snapshot snapshot)
+ {
+ 	TransactionId parentXid;
+ 
+ 	if (snapshot->subxcnt < 0)
+ 	{
+ 		/*
+ 		 * The snapshot does not have enough information. We will get
+ 		 * information from pg_subtrans log.
+ 		 */
+ 		parentXid = SubTransGetTopmostTransaction(xid);
+ 	}
+ 	else
+ 	{
+ 		int32		i;
+ 
+ 		for (i = 0; i < snapshot->subxcnt; i++)
+ 		{
+ 			if (TransactionIdEquals(xid, snapshot->subxip[i]))
+ 				return true;
+ 		}
+ 
+ 		/*
+ 		 * XID may not be a top transaction id. However, they will not match
+ 		 * any top XIDs. So we can merely ignore any subxids not in subxip.
+ 		 */
+ 		parentXid = xid;
+ 	}
+ 
+ 	if (TransactionIdFollowsOrEquals(parentXid, snapshot->xmin))
+ 	{
+ 		uint32		i;
+ 
+ 		/* no point in checking parentXid against xmax here */
+ 
+ 		for (i = 0; i < snapshot->xcnt; i++)
+ 		{
+ 			if (TransactionIdEquals(parentXid, snapshot->xip[i]))
+ 				return true;
+ 		}
+ 	}
+ 
+ 	return false;
  }
diff -cpr pgsql-orig/src/include/utils/tqual.h pgsql/src/include/utils/tqual.h
*** pgsql-orig/src/include/utils/tqual.h	Mon Aug 28 09:36:13 2006
--- pgsql/src/include/utils/tqual.h	Mon Aug 28 17:24:04 2006
*************** typedef struct SnapshotData
*** 39,44 ****
--- 39,46 ----
  	TransactionId xmax;			/* XID >= xmax are invisible to me */
  	uint32		xcnt;			/* # of xact ids in xip[] */
  	TransactionId *xip;			/* array of xact IDs in progress */
+ 	int32		subxcnt;		/* # of xact ids in subxip[], -1 on overflow */
+ 	TransactionId *subxip;		/* array of subxact IDs in progress */
  	/* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
  	CommandId	curcid;			/* in my xact, CID < curcid are visible */
  } SnapshotData;