diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 83ca5b32c5439fea5ed981060caeb0aed3360df5..16c23d320ee4e3d98ec559c1dd56a309cb39e081 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.155 2002/05/21 22:05:54 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.156 2002/05/21 22:59:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -447,6 +447,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
 	bool	   *isvarlena;
 	int16		fld_size;
 	char	   *string;
+	Snapshot	mySnapshot;
 
 	if (oids && !rel->rd_rel->relhasoids)
 		elog(ERROR, "COPY: table %s does not have OIDs",
@@ -494,7 +495,9 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
 		CopySendData(&tmp, sizeof(int32), fp);
 	}
 
-	scandesc = heap_beginscan(rel, QuerySnapshot, 0, NULL);
+	mySnapshot = CopyQuerySnapshot();
+
+	scandesc = heap_beginscan(rel, mySnapshot, 0, NULL);
 
 	while ((tuple = heap_getnext(scandesc, ForwardScanDirection)) != NULL)
 	{
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index a8c776bab2c4a89b145ef3721933b3851fd34463..29687a54baa2a9744e1a3f78b2c7bf02256142c6 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.162 2002/05/21 22:05:55 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.163 2002/05/21 22:59:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -101,7 +101,6 @@ TupleDesc
 ExecutorStart(QueryDesc *queryDesc, EState *estate)
 {
 	TupleDesc	result;
-	Snapshot	es_snapshot;
 
 	/* sanity checks */
 	Assert(queryDesc != NULL);
@@ -121,22 +120,7 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
 	 * for the life of this query, even if it outlives the current command
 	 * and current snapshot.
 	 */
-	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)
-	{
-		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;
+	estate->es_snapshot = CopyQuerySnapshot();
 
 	/*
 	 * Initialize the plan
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index 58534159f7a95d17e408354e4f7a53725fc20f24..582ec28183ee058c68227f45fb317648ada89203 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.51 2002/05/21 22:05:55 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.52 2002/05/21 22:59:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -963,6 +963,40 @@ SetQuerySnapshot(void)
 	Assert(QuerySnapshot != NULL);
 }
 
+/*
+ * CopyQuerySnapshot
+ *		Copy the current query snapshot.
+ *
+ * Copying the snapshot is done so that a query is guaranteed to use a
+ * consistent snapshot for its entire execution life, even if the command
+ * counter is incremented or SetQuerySnapshot() is called while it runs
+ * (as could easily happen, due to triggers etc. executing queries).
+ *
+ * The copy is palloc'd in the current memory context.
+ */
+Snapshot
+CopyQuerySnapshot(void)
+{
+	Snapshot	snapshot;
+
+	if (QuerySnapshot == NULL)	/* should be set already, but... */
+		SetQuerySnapshot();
+
+	snapshot = (Snapshot) palloc(sizeof(SnapshotData));
+	memcpy(snapshot, QuerySnapshot, sizeof(SnapshotData));
+	if (snapshot->xcnt > 0)
+	{
+		snapshot->xip = (TransactionId *)
+			palloc(snapshot->xcnt * sizeof(TransactionId));
+		memcpy(snapshot->xip, QuerySnapshot->xip,
+			   snapshot->xcnt * sizeof(TransactionId));
+	}
+	else
+		snapshot->xip = NULL;
+
+	return snapshot;
+}
+
 /*
  * FreeXactSnapshot
  *		Free snapshot(s) at end of transaction.
diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h
index f5f03ea01af737c978ee3708cd1b1ac665fb2bfd..3ddceff5f8db1d4f24c1563cb22fb70031ac90ef 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.39 2002/05/21 22:05:55 tgl Exp $
+ * $Id: tqual.h,v 1.40 2002/05/21 22:59:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -112,6 +112,7 @@ extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
 
 extern Snapshot GetSnapshotData(bool serializable);
 extern void SetQuerySnapshot(void);
+extern Snapshot CopyQuerySnapshot(void);
 extern void FreeXactSnapshot(void);
 
 #endif   /* TQUAL_H */