diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index e664b3e494230cb49bede711b5ae529f2860e6aa..eb73c91409b25b19798384a683d6dff18ca15df1 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.115 2003/08/11 20:46:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.116 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -207,7 +207,7 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
 	gettimeofday(&starttime, NULL);
 
 	/* call ExecutorStart to prepare the plan for execution */
-	ExecutorStart(queryDesc, !stmt->analyze);
+	ExecutorStart(queryDesc, false, !stmt->analyze);
 
 	/* Execute the plan for statistics if asked for */
 	if (stmt->analyze)
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index d6868818656f587c97bc192e62fd03939500a56e..5a824ce40ee3a2d417c000e1971c8847b0790d4a 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.157 2003/09/25 06:57:58 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.158 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1862,12 +1862,6 @@ DeferredTriggerExecute(DeferredTriggerEvent event, int itemno,
 	if (rettuple != NULL && rettuple != &oldtuple && rettuple != &newtuple)
 		heap_freetuple(rettuple);
 
-	/*
-	 * Might have been a referential integrity constraint trigger. Reset
-	 * the snapshot overriding flag.
-	 */
-	ReferentialIntegritySnapshotOverride = false;
-
 	/*
 	 * Release buffers
 	 */
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 5d904f15d3d3395a6cccd3a0a0f93ff6223d120b..6b92920bcd1686f9db1564b8f4a8dada687bc990 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.218 2003/09/25 06:57:59 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.219 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -104,6 +104,9 @@ static void EvalPlanQualStop(evalPlanQual *epq);
  * field of the QueryDesc is filled in to describe the tuples that will be
  * returned, and the internal fields (estate and planstate) are set up.
  *
+ * If useSnapshotNow is true, run the query with SnapshotNow time qual rules
+ * instead of the normal use of QuerySnapshot.
+ *
  * If explainOnly is true, we are not actually intending to run the plan,
  * only to set up for EXPLAIN; so skip unwanted side-effects.
  *
@@ -112,7 +115,7 @@ static void EvalPlanQualStop(evalPlanQual *epq);
  * ----------------------------------------------------------------
  */
 void
-ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
+ExecutorStart(QueryDesc *queryDesc, bool useSnapshotNow, bool explainOnly)
 {
 	EState	   *estate;
 	MemoryContext oldcontext;
@@ -154,7 +157,16 @@ ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
 	 * the life of this query, even if it outlives the current command and
 	 * current snapshot.
 	 */
-	estate->es_snapshot = CopyQuerySnapshot();
+	if (useSnapshotNow)
+	{
+		estate->es_snapshot = SnapshotNow;
+		estate->es_snapshot_cid = GetCurrentCommandId();
+	}
+	else
+	{
+		estate->es_snapshot = CopyQuerySnapshot();
+		estate->es_snapshot_cid = estate->es_snapshot->curcid;
+	}
 
 	/*
 	 * Initialize the plan state tree
@@ -1106,7 +1118,7 @@ lnext:	;
 
 					tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
 					test = heap_mark4update(erm->relation, &tuple, &buffer,
-											estate->es_snapshot->curcid);
+											estate->es_snapshot_cid);
 					ReleaseBuffer(buffer);
 					switch (test)
 					{
@@ -1266,7 +1278,7 @@ ExecSelect(TupleTableSlot *slot,
 	if (estate->es_into_relation_descriptor != NULL)
 	{
 		heap_insert(estate->es_into_relation_descriptor, tuple,
-					estate->es_snapshot->curcid);
+					estate->es_snapshot_cid);
 		IncrAppended();
 	}
 
@@ -1342,7 +1354,7 @@ ExecInsert(TupleTableSlot *slot,
 	 * insert the tuple
 	 */
 	newId = heap_insert(resultRelationDesc, tuple,
-						estate->es_snapshot->curcid);
+						estate->es_snapshot_cid);
 
 	IncrAppended();
 	(estate->es_processed)++;
@@ -1394,7 +1406,7 @@ ExecDelete(TupleTableSlot *slot,
 		bool		dodelete;
 
 		dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid,
-										estate->es_snapshot->curcid);
+										estate->es_snapshot_cid);
 
 		if (!dodelete)			/* "do nothing" */
 			return;
@@ -1406,7 +1418,7 @@ ExecDelete(TupleTableSlot *slot,
 ldelete:;
 	result = heap_delete(resultRelationDesc, tupleid,
 						 &ctid,
-						 estate->es_snapshot->curcid,
+						 estate->es_snapshot_cid,
 						 true /* wait for commit */);
 	switch (result)
 	{
@@ -1505,7 +1517,7 @@ ExecUpdate(TupleTableSlot *slot,
 
 		newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
 										tupleid, tuple,
-										estate->es_snapshot->curcid);
+										estate->es_snapshot_cid);
 
 		if (newtuple == NULL)	/* "do nothing" */
 			return;
@@ -1541,7 +1553,7 @@ lreplace:;
 	 */
 	result = heap_update(resultRelationDesc, tupleid, tuple,
 						 &ctid,
-						 estate->es_snapshot->curcid,
+						 estate->es_snapshot_cid,
 						 true /* wait for commit */);
 	switch (result)
 	{
@@ -2027,6 +2039,7 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
 	 */
 	epqstate->es_direction = ForwardScanDirection;
 	epqstate->es_snapshot = estate->es_snapshot;
+	epqstate->es_snapshot_cid = estate->es_snapshot_cid;
 	epqstate->es_range_table = estate->es_range_table;
 	epqstate->es_result_relations = estate->es_result_relations;
 	epqstate->es_num_result_relations = estate->es_num_result_relations;
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 4aa3170daa6a8995019f61df629018a99c205e7e..c9c7ef79396b26190b4ba95deeb8d5f4c507a991 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.104 2003/09/24 18:54:01 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.105 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -178,6 +178,7 @@ CreateExecutorState(void)
 	 */
 	estate->es_direction = ForwardScanDirection;
 	estate->es_snapshot = SnapshotNow;
+	estate->es_snapshot_cid = FirstCommandId;
 	estate->es_range_table = NIL;
 
 	estate->es_result_relations = NULL;
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 28276adc94d7cadaf108da3c29363b681872f28f..048a2609d7104a5882ee7f1dda146f17659c75ad 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.74 2003/09/25 06:57:59 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.75 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -291,7 +291,7 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
 
 	/* Utility commands don't need Executor. */
 	if (es->qd->operation != CMD_UTILITY)
-		ExecutorStart(es->qd, false);
+		ExecutorStart(es->qd, false, false);
 
 	es->status = F_EXEC_RUN;
 }
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index f1b96ee5d813fd0e12307dd69e3f1cbb03b0efd6..488a37b24d3f539190d94dc61e4184977dec0440 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.56 2003/09/25 06:57:59 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.57 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -709,6 +709,7 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
 	sp_estate->es_tupleTable =
 		ExecCreateTupleTable(ExecCountSlotsNode(subplan->plan) + 10);
 	sp_estate->es_snapshot = estate->es_snapshot;
+	sp_estate->es_snapshot_cid = estate->es_snapshot_cid;
 	sp_estate->es_instrument = estate->es_instrument;
 
 	/*
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index 34d9d0c62ff3de5686b0022f24b2cc68cabbb1fc..f8d2640349f81e829b4d104c6578e05ef2220098 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.20 2003/08/04 02:39:59 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.21 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -177,6 +177,7 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
 	sp_estate->es_tupleTable =
 		ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
 	sp_estate->es_snapshot = estate->es_snapshot;
+	sp_estate->es_snapshot_cid = estate->es_snapshot_cid;
 	sp_estate->es_instrument = estate->es_instrument;
 
 	/*
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index d2b07d484ac66f1034fe514df1ee5b7b12a71661..2626b728e94131c35156e8bcdf3f1ff88bf7009c 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.105 2003/09/23 15:11:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.106 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,10 +32,12 @@ static int	_SPI_connected = -1;
 static int	_SPI_curid = -1;
 
 static int	_SPI_execute(const char *src, int tcount, _SPI_plan *plan);
-static int	_SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount);
+static int	_SPI_pquery(QueryDesc *queryDesc, bool runit,
+						bool useSnapshotNow, int tcount);
 
 static int _SPI_execute_plan(_SPI_plan *plan,
-				  Datum *Values, const char *Nulls, int tcount);
+							 Datum *Values, const char *Nulls,
+							 bool useSnapshotNow, int tcount);
 
 static void _SPI_cursor_operation(Portal portal, bool forward, int count,
 					  DestReceiver *dest);
@@ -236,7 +238,33 @@ SPI_execp(void *plan, Datum *Values, const char *Nulls, int tcount)
 	if (res < 0)
 		return res;
 
-	res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, tcount);
+	res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, false, tcount);
+
+	_SPI_end_call(true);
+	return res;
+}
+
+/*
+ * SPI_execp_now -- identical to SPI_execp, except that we use SnapshotNow
+ * instead of the normal QuerySnapshot.  This is currently not documented
+ * in spi.sgml because it is only intended for use by RI triggers.
+ */
+int
+SPI_execp_now(void *plan, Datum *Values, const char *Nulls, int tcount)
+{
+	int			res;
+
+	if (plan == NULL || tcount < 0)
+		return SPI_ERROR_ARGUMENT;
+
+	if (((_SPI_plan *) plan)->nargs > 0 && Values == NULL)
+		return SPI_ERROR_PARAM;
+
+	res = _SPI_begin_call(true);
+	if (res < 0)
+		return res;
+
+	res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, true, tcount);
 
 	_SPI_end_call(true);
 	return res;
@@ -1068,7 +1096,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
 			{
 				qdesc = CreateQueryDesc(queryTree, planTree, dest,
 										NULL, false);
-				res = _SPI_pquery(qdesc, true,
+				res = _SPI_pquery(qdesc, true, false,
 								  queryTree->canSetTag ? tcount : 0);
 				if (res < 0)
 					return res;
@@ -1078,7 +1106,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
 			{
 				qdesc = CreateQueryDesc(queryTree, planTree, dest,
 										NULL, false);
-				res = _SPI_pquery(qdesc, false, 0);
+				res = _SPI_pquery(qdesc, false, false, 0);
 				if (res < 0)
 					return res;
 			}
@@ -1096,7 +1124,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
 
 static int
 _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
-				  int tcount)
+				  bool useSnapshotNow, int tcount)
 {
 	List	   *query_list_list = plan->qtlist;
 	List	   *plan_list = plan->ptlist;
@@ -1167,7 +1195,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
 			{
 				qdesc = CreateQueryDesc(queryTree, planTree, dest,
 										paramLI, false);
-				res = _SPI_pquery(qdesc, true,
+				res = _SPI_pquery(qdesc, true, useSnapshotNow,
 								  queryTree->canSetTag ? tcount : 0);
 				if (res < 0)
 					return res;
@@ -1180,7 +1208,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
 }
 
 static int
-_SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
+_SPI_pquery(QueryDesc *queryDesc, bool runit, bool useSnapshotNow, int tcount)
 {
 	int			operation = queryDesc->operation;
 	int			res;
@@ -1217,7 +1245,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
 		ResetUsage();
 #endif
 
-	ExecutorStart(queryDesc, false);
+	ExecutorStart(queryDesc, useSnapshotNow, false);
 
 	ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
 
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 83dd0d54d8d83934dced908a3ad248b4f3185d1f..22cb49f973b2f35ca7ba7f60f1cc7946758b5572 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.72 2003/08/12 18:23:21 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.73 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -131,7 +131,7 @@ ProcessQuery(Query *parsetree,
 	/*
 	 * Call ExecStart to prepare the plan for execution
 	 */
-	ExecutorStart(queryDesc, false);
+	ExecutorStart(queryDesc, false, false);
 
 	/*
 	 * Run the plan to completion.
@@ -269,7 +269,7 @@ PortalStart(Portal portal, ParamListInfo params)
 			/*
 			 * Call ExecStart to prepare the plan for execution
 			 */
-			ExecutorStart(queryDesc, false);
+			ExecutorStart(queryDesc, false, false);
 
 			/*
 			 * This tells PortalCleanup to shut down the executor
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 877034519c195e8a4fa72dd165c6a06edbe6e42a..6250995e1b81ca160ae513c1f9e1e085a2c87dda 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -17,7 +17,7 @@
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.57 2003/09/25 06:58:04 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.58 2003/09/25 18:58:35 tgl Exp $
  *
  * ----------
  */
@@ -187,8 +187,6 @@ RI_FKey_check(PG_FUNCTION_ARGS)
 	int			i;
 	int			match_type;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -627,8 +625,6 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
 	int			i;
 	int			match_type;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -807,8 +803,6 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
 	int			i;
 	int			match_type;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -995,8 +989,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
 	void	   *qplan;
 	int			i;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -1159,8 +1151,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
 	int			i;
 	int			j;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -1349,8 +1339,6 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
 	void	   *qplan;
 	int			i;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -1520,8 +1508,6 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
 	void	   *qplan;
 	int			i;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -1694,8 +1680,6 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
 	void	   *qplan;
 	int			i;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -1868,8 +1852,6 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
 	int			match_type;
 	bool		use_cached_query;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -2083,8 +2065,6 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
 	RI_QueryKey qkey;
 	void	   *qplan;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -2296,8 +2276,6 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
 	void	   *qplan;
 	int			match_type;
 
-	ReferentialIntegritySnapshotOverride = true;
-
 	/*
 	 * Check that this is a valid trigger call on the right time and
 	 * event.
@@ -2936,15 +2914,19 @@ ri_PerformCheck(RI_QueryKey *qkey, void *qplan,
 	 */
 	limit = (expect_OK == SPI_OK_SELECT) ? 1 : 0;
 
-	/* Run the plan */
-	spi_result = SPI_execp(qplan, vals, nulls, limit);
+	/*
+	 * Run the plan, using SnapshotNow time qual rules so that we can see
+	 * all committed tuples, even those committed after our own transaction
+	 * or query started.
+	 */
+	spi_result = SPI_execp_now(qplan, vals, nulls, limit);
 
 	/* Restore UID */
 	SetUserId(save_uid);
 
 	/* Check result */
 	if (spi_result < 0)
-		elog(ERROR, "SPI_execp failed");
+		elog(ERROR, "SPI_execp_now returned %d", spi_result);
 
 	if (expect_OK >= 0 && spi_result != expect_OK)
 		ri_ReportViolation(qkey, constrname ? constrname : "",
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index 6a1ab38d14adedef20d67920aedf2536f7dadbb6..5b594fcf6801057ca804db83b47da20b41d41942 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.68 2003/09/22 00:47:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.69 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,8 +39,6 @@ Snapshot	SerializableSnapshot = NULL;
 TransactionId RecentXmin = InvalidTransactionId;
 TransactionId RecentGlobalXmin = InvalidTransactionId;
 
-bool		ReferentialIntegritySnapshotOverride = false;
-
 
 /*
  * HeapTupleSatisfiesItself
@@ -665,10 +663,6 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
 bool
 HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
 {
-	/* XXX this is horribly ugly: */
-	if (ReferentialIntegritySnapshotOverride)
-		return HeapTupleSatisfiesNow(tuple);
-
 	if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
 	{
 		if (tuple->t_infomask & HEAP_XMIN_INVALID)
@@ -978,9 +972,6 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
 void
 SetQuerySnapshot(void)
 {
-	/* Initialize snapshot overriding to false */
-	ReferentialIntegritySnapshotOverride = false;
-
 	/* 1st call in xaction? */
 	if (SerializableSnapshot == NULL)
 	{
diff --git a/src/include/access/valid.h b/src/include/access/valid.h
index c1b8f02127b1cce3b9ba4c1819b7673e7fa51791..3109d3e7e4d9374dc286b449d8d0603cc5b87ec8 100644
--- a/src/include/access/valid.h
+++ b/src/include/access/valid.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: valid.h,v 1.30 2003/08/04 02:40:10 momjian Exp $
+ * $Id: valid.h,v 1.31 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -93,7 +93,7 @@ do \
 						   relation, \
 						   buffer, \
 						   disk_page, \
-						   seeself, \
+						   snapshot, \
 						   nKeys, \
 						   key, \
 						   res) \
@@ -112,7 +112,7 @@ do \
 		{ \
 			uint16	_infomask = (tuple)->t_data->t_infomask; \
 			\
-			(res) = HeapTupleSatisfiesVisibility((tuple), (seeself)); \
+			(res) = HeapTupleSatisfiesVisibility((tuple), (snapshot)); \
 			if ((tuple)->t_data->t_infomask != _infomask) \
 				SetBufferCommitInfoNeedsSave(buffer); \
 		} \
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 88449034feec56d90ff0c0294c8443fab3c9b6e8..034494b844fd9594104e0e6bbdf4d0b84f9ae0fe 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: executor.h,v 1.100 2003/08/19 01:13:41 tgl Exp $
+ * $Id: executor.h,v 1.101 2003/09/25 18:58:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -85,7 +85,8 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
 /*
  * prototypes from functions in execMain.c
  */
-extern void ExecutorStart(QueryDesc *queryDesc, bool explainOnly);
+extern void ExecutorStart(QueryDesc *queryDesc, bool useSnapshotNow,
+						  bool explainOnly);
 extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
 			ScanDirection direction, long count);
 extern void ExecutorEnd(QueryDesc *queryDesc);
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index c7366c1af555675ec8f8849444f44d05e770f30d..800616b56b6657151f908a3da634f67b98358c80 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -2,7 +2,7 @@
  *
  * spi.h
  *
- * $Id: spi.h,v 1.37 2003/08/04 00:43:31 momjian Exp $
+ * $Id: spi.h,v 1.38 2003/09/25 18:58:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -84,6 +84,8 @@ extern void SPI_pop(void);
 extern int	SPI_exec(const char *src, int tcount);
 extern int SPI_execp(void *plan, Datum *values, const char *Nulls,
 		  int tcount);
+extern int SPI_execp_now(void *plan, Datum *values, const char *Nulls,
+		  int tcount);
 extern void *SPI_prepare(const char *src, int nargs, Oid *argtypes);
 extern void *SPI_saveplan(void *plan);
 extern int	SPI_freeplan(void *plan);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 97609f583857be569ef7dc6865e255e37bd09ce2..b40df71776592cae474a44cb5a8631ed654eafd2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: execnodes.h,v 1.105 2003/08/22 20:26:43 tgl Exp $
+ * $Id: execnodes.h,v 1.106 2003/09/25 18:58:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -286,6 +286,7 @@ typedef struct EState
 	/* Basic state for all query types: */
 	ScanDirection es_direction; /* current scan direction */
 	Snapshot	es_snapshot;	/* time qual to use */
+	CommandId	es_snapshot_cid;	/* CommandId component of time qual */
 	List	   *es_range_table; /* List of RangeTableEntrys */
 
 	/* Info about target table for insert/update/delete queries: */
diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h
index c99d37953053d133afc5db243aa62b3fbc681f59..0c9f10f368cd190082a0858dfe88743a7db2dd1d 100644
--- a/src/include/utils/tqual.h
+++ b/src/include/utils/tqual.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tqual.h,v 1.46 2003/08/04 02:40:15 momjian Exp $
+ * $Id: tqual.h,v 1.47 2003/09/25 18:58:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,14 +44,6 @@ extern DLLIMPORT Snapshot SerializableSnapshot;
 extern TransactionId RecentXmin;
 extern TransactionId RecentGlobalXmin;
 
-extern bool ReferentialIntegritySnapshotOverride;
-
-#define IsSnapshotNow(snapshot)		((Snapshot) (snapshot) == SnapshotNow)
-#define IsSnapshotSelf(snapshot)	((Snapshot) (snapshot) == SnapshotSelf)
-#define IsSnapshotAny(snapshot)		((Snapshot) (snapshot) == SnapshotAny)
-#define IsSnapshotToast(snapshot)	((Snapshot) (snapshot) == SnapshotToast)
-#define IsSnapshotDirty(snapshot)	((Snapshot) (snapshot) == SnapshotDirty)
-
 
 /*
  * HeapTupleSatisfiesVisibility
@@ -62,19 +54,19 @@ extern bool ReferentialIntegritySnapshotOverride;
  *		Beware of multiple evaluations of snapshot argument.
  */
 #define HeapTupleSatisfiesVisibility(tuple, snapshot) \
-(IsSnapshotNow(snapshot) ? \
+((snapshot) == SnapshotNow ? \
 	HeapTupleSatisfiesNow((tuple)->t_data) \
 : \
-	(IsSnapshotSelf(snapshot) ? \
+	((snapshot) == SnapshotSelf ? \
 		HeapTupleSatisfiesItself((tuple)->t_data) \
 	: \
-		(IsSnapshotAny(snapshot) ? \
+		((snapshot) == SnapshotAny ? \
 			true \
 		: \
-			(IsSnapshotToast(snapshot) ? \
+			((snapshot) == SnapshotToast ? \
 				HeapTupleSatisfiesToast((tuple)->t_data) \
 			: \
-				(IsSnapshotDirty(snapshot) ? \
+				((snapshot) == SnapshotDirty ? \
 					HeapTupleSatisfiesDirty((tuple)->t_data) \
 				: \
 					HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \