diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index dac14ac33978305566b5e19f8f62f812699054ec..a8d7ca0c29fe5d04280d4f8d34e646d5981aca5d 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.134 2002/05/20 23:51:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.135 2002/05/21 22:05:53 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1059,15 +1059,14 @@ heap_get_latest_tid(Relation relation,
 	return tid;
 }
 
-/* ----------------
- *		heap_insert		- insert tuple into a heap
+/*
+ *	heap_insert		- insert tuple into a heap
  *
- *		The assignment of t_min (and thus the others) should be
- *		removed eventually.
- * ----------------
+ * The new tuple is stamped with current transaction ID and the specified
+ * command ID.
  */
 Oid
-heap_insert(Relation relation, HeapTuple tup)
+heap_insert(Relation relation, HeapTuple tup, CommandId cid)
 {
 	Buffer		buffer;
 
@@ -1093,8 +1092,9 @@ heap_insert(Relation relation, HeapTuple tup)
 	}
 
 	TransactionIdStore(GetCurrentTransactionId(), &(tup->t_data->t_xmin));
-	tup->t_data->t_cmin = GetCurrentCommandId();
+	tup->t_data->t_cmin = cid;
 	StoreInvalidTransactionId(&(tup->t_data->t_xmax));
+	tup->t_data->t_cmax = FirstCommandId;
 	tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
 	tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
 	tup->t_tableOid = relation->rd_id;
@@ -1178,6 +1178,19 @@ heap_insert(Relation relation, HeapTuple tup)
 	return tup->t_data->t_oid;
 }
 
+/*
+ *	simple_heap_insert - insert a tuple
+ *
+ * Currently, this routine differs from heap_insert only in supplying
+ * a default command ID.  But it should be used rather than using
+ * heap_insert directly in most places where we are modifying system catalogs.
+ */
+Oid
+simple_heap_insert(Relation relation, HeapTuple tup)
+{
+	return heap_insert(relation, tup, GetCurrentCommandId());
+}
+
 /*
  *	heap_delete		- delete a tuple
  *
@@ -1185,7 +1198,8 @@ heap_insert(Relation relation, HeapTuple tup)
  * concurrent-update conditions.  Use simple_heap_delete instead.
  */
 int
-heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid)
+heap_delete(Relation relation, ItemPointer tid,
+			ItemPointer ctid, CommandId cid)
 {
 	ItemId		lp;
 	HeapTupleData tp;
@@ -1215,7 +1229,7 @@ heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid)
 	tp.t_tableOid = relation->rd_id;
 
 l1:
-	result = HeapTupleSatisfiesUpdate(&tp);
+	result = HeapTupleSatisfiesUpdate(&tp, cid);
 
 	if (result == HeapTupleInvisible)
 	{
@@ -1265,7 +1279,7 @@ l1:
 	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_cmax = cid;
 	tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
 							 HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
 	/* XLOG stuff */
@@ -1336,7 +1350,7 @@ simple_heap_delete(Relation relation, ItemPointer tid)
 	ItemPointerData ctid;
 	int			result;
 
-	result = heap_delete(relation, tid, &ctid);
+	result = heap_delete(relation, tid, &ctid, GetCurrentCommandId());
 	switch (result)
 	{
 		case HeapTupleSelfUpdated:
@@ -1356,7 +1370,6 @@ simple_heap_delete(Relation relation, ItemPointer tid)
 			elog(ERROR, "Unknown status %u from heap_delete", result);
 			break;
 	}
-
 }
 
 /*
@@ -1367,7 +1380,7 @@ simple_heap_delete(Relation relation, ItemPointer tid)
  */
 int
 heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
-			ItemPointer ctid)
+			ItemPointer ctid, CommandId cid)
 {
 	ItemId		lp;
 	HeapTupleData oldtup;
@@ -1407,7 +1420,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
 	 */
 
 l2:
-	result = HeapTupleSatisfiesUpdate(&oldtup);
+	result = HeapTupleSatisfiesUpdate(&oldtup, cid);
 
 	if (result == HeapTupleInvisible)
 	{
@@ -1457,7 +1470,7 @@ l2:
 	/* 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();
+	newtup->t_data->t_cmin = cid;
 	StoreInvalidTransactionId(&(newtup->t_data->t_xmax));
 	newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
 	newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED);
@@ -1496,7 +1509,7 @@ l2:
 
 		TransactionIdStore(GetCurrentTransactionId(),
 						   &(oldtup.t_data->t_xmax));
-		oldtup.t_data->t_cmax = GetCurrentCommandId();
+		oldtup.t_data->t_cmax = cid;
 		oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
 									   HEAP_XMAX_INVALID |
 									   HEAP_MARKED_FOR_UPDATE);
@@ -1588,7 +1601,7 @@ l2:
 	{
 		TransactionIdStore(GetCurrentTransactionId(),
 						   &(oldtup.t_data->t_xmax));
-		oldtup.t_data->t_cmax = GetCurrentCommandId();
+		oldtup.t_data->t_cmax = cid;
 		oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
 									   HEAP_XMAX_INVALID |
 									   HEAP_MARKED_FOR_UPDATE);
@@ -1653,7 +1666,7 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
 	ItemPointerData ctid;
 	int			result;
 
-	result = heap_update(relation, otid, tup, &ctid);
+	result = heap_update(relation, otid, tup, &ctid, GetCurrentCommandId());
 	switch (result)
 	{
 		case HeapTupleSelfUpdated:
@@ -1679,7 +1692,8 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
  *	heap_mark4update		- mark a tuple for update
  */
 int
-heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer)
+heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer,
+				 CommandId cid)
 {
 	ItemPointer tid = &(tuple->t_self);
 	ItemId		lp;
@@ -1704,7 +1718,7 @@ heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer)
 	tuple->t_len = ItemIdGetLength(lp);
 
 l3:
-	result = HeapTupleSatisfiesUpdate(tuple);
+	result = HeapTupleSatisfiesUpdate(tuple, cid);
 
 	if (result == HeapTupleInvisible)
 	{
@@ -1758,7 +1772,7 @@ l3:
 
 	/* 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_cmax = cid;
 	tuple->t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
 	tuple->t_data->t_infomask |= HEAP_MARKED_FOR_UPDATE;
 
@@ -2400,9 +2414,8 @@ _heap_unlock_tuple(void *data)
 
 	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");
+	if (!TransactionIdEquals(htup->t_xmax, GetCurrentTransactionId()))
+		elog(PANIC, "_heap_unlock_tuple: invalid xmax in rollback");
 	htup->t_infomask &= ~HEAP_XMAX_UNLOGGED;
 	htup->t_infomask |= HEAP_XMAX_INVALID;
 	UnlockAndWriteBuffer(buffer);
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 18bc99982a5b0eb46000d2560796609ad2c4ad73..9ac1c69c8ea518514366f7ffa65594a76b99fc9d 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.29 2002/05/20 23:51:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.30 2002/05/21 22:05:53 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -911,7 +911,7 @@ toast_save_datum(Relation rel, Datum value)
 		if (!HeapTupleIsValid(toasttup))
 			elog(ERROR, "Failed to build TOAST tuple");
 
-		heap_insert(toastrel, toasttup);
+		simple_heap_insert(toastrel, toasttup);
 
 		/*
 		 * Create the index entry.	We cheat a little here by not using
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 39e4afeb7490d7c5f006cb67886937378be29af8..10de2f8a6d539eec2b56983aa325cf0b56afaa13 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.122 2002/05/17 20:53:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.123 2002/05/21 22:05:53 tgl Exp $
  *
  * NOTES
  *		Transaction aborts can now occur two ways:
@@ -350,14 +350,6 @@ GetCurrentCommandId(void)
 	return s->commandId;
 }
 
-CommandId
-GetScanCommandId(void)
-{
-	TransactionState s = CurrentTransactionState;
-
-	return s->scanCommandId;
-}
-
 
 /* --------------------------------
  *		GetCurrentTransactionStartTime
@@ -418,17 +410,6 @@ CommandIdIsCurrentCommandId(CommandId cid)
 	return (cid == s->commandId) ? true : false;
 }
 
-bool
-CommandIdGEScanCommandId(CommandId cid)
-{
-	TransactionState s = CurrentTransactionState;
-
-	if (AMI_OVERRIDE)
-		return false;
-
-	return (cid >= s->scanCommandId) ? true : false;
-}
-
 
 /* --------------------------------
  *		CommandCounterIncrement
@@ -437,11 +418,17 @@ CommandIdGEScanCommandId(CommandId cid)
 void
 CommandCounterIncrement(void)
 {
-	CurrentTransactionStateData.commandId += 1;
-	if (CurrentTransactionStateData.commandId == FirstCommandId)
+	TransactionState s = CurrentTransactionState;
+
+	s->commandId += 1;
+	if (s->commandId == FirstCommandId)	/* check for overflow */
 		elog(ERROR, "You may only have 2^32-1 commands per transaction");
 
-	CurrentTransactionStateData.scanCommandId = CurrentTransactionStateData.commandId;
+	/* Propagate new command ID into query snapshots, if set */
+	if (QuerySnapshot)
+		QuerySnapshot->curcid = s->commandId;
+	if (SerializableSnapshot)
+		SerializableSnapshot->curcid = s->commandId;
 
 	/*
 	 * make cache changes visible to me.  AtCommit_LocalCache() instead of
@@ -451,11 +438,6 @@ CommandCounterIncrement(void)
 	AtStart_Cache();
 }
 
-void
-SetScanCommandId(CommandId savedId)
-{
-	CurrentTransactionStateData.scanCommandId = savedId;
-}
 
 /* ----------------------------------------------------------------
  *						StartTransaction stuff
@@ -889,10 +871,6 @@ StartTransaction(void)
 	 * initialize current transaction state fields
 	 */
 	s->commandId = FirstCommandId;
-	s->scanCommandId = FirstCommandId;
-#if NOT_USED
-	s->startTime = GetCurrentAbsoluteTime();
-#endif
 	s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeUsec));
 
 	/*
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 5f734ff544768de5f20329fddada3012fb0bbe68..3d1784870e99654b8f79812e2dd33e1a1ddc2cf8 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.130 2002/05/20 23:51:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.131 2002/05/21 22:05:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -680,7 +680,7 @@ InsertOneTuple(Oid objectid)
 
 	if (objectid != (Oid) 0)
 		tuple->t_data->t_oid = objectid;
-	heap_insert(boot_reldesc, tuple);
+	simple_heap_insert(boot_reldesc, tuple);
 	heap_freetuple(tuple);
 	elog(DEBUG3, "row inserted");
 
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 176973363308ec194f1ad65ceae06610f4522d77..c206196bfcc49082dade1667cae906580bbb1194 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.200 2002/05/20 23:51:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.201 2002/05/21 22:05:53 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -440,7 +440,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
 							 ATTRIBUTE_TUPLE_SIZE,
 							 (void *) *dpp);
 
-		heap_insert(rel, tup);
+		simple_heap_insert(rel, tup);
 
 		if (hasindex)
 			CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
@@ -474,7 +474,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
 			/* attStruct->attstattarget = 0; */
 			/* attStruct->attcacheoff = -1; */
 
-			heap_insert(rel, tup);
+			simple_heap_insert(rel, tup);
 
 			if (hasindex)
 				CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
@@ -574,7 +574,7 @@ AddNewRelationTuple(Relation pg_class_desc,
 	/*
 	 * finally insert the new tuple and free it.
 	 */
-	heap_insert(pg_class_desc, tup);
+	simple_heap_insert(pg_class_desc, tup);
 
 	if (!IsIgnoringSystemIndexes())
 	{
@@ -1308,7 +1308,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
 												 CStringGetDatum(adsrc));
 	adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
 	tuple = heap_formtuple(adrel->rd_att, values, nulls);
-	heap_insert(adrel, tuple);
+	simple_heap_insert(adrel, tuple);
 	CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices,
 					   idescs);
 	CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
@@ -1388,7 +1388,7 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
 												 CStringGetDatum(ccsrc));
 	rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
 	tuple = heap_formtuple(rcrel->rd_att, values, nulls);
-	heap_insert(rcrel, tuple);
+	simple_heap_insert(rcrel, tuple);
 	CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices,
 					   idescs);
 	CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 84cc2fe9b1d8d2c9bb9b18e2df2d4d2da4a2cc5b..a0f7f9b4cdf6dccc73d531905e882b2487e74851 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.178 2002/05/20 23:51:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.179 2002/05/21 22:05:53 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -327,7 +327,7 @@ UpdateRelationRelation(Relation indexRelation)
 	 * sure would be embarrassing to do this sort of thing in polite company.
 	 */
 	tuple->t_data->t_oid = RelationGetRelid(indexRelation);
-	heap_insert(pg_class, tuple);
+	simple_heap_insert(pg_class, tuple);
 
 	/*
 	 * During normal processing, we need to make sure that the system
@@ -408,7 +408,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
 								   ATTRIBUTE_TUPLE_SIZE,
 								   (void *) indexTupDesc->attrs[i]);
 
-		heap_insert(pg_attribute, new_tuple);
+		simple_heap_insert(pg_attribute, new_tuple);
 
 		if (hasind)
 			CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, new_tuple);
@@ -500,7 +500,7 @@ UpdateIndexRelation(Oid indexoid,
 	/*
 	 * insert the tuple into the pg_index
 	 */
-	heap_insert(pg_index, tuple);
+	simple_heap_insert(pg_index, tuple);
 
 	/*
 	 * add index tuples for it
@@ -1010,7 +1010,8 @@ LockClassinfoForUpdate(Oid relid, HeapTuple rtup,
 		ItemPointerData tidsave;
 
 		ItemPointerCopy(&(rtup->t_self), &tidsave);
-		test = heap_mark4update(relationRelation, rtup, buffer);
+		test = heap_mark4update(relationRelation, rtup, buffer,
+								GetCurrentCommandId());
 		switch (test)
 		{
 			case HeapTupleSelfUpdated:
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 3e586f0b52392f9bc015f6d1f68b52294e4533fe..1853acda73cf8a8a0231fbb63562b5234053443f 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.46 2002/05/18 13:47:59 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.47 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -174,7 +174,7 @@ AggregateCreate(const char *aggName,
 	tupDesc = aggdesc->rd_att;
 
 	tup = heap_formtuple(tupDesc, values, nulls);
-	heap_insert(aggdesc, tup);
+	simple_heap_insert(aggdesc, tup);
 
 	if (RelationGetForm(aggdesc)->relhasindex)
 	{
diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c
index d4b5e6bfeb3c34f9f822b3f2adca6cd540bf858a..bc3c69f6e7f9d84cc00e2aedfee4783853211542 100644
--- a/src/backend/catalog/pg_largeobject.c
+++ b/src/backend/catalog/pg_largeobject.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.11 2002/05/20 23:51:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.12 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,7 +63,7 @@ LargeObjectCreate(Oid loid)
 	/*
 	 * Insert it
 	 */
-	heap_insert(pg_largeobject, ntup);
+	simple_heap_insert(pg_largeobject, ntup);
 
 	/*
 	 * Update indices
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
index e2cf0128dc8a6bd819ec89483f7aaf4a5dee65cc..f95dafd8ee81ce901820277dceb3d3da99ee47c2 100644
--- a/src/backend/catalog/pg_namespace.c
+++ b/src/backend/catalog/pg_namespace.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_namespace.c,v 1.2 2002/03/31 06:26:30 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_namespace.c,v 1.3 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,13 +61,10 @@ NamespaceCreate(const char *nspName, int32 ownerSysId)
 
 	nspdesc = heap_openr(NamespaceRelationName, RowExclusiveLock);
 	tupDesc = nspdesc->rd_att;
-	if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
-											   values,
-											   nulls)))
-		elog(ERROR, "NamespaceCreate: heap_formtuple failed");
-	nspoid = heap_insert(nspdesc, tup);
-	if (!OidIsValid(nspoid))
-		elog(ERROR, "NamespaceCreate: heap_insert failed");
+
+	tup = heap_formtuple(tupDesc, values, nulls);
+	nspoid = simple_heap_insert(nspdesc, tup);
+	Assert(OidIsValid(nspoid));
 
 	if (RelationGetForm(nspdesc)->relhasindex)
 	{
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 53a5d61cd905b17c90bf7eec90f9342417b090c2..874626ac91b34d284a3691e7145300ea117cc0bc 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.68 2002/04/27 03:45:00 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.69 2002/05/21 22:05:54 tgl Exp $
  *
  * NOTES
  *	  these routines moved here from commands/define.c and somewhat cleaned up.
@@ -260,8 +260,7 @@ OperatorShellMake(const char *operatorName,
 	/*
 	 * insert our "shell" operator tuple
 	 */
-	heap_insert(pg_operator_desc, tup);
-	operatorObjectId = tup->t_data->t_oid;
+	operatorObjectId = simple_heap_insert(pg_operator_desc, tup);
 
 	if (RelationGetForm(pg_operator_desc)->relhasindex)
 	{
@@ -360,7 +359,7 @@ OperatorShellMake(const char *operatorName,
  *	 get the t_self from the modified tuple and call RelationReplaceHeapTuple
  * else if a new operator is being created
  *	 create a tuple using heap_formtuple
- *	 call heap_insert
+ *	 call simple_heap_insert
  */
 void
 OperatorCreate(const char *operatorName,
@@ -647,8 +646,7 @@ OperatorCreate(const char *operatorName,
 		tupDesc = pg_operator_desc->rd_att;
 		tup = heap_formtuple(tupDesc, values, nulls);
 
-		heap_insert(pg_operator_desc, tup);
-		operatorObjectId = tup->t_data->t_oid;
+		operatorObjectId = simple_heap_insert(pg_operator_desc, tup);
 	}
 
 	/* Must update the indexes in either case */
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 6fa6a4bf6fe3ea807f416bde7492e079bbd6fa3d..4d656d98ba22b2ac0a608c73c78cf62919a11bbc 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.72 2002/05/18 13:47:59 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.73 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -298,7 +298,7 @@ ProcedureCreate(const char *procedureName,
 		nulls[Anum_pg_proc_proacl-1] = 'n';
 
 		tup = heap_formtuple(tupDesc, values, nulls);
-		heap_insert(rel, tup);
+		simple_heap_insert(rel, tup);
 	}
 
 	/* Need to update indices for either the insert or update case */
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 15c24c077ad90fa56715273ce2007c2975c1eeef..d07e8c243906f2b964485433c506cdd8a620bb74 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.70 2002/03/29 19:06:02 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.71 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,8 +102,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
 	/*
 	 * insert the tuple in the relation and get the tuple's oid.
 	 */
-	heap_insert(pg_type_desc, tup);
-	typoid = tup->t_data->t_oid;
+	typoid = simple_heap_insert(pg_type_desc, tup);
 
 	if (RelationGetForm(pg_type_desc)->relhasindex)
 	{
@@ -286,9 +285,7 @@ TypeCreate(const char *typeName,
 		/* preassign tuple Oid, if one was given */
 		tup->t_data->t_oid = assignedTypeOid;
 
-		heap_insert(pg_type_desc, tup);
-
-		typeObjectId = tup->t_data->t_oid;
+		typeObjectId = simple_heap_insert(pg_type_desc, tup);
 	}
 
 	/* Update indices (not necessary if bootstrapping) */
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index c015043843843bef5a0655d4fcbc629f315a12a0..3f5cc96f41a014776212171238346677d492517a 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.33 2002/05/20 23:51:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.34 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1787,7 +1787,7 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
 		{
 			/* No, insert new tuple */
 			stup = heap_formtuple(sd->rd_att, values, nulls);
-			heap_insert(sd, stup);
+			simple_heap_insert(sd, stup);
 		}
 
 		/* update indices too */
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 271be1511955c3c6b493f4aed381203a7fc1a2ee..7ed3663a48f394a91fef77b3ed1b99a2b592964c 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.85 2002/05/20 23:51:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.86 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -242,7 +242,7 @@ Async_Listen(char *relname, int pid)
 	values[i++] = (Datum) 0;	/* no notifies pending */
 
 	tuple = heap_formtuple(RelationGetDescr(lRel), values, nulls);
-	heap_insert(lRel, tuple);
+	simple_heap_insert(lRel, tuple);
 
 #ifdef NOT_USED					/* currently there are no indexes */
 	if (RelationGetForm(lRel)->relhasindex)
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index a6215cb23f4140bad06238cd4bc28520db985c93..be60227402886abbc6453fe76d9008493a9c1ac7 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.80 2002/05/20 23:51:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.81 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -241,7 +241,7 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
 		 */
 		HeapTuple	copiedTuple = heap_copytuple(LocalHeapTuple);
 
-		heap_insert(LocalNewHeap, copiedTuple);
+		simple_heap_insert(LocalNewHeap, copiedTuple);
 		heap_freetuple(copiedTuple);
 
 		CHECK_FOR_INTERRUPTS();
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 9d48e33b2c0c0fd92f7dcb0e97a2c56f8d3f06d6..728672061438db519549da76210a1e95bb0a908e 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
  * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.47 2002/05/20 23:51:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.48 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -199,7 +199,7 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 	{
 		newtuple = heap_formtuple(RelationGetDescr(description),
 								  values, nulls);
-		heap_insert(description, newtuple);
+		simple_heap_insert(description, newtuple);
 	}
 
 	/* Update indexes, if necessary */
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 1f9aef8fc0dc7e739a8b2325922d3807bb35d305..83ca5b32c5439fea5ed981060caeb0aed3360df5 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.154 2002/05/20 23:51:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.155 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -947,7 +947,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
 			/*
 			 * OK, store the tuple and create index entries for it
 			 */
-			heap_insert(rel, tuple);
+			simple_heap_insert(rel, tuple);
 
 			if (resultRelInfo->ri_NumIndices > 0)
 				ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index d4bc274ba29575615b933ac94069e2700438f92c..bdba0dacfc0a145bd4d55a2d31f593034e7036ef 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.90 2002/05/20 23:51:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.91 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -293,7 +293,7 @@ createdb(const char *dbname, const char *dbowner,
 	tuple->t_data->t_oid = dboid;		/* override heap_insert's OID
 										 * selection */
 
-	heap_insert(pg_database_rel, tuple);
+	simple_heap_insert(pg_database_rel, tuple);
 
 	/*
 	 * Update indexes
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
index 6f690c0927ce5357fff37439f83f6aaa081c72b8..754ea46246c733d411738503abebd61382103e8d 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.2 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -74,7 +74,6 @@ PerformPortalFetch(char *name,
 	EState	   *estate;
 	MemoryContext oldcontext;
 	ScanDirection direction;
-	CommandId	savedId;
 	bool		temp_desc = false;
 
 	/* initialize completion status in case of early exit */
@@ -131,14 +130,6 @@ PerformPortalFetch(char *name,
 		temp_desc = true;
 	}
 
-	/*
-	 * Restore the scanCommandId that was current when the cursor was
-	 * opened.  This ensures that we see the same tuples throughout the
-	 * execution of the cursor.
-	 */
-	savedId = GetScanCommandId();
-	SetScanCommandId(PortalGetCommandId(portal));
-
 	/*
 	 * Determine which direction to go in, and check to see if we're
 	 * already at the end of the available tuples in that direction.  If
@@ -185,11 +176,6 @@ PerformPortalFetch(char *name,
 				 (dest == None) ? "MOVE" : "FETCH",
 				 estate->es_processed);
 
-	/*
-	 * Restore outer command ID.
-	 */
-	SetScanCommandId(savedId);
-
 	/*
 	 * Clean up and switch back to old context.
 	 */
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 2ad25fdbd4f2cf977f9cd78175e99cd70b7a40b9..6cabbf0ec1357d5ff559c357449d3d611b9b67d8 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.31 2002/04/15 05:22:03 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.32 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,7 +102,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	tupDesc = rel->rd_att;
 	tup = heap_formtuple(tupDesc, values, nulls);
 
-	heap_insert(rel, tup);
+	simple_heap_insert(rel, tup);
 
 	if (RelationGetForm(rel)->relhasindex)
 	{
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0fa56fcfb7db7fdba605fade2ae2ecc978069076..c79e6f97e1ba6bfd5b39ca453664ce2af4bc72fe 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.77 2002/04/15 05:22:03 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.78 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -197,7 +197,7 @@ DefineSequence(CreateSeqStmt *seq)
 
 	/* Now form & insert sequence tuple */
 	tuple = heap_formtuple(tupDesc, value, null);
-	heap_insert(rel, tuple);
+	simple_heap_insert(rel, tuple);
 
 	Assert(ItemPointerGetOffsetNumber(&(tuple->t_self)) == FirstOffsetNumber);
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f2bbdb01075d4085beb9be9bd21fbeda23d21945..aff1590f11be62db122ba7ee1388e92617a4be27 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.15 2002/05/20 23:51:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.16 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -821,7 +821,7 @@ StoreCatalogInheritance(Oid relationId, List *supers)
 
 		tuple = heap_formtuple(desc, datum, nullarr);
 
-		heap_insert(relation, tuple);
+		simple_heap_insert(relation, tuple);
 
 		if (RelationGetForm(relation)->relhasindex)
 		{
@@ -1673,7 +1673,7 @@ AlterTableAddColumn(Oid myrelid,
 
 	ReleaseSysCache(typeTuple);
 
-	heap_insert(attrdesc, attributeTuple);
+	simple_heap_insert(attrdesc, attributeTuple);
 
 	/* Update indexes on pg_attribute */
 	if (RelationGetForm(attrdesc)->relhasindex)
@@ -2890,7 +2890,8 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
 	classtuple.t_self = reltup->t_self;
 	ReleaseSysCache(reltup);
 
-	switch (heap_mark4update(class_rel, &classtuple, &buffer))
+	switch (heap_mark4update(class_rel, &classtuple, &buffer,
+							 GetCurrentCommandId()))
 	{
 		case HeapTupleSelfUpdated:
 		case HeapTupleMayBeUpdated:
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index a871c857880b65601892f54182a453b543d256bc..e0b01b6fee5c236a8d52abf04decdf211820d84f 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.117 2002/04/30 01:24:57 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.118 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -270,7 +270,7 @@ CreateTrigger(CreateTrigStmt *stmt)
 	/*
 	 * Insert tuple into pg_trigger.
 	 */
-	heap_insert(tgrel, tuple);
+	simple_heap_insert(tgrel, tuple);
 	CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs);
 	CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
 	CatalogCloseIndices(Num_pg_trigger_indices, idescs);
@@ -1183,7 +1183,8 @@ GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
 		*newSlot = NULL;
 		tuple.t_self = *tid;
 ltrmark:;
-		test = heap_mark4update(relation, &tuple, &buffer);
+		test = heap_mark4update(relation, &tuple, &buffer,
+								GetCurrentCommandId());
 		switch (test)
 		{
 			case HeapTupleSelfUpdated:
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index c7c3da9dd42ef4f79802485f805ae483b19842ef..98f47dd98bb5d83c885d1b5cef6f864931493a3c 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.102 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.103 2002/05/21 22:05:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -596,7 +596,7 @@ CreateUser(CreateUserStmt *stmt)
 	/*
 	 * Insert new record in the pg_shadow table
 	 */
-	heap_insert(pg_shadow_rel, tuple);
+	simple_heap_insert(pg_shadow_rel, tuple);
 
 	/*
 	 * Update indexes
@@ -1213,9 +1213,9 @@ CreateGroup(CreateGroupStmt *stmt)
 	tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
 
 	/*
-	 * Insert a new record in the pg_group_table
+	 * Insert a new record in the pg_group table
 	 */
-	heap_insert(pg_group_rel, tuple);
+	simple_heap_insert(pg_group_rel, tuple);
 
 	/*
 	 * Update indexes
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index a2c43bc0359d76103de2dfc39c278cd4ed94f94b..a8c776bab2c4a89b145ef3721933b3851fd34463 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.161 2002/05/12 20:10:02 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.162 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -101,6 +101,7 @@ TupleDesc
 ExecutorStart(QueryDesc *queryDesc, EState *estate)
 {
 	TupleDesc	result;
+	Snapshot	es_snapshot;
 
 	/* sanity checks */
 	Assert(queryDesc != NULL);
@@ -114,22 +115,28 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
 	}
 
 	/*
-	 * Make our own private copy of the current queries snapshot data
+	 * Make our own private copy of the current query snapshot data.
+	 *
+	 * This "freezes" our idea of which tuples are good and which are not
+	 * for the life of this query, even if it outlives the current command
+	 * and current snapshot.
 	 */
-	if (QuerySnapshot == NULL)
-		estate->es_snapshot = NULL;
-	else
+	if (QuerySnapshot == NULL)	/* should be set already, but... */
+		SetQuerySnapshot();
+
+	es_snapshot = (Snapshot) palloc(sizeof(SnapshotData));
+	memcpy(es_snapshot, QuerySnapshot, sizeof(SnapshotData));
+	if (es_snapshot->xcnt > 0)
 	{
-		estate->es_snapshot = (Snapshot) palloc(sizeof(SnapshotData));
-		memcpy(estate->es_snapshot, QuerySnapshot, sizeof(SnapshotData));
-		if (estate->es_snapshot->xcnt > 0)
-		{
-			estate->es_snapshot->xip = (TransactionId *)
-				palloc(estate->es_snapshot->xcnt * sizeof(TransactionId));
-			memcpy(estate->es_snapshot->xip, QuerySnapshot->xip,
-				   estate->es_snapshot->xcnt * sizeof(TransactionId));
-		}
+		es_snapshot->xip = (TransactionId *)
+			palloc(es_snapshot->xcnt * sizeof(TransactionId));
+		memcpy(es_snapshot->xip, QuerySnapshot->xip,
+			   es_snapshot->xcnt * sizeof(TransactionId));
 	}
+	else
+		es_snapshot->xip = NULL;
+
+	estate->es_snapshot = es_snapshot;
 
 	/*
 	 * Initialize the plan
@@ -1031,7 +1038,8 @@ lnext:	;
 							 erm->resname);
 
 					tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
-					test = heap_mark4update(erm->relation, &tuple, &buffer);
+					test = heap_mark4update(erm->relation, &tuple, &buffer,
+											estate->es_snapshot->curcid);
 					ReleaseBuffer(buffer);
 					switch (test)
 					{
@@ -1163,7 +1171,8 @@ ExecRetrieve(TupleTableSlot *slot,
 	 */
 	if (estate->es_into_relation_descriptor != NULL)
 	{
-		heap_insert(estate->es_into_relation_descriptor, tuple);
+		heap_insert(estate->es_into_relation_descriptor, tuple,
+					estate->es_snapshot->curcid);
 		IncrAppended();
 	}
 
@@ -1239,7 +1248,8 @@ ExecAppend(TupleTableSlot *slot,
 	/*
 	 * insert the tuple
 	 */
-	newId = heap_insert(resultRelationDesc, tuple);
+	newId = heap_insert(resultRelationDesc, tuple,
+						estate->es_snapshot->curcid);
 
 	IncrAppended();
 	(estate->es_processed)++;
@@ -1301,7 +1311,9 @@ ExecDelete(TupleTableSlot *slot,
 	 * delete the tuple
 	 */
 ldelete:;
-	result = heap_delete(resultRelationDesc, tupleid, &ctid);
+	result = heap_delete(resultRelationDesc, tupleid,
+						 &ctid,
+						 estate->es_snapshot->curcid);
 	switch (result)
 	{
 		case HeapTupleSelfUpdated:
@@ -1433,7 +1445,9 @@ lreplace:;
 	/*
 	 * replace the heap tuple
 	 */
-	result = heap_update(resultRelationDesc, tupleid, tuple, &ctid);
+	result = heap_update(resultRelationDesc, tupleid, tuple,
+						 &ctid,
+						 estate->es_snapshot->curcid);
 	switch (result)
 	{
 		case HeapTupleSelfUpdated:
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 938f7e17f931ba31ef8398fd8cfce21c7ea50a21..1265bc78d4b259e2acbbed78ca08145291ec1de7 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.50 2002/05/12 20:10:02 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.51 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -465,7 +465,6 @@ fmgr_sql(PG_FUNCTION_ARGS)
 	SQLFunctionCachePtr fcache;
 	execution_state *es;
 	Datum		result = 0;
-	CommandId	savedId;
 
 	/*
 	 * Switch to context in which the fcache lives.  This ensures that
@@ -474,14 +473,6 @@ fmgr_sql(PG_FUNCTION_ARGS)
 	 */
 	oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
 
-	/*
-	 * Before we start do anything we must save CurrentScanCommandId to
-	 * restore it before return to upper Executor. Also, we have to set
-	 * CurrentScanCommandId equal to CurrentCommandId. - vadim 08/29/97
-	 */
-	savedId = GetScanCommandId();
-	SetScanCommandId(GetCurrentCommandId());
-
 	/*
 	 * Initialize fcache and execution state if first time through.
 	 */
@@ -515,11 +506,6 @@ fmgr_sql(PG_FUNCTION_ARGS)
 		es = es->next;
 	}
 
-	/*
-	 * Restore outer command ID.
-	 */
-	SetScanCommandId(savedId);
-
 	/*
 	 * If we've gone through every command in this function, we are done.
 	 */
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index b9bcce30e29acab992940a0f59ff650b7d638349..9c445650e54e5e9e90cd092db02209c81d794d43 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.69 2002/04/15 05:22:04 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.70 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -106,11 +106,7 @@ SPI_connect(void)
 	/* ... and switch to procedure's context */
 	_SPI_current->savedcxt = MemoryContextSwitchTo(_SPI_current->procCxt);
 
-	_SPI_current->savedId = GetScanCommandId();
-	SetScanCommandId(GetCurrentCommandId());
-
 	return SPI_OK_CONNECT;
-
 }
 
 int
@@ -129,8 +125,6 @@ SPI_finish(void)
 	MemoryContextDelete(_SPI_current->execCxt);
 	MemoryContextDelete(_SPI_current->procCxt);
 
-	SetScanCommandId(_SPI_current->savedId);
-
 	/*
 	 * After _SPI_begin_call _SPI_connected == _SPI_curid. Now we are
 	 * closing connection to SPI and returning to upper Executor and so
@@ -1233,7 +1227,6 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
 	EState	   *estate;
 	MemoryContext oldcontext;
 	ScanDirection direction;
-	CommandId	savedId;
 	CommandDest olddest;
 
 	/* Check that the portal is valid */
@@ -1260,14 +1253,6 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
 	olddest = querydesc->dest;
 	querydesc->dest = dest;
 
-	/*
-	 * Restore the scanCommandId that was current when the cursor was
-	 * opened.  This ensures that we see the same tuples throughout the
-	 * execution of the cursor.
-	 */
-	savedId = GetScanCommandId();
-	SetScanCommandId(PortalGetCommandId(portal));
-
 	/* Run the executor like PerformPortalFetch and remember states */
 	if (forward)
 	{
@@ -1300,11 +1285,6 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
 
 	_SPI_current->processed = estate->es_processed;
 
-	/*
-	 * Restore outer command ID.
-	 */
-	SetScanCommandId(savedId);
-
 	/* Restore the old command destination and switch back to callers */
 	/* memory context */
 	querydesc->dest = olddest;
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 4b1799ff2e953161563cc3769e729ab04dd7ebfa..81fd39df360e271afb50c506cf42ec1f4fdee7b4 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.71 2002/05/20 23:51:43 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.72 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -88,9 +88,7 @@ InsertRule(char *rulname,
 						 values,
 						 nulls);
 
-	heap_insert(pg_rewrite_desc, tup);
-
-	rewriteObjectId = tup->t_data->t_oid;
+	rewriteObjectId = simple_heap_insert(pg_rewrite_desc, tup);
 
 	if (RelationGetForm(pg_rewrite_desc)->relhasindex)
 	{
diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c
index 865c96ed8fa48cefabcbee6b15b4592f21d1021a..a32c8ae7035462d94a3c2aaf734284af43dabbb6 100644
--- a/src/backend/storage/ipc/sinval.c
+++ b/src/backend/storage/ipc/sinval.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.45 2002/03/02 23:35:57 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.46 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -397,6 +397,9 @@ GetSnapshotData(bool serializable)
 	Assert(TransactionIdIsValid(MyProc->xmin));
 
 	snapshot->xcnt = count;
+
+	snapshot->curcid = GetCurrentCommandId();
+
 	return snapshot;
 }
 
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index a470a870df725500eb7b6b43d1bd7e0dc1525de2..fb0bf888093f538876dd056eca78e3ff1615e4ed 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.91 2002/05/20 23:51:43 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.92 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -555,7 +555,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 			values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);
 			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
 			newtup = heap_formtuple(obj_desc->heap_r->rd_att, values, nulls);
-			heap_insert(obj_desc->heap_r, newtup);
+			simple_heap_insert(obj_desc->heap_r, newtup);
 			if (write_indices)
 				CatalogIndexInsert(idescs, Num_pg_largeobject_indices,
 								   obj_desc->heap_r, newtup);
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 318827ed957761dd42d34af702734a166f3aa5bb..90e9ca6a71cc7c786d841fb62176427eb8d4b1f8 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.47 2002/03/06 06:10:29 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.48 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -168,7 +168,6 @@ PortalSetQuery(Portal portal,
 
 	portal->queryDesc = queryDesc;
 	portal->attinfo = attinfo;
-	portal->commandId = GetScanCommandId();
 	portal->state = state;
 	portal->atStart = true;		/* Allow fetch forward only */
 	portal->atEnd = false;
@@ -214,7 +213,6 @@ CreatePortal(char *name)
 	/* initialize portal query */
 	portal->queryDesc = NULL;
 	portal->attinfo = NULL;
-	portal->commandId = 0;
 	portal->state = NULL;
 	portal->atStart = true;		/* disallow fetches until query is set */
 	portal->atEnd = true;
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index ba052e5f77b6fbb1f5d855eb9fc6e34949427100..58534159f7a95d17e408354e4f7a53725fc20f24 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -16,7 +16,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.50 2002/05/06 02:39:01 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.51 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -238,7 +238,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
 		}
 		else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
 		{
-			if (CommandIdGEScanCommandId(tuple->t_cmin))
+			if (tuple->t_cmin >= GetCurrentCommandId())
 				return false;	/* inserted after scan started */
 
 			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
@@ -249,7 +249,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
 			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
 				return true;
 
-			if (CommandIdGEScanCommandId(tuple->t_cmax))
+			if (tuple->t_cmax >= GetCurrentCommandId())
 				return true;	/* deleted after scan started */
 			else
 				return false;	/* deleted before scan started */
@@ -280,7 +280,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
 	{
 		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
 			return true;
-		if (CommandIdGEScanCommandId(tuple->t_cmax))
+		if (tuple->t_cmax >= GetCurrentCommandId())
 			return true;		/* deleted after scan started */
 		else
 			return false;		/* deleted before scan started */
@@ -363,10 +363,12 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
  * HeapTupleSatisfiesUpdate
  *
  *	Same logic as HeapTupleSatisfiesNow, but returns a more detailed result
- *	code, since UPDATE needs to know more than "is it visible?".
+ *	code, since UPDATE needs to know more than "is it visible?".  Also,
+ *	tuples of my own xact are tested against the passed CommandId not
+ *	CurrentCommandId.
  */
 int
-HeapTupleSatisfiesUpdate(HeapTuple htuple)
+HeapTupleSatisfiesUpdate(HeapTuple htuple, CommandId curcid)
 {
 	HeapTupleHeader tuple = htuple->t_data;
 
@@ -409,7 +411,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple)
 		}
 		else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
 		{
-			if (CommandIdGEScanCommandId(tuple->t_cmin))
+			if (tuple->t_cmin >= curcid)
 				return HeapTupleInvisible;		/* inserted after scan
 												 * started */
 
@@ -421,7 +423,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple)
 			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
 				return HeapTupleMayBeUpdated;
 
-			if (CommandIdGEScanCommandId(tuple->t_cmax))
+			if (tuple->t_cmax >= curcid)
 				return HeapTupleSelfUpdated;	/* updated after scan
 												 * started */
 			else
@@ -454,7 +456,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple)
 	{
 		if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
 			return HeapTupleMayBeUpdated;
-		if (CommandIdGEScanCommandId(tuple->t_cmax))
+		if (tuple->t_cmax >= curcid)
 			return HeapTupleSelfUpdated;		/* updated after scan
 												 * started */
 		else
@@ -677,7 +679,7 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
 		}
 		else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
 		{
-			if (CommandIdGEScanCommandId(tuple->t_cmin))
+			if (tuple->t_cmin >= snapshot->curcid)
 				return false;	/* inserted after scan started */
 
 			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
@@ -688,7 +690,7 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
 			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
 				return true;
 
-			if (CommandIdGEScanCommandId(tuple->t_cmax))
+			if (tuple->t_cmax >= snapshot->curcid)
 				return true;	/* deleted after scan started */
 			else
 				return false;	/* deleted before scan started */
@@ -730,7 +732,7 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
 	{
 		if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
 		{
-			if (CommandIdGEScanCommandId(tuple->t_cmax))
+			if (tuple->t_cmax >= snapshot->curcid)
 				return true;	/* deleted after scan started */
 			else
 				return false;	/* deleted before scan started */
@@ -950,6 +952,7 @@ SetQuerySnapshot(void)
 	{
 		free(QuerySnapshot->xip);
 		free(QuerySnapshot);
+		QuerySnapshot = NULL;
 	}
 
 	if (XactIsoLevel == XACT_SERIALIZABLE)
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index b8f2394fc54ca58215ea45440930c649e7905957..7bf75f512d3393316bc53ad7dacad44c76da3ac9 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.74 2002/05/20 23:51:43 tgl Exp $
+ * $Id: heapam.h,v 1.75 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -156,16 +156,23 @@ extern void heap_fetch(Relation relation, Snapshot snapshot,
 					   HeapTuple tuple, Buffer *userbuf,
 					   PgStat_Info *pgstat_info);
 
-extern ItemPointer heap_get_latest_tid(Relation relation, Snapshot snapshot, ItemPointer tid);
+extern ItemPointer heap_get_latest_tid(Relation relation, Snapshot snapshot,
+									   ItemPointer tid);
 extern void setLastTid(const ItemPointer tid);
-extern Oid	heap_insert(Relation relation, HeapTuple tup);
-extern int	heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid);
+
+extern Oid	heap_insert(Relation relation, HeapTuple tup, CommandId cid);
+extern int	heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid,
+						CommandId cid);
 extern int heap_update(Relation relation, ItemPointer otid, HeapTuple tup,
-			ItemPointer ctid);
-extern int	heap_mark4update(Relation relation, HeapTuple tup, Buffer *userbuf);
+					   ItemPointer ctid, CommandId cid);
+extern int	heap_mark4update(Relation relation, HeapTuple tup,
+							 Buffer *userbuf, CommandId cid);
+
+extern Oid	simple_heap_insert(Relation relation, HeapTuple tup);
 extern void simple_heap_delete(Relation relation, ItemPointer tid);
 extern void simple_heap_update(Relation relation, ItemPointer otid,
 				   HeapTuple tup);
+
 extern void heap_markpos(HeapScanDesc scan);
 extern void heap_restrpos(HeapScanDesc scan);
 
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 0cfc1652f22ea032adcb95514a21415b9ed52abf..537d84b63dba36babd09abd8c3cfec041dbe77c4 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: xact.h,v 1.42 2002/04/01 03:34:27 tgl Exp $
+ * $Id: xact.h,v 1.43 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,7 +38,6 @@ typedef struct TransactionStateData
 {
 	TransactionId transactionIdData;
 	CommandId	commandId;
-	CommandId	scanCommandId;
 	AbsoluteTime startTime;
 	int			startTimeUsec;
 	int			state;
@@ -101,13 +100,10 @@ extern bool IsTransactionState(void);
 extern bool IsAbortedTransactionBlockState(void);
 extern TransactionId GetCurrentTransactionId(void);
 extern CommandId GetCurrentCommandId(void);
-extern CommandId GetScanCommandId(void);
-extern void SetScanCommandId(CommandId);
 extern AbsoluteTime GetCurrentTransactionStartTime(void);
 extern AbsoluteTime GetCurrentTransactionStartTimeUsec(int *usec);
 extern bool TransactionIdIsCurrentTransactionId(TransactionId xid);
 extern bool CommandIdIsCurrentCommandId(CommandId cid);
-extern bool CommandIdGEScanCommandId(CommandId cid);
 extern void CommandCounterIncrement(void);
 extern void StartTransactionCommand(void);
 extern void CommitTransactionCommand(void);
diff --git a/src/include/executor/spi_priv.h b/src/include/executor/spi_priv.h
index dd8b18775029d8bf20037b1e2268b0ae0602caf2..c780c3656fa9423f379ca489df37a8f716b80086 100644
--- a/src/include/executor/spi_priv.h
+++ b/src/include/executor/spi_priv.h
@@ -3,7 +3,7 @@
  * spi.c
  *				Server Programming Interface private declarations
  *
- * $Header: /cvsroot/pgsql/src/include/executor/spi_priv.h,v 1.11 2001/11/05 17:46:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/include/executor/spi_priv.h,v 1.12 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,6 @@ typedef struct
 	MemoryContext procCxt;		/* procedure context */
 	MemoryContext execCxt;		/* executor context */
 	MemoryContext savedcxt;
-	CommandId	savedId;
 } _SPI_connection;
 
 typedef struct
diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h
index 9198b21feb9f53194aa779e474931519cd8ee67c..491106fac37293d6282397f12949059d17fc5612 100644
--- a/src/include/utils/portal.h
+++ b/src/include/utils/portal.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: portal.h,v 1.32 2002/02/14 15:24:10 tgl Exp $
+ * $Id: portal.h,v 1.33 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,6 @@ typedef struct PortalData
 	MemoryContext heap;			/* subsidiary memory */
 	QueryDesc  *queryDesc;		/* Info about query associated with portal */
 	TupleDesc	attinfo;
-	CommandId	commandId;		/* Command counter value for query */
 	EState	   *state;			/* Execution state of query */
 	bool		atStart;		/* T => fetch backwards is not allowed */
 	bool		atEnd;			/* T => fetch forwards is not allowed */
@@ -49,7 +48,6 @@ typedef struct PortalData
  */
 #define PortalGetQueryDesc(portal)	((portal)->queryDesc)
 #define PortalGetTupleDesc(portal)	((portal)->attinfo)
-#define PortalGetCommandId(portal)	((portal)->commandId)
 #define PortalGetState(portal)		((portal)->state)
 #define PortalGetHeapMemory(portal)	((portal)->heap)
 
diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h
index a69851e66611ccce2467485dabe04a4363b8d532..f5f03ea01af737c978ee3708cd1b1ac665fb2bfd 100644
--- a/src/include/utils/tqual.h
+++ b/src/include/utils/tqual.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tqual.h,v 1.38 2002/01/16 20:29:02 tgl Exp $
+ * $Id: tqual.h,v 1.39 2002/05/21 22:05:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@ typedef struct SnapshotData
 	uint32		xcnt;			/* # of xact ids in xip[] */
 	TransactionId *xip;			/* array of xact IDs in progress */
 	/* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
+	CommandId	curcid;			/* in my xact, CID < curcid are visible */
 	ItemPointerData tid;		/* required for Dirty snapshot -:( */
 } SnapshotData;
 
@@ -104,7 +105,8 @@ extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple);
 extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple);
 extern bool HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple,
 						   Snapshot snapshot);
-extern int	HeapTupleSatisfiesUpdate(HeapTuple tuple);
+extern int	HeapTupleSatisfiesUpdate(HeapTuple tuple,
+									 CommandId curcid);
 extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
 						 TransactionId OldestXmin);