diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index c1633ecd8346db393988a6d8eb7c14e4719dbfd2..6557335d994b0bd8dfb3695d3a518556dc2e7caf 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.40 2000/01/26 05:56:11 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.41 2000/04/04 21:44:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,7 +61,6 @@ ProcedureCreate(char *procedureName,
 	Oid			typeObjectId;
 	List	   *x;
 	List	   *querytree_list;
-	List	   *plan_list;
 	Oid			typev[FUNC_MAX_ARGS];
 	Oid			relid;
 	Oid			toid;
@@ -222,9 +221,8 @@ ProcedureCreate(char *procedureName,
 
 	if (strcmp(languageName, "sql") == 0)
 	{
-		plan_list = pg_parse_and_plan(prosrc, typev, parameterCount,
-									  &querytree_list, dest, FALSE);
-
+		querytree_list = pg_parse_and_rewrite(prosrc, typev, parameterCount,
+											  FALSE);
 		/* typecheck return value */
 		pg_checkretval(typeObjectId, querytree_list);
 	}
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 5a7f4c0889fb72aae4ff3b8b1781e594c9f73c80..3854978029b2393a7f5c1f0f3b59d905164c027d 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.31 2000/01/26 05:56:22 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.32 2000/04/04 21:44:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -84,7 +84,6 @@ init_execution_state(FunctionCachePtr fcache,
 	execution_state *nextes;
 	execution_state *preves;
 	List	   *queryTree_list,
-			   *planTree_list,
 			   *qtl_item;
 	int			nargs = fcache->nargs;
 
@@ -92,15 +91,17 @@ init_execution_state(FunctionCachePtr fcache,
 	nextes = newes;
 	preves = (execution_state *) NULL;
 
-	planTree_list = pg_parse_and_plan(fcache->src, fcache->argOidVect,
-									nargs, &queryTree_list, None, FALSE);
+	queryTree_list = pg_parse_and_rewrite(fcache->src, fcache->argOidVect,
+										  nargs, FALSE);
 
 	foreach(qtl_item, queryTree_list)
 	{
 		Query	   *queryTree = lfirst(qtl_item);
-		Plan	   *planTree = lfirst(planTree_list);
+		Plan	   *planTree;
 		EState	   *estate;
 
+		planTree = pg_plan_query(queryTree);
+
 		if (!nextes)
 			nextes = (execution_state *) palloc(sizeof(execution_state));
 		if (preves)
@@ -141,8 +142,6 @@ init_execution_state(FunctionCachePtr fcache,
 		nextes->estate = estate;
 		preves = nextes;
 		nextes = (execution_state *) NULL;
-
-		planTree_list = lnext(planTree_list);
 	}
 
 	return newes;
@@ -151,15 +150,12 @@ init_execution_state(FunctionCachePtr fcache,
 static TupleDesc
 postquel_start(execution_state *es)
 {
-#ifdef FUNC_UTIL_PATCH
-
 	/*
 	 * Do nothing for utility commands. (create, destroy...)  DZ -
 	 * 30-8-1996
 	 */
 	if (es->qd->operation == CMD_UTILITY)
 		return (TupleDesc) NULL;
-#endif
 	return ExecutorStart(es->qd, es->estate);
 }
 
@@ -168,12 +164,10 @@ postquel_getnext(execution_state *es)
 {
 	int			feature;
 
-#ifdef FUNC_UTIL_PATCH
 	if (es->qd->operation == CMD_UTILITY)
 	{
-
 		/*
-		 * Process an utility command. (create, destroy...)  DZ -
+		 * Process a utility command. (create, destroy...)  DZ -
 		 * 30-8-1996
 		 */
 		ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->dest);
@@ -181,7 +175,6 @@ postquel_getnext(execution_state *es)
 			CommandCounterIncrement();
 		return (TupleTableSlot *) NULL;
 	}
-#endif
 
 	feature = (LAST_POSTQUEL_COMMAND(es)) ? EXEC_RETONE : EXEC_RUN;
 
@@ -191,15 +184,12 @@ postquel_getnext(execution_state *es)
 static void
 postquel_end(execution_state *es)
 {
-#ifdef FUNC_UTIL_PATCH
-
 	/*
 	 * Do nothing for utility commands. (create, destroy...)  DZ -
 	 * 30-8-1996
 	 */
 	if (es->qd->operation == CMD_UTILITY)
 		return;
-#endif
 	ExecutorEnd(es->qd, es->estate);
 }
 
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 7c65c66814f863bdaa590c88af77936c27d0e3ea..016d15ae8ac56a0c6a4b38aeda401240ed7160d2 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -3,7 +3,7 @@
  * spi.c
  *				Server Programming Interface
  *
- * $Id: spi.c,v 1.44 1999/12/16 22:19:44 wieck Exp $
+ * $Id: spi.c,v 1.45 2000/04/04 21:44:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -622,7 +622,6 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
 	List	   *queryTree_list;
 	List	   *planTree_list;
 	List	   *queryTree_list_item;
-	List	   *ptlist;
 	QueryDesc  *qdesc;
 	Query	   *queryTree;
 	Plan	   *planTree;
@@ -645,18 +644,20 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
 		nargs = plan->nargs;
 		argtypes = plan->argtypes;
 	}
-	ptlist = planTree_list =
-		pg_parse_and_plan(src, argtypes, nargs, &queryTree_list, None, FALSE);
+
+	queryTree_list = pg_parse_and_rewrite(src, argtypes, nargs, FALSE);
 
 	_SPI_current->qtlist = queryTree_list;
 
+	planTree_list = NIL;
+
 	foreach(queryTree_list_item, queryTree_list)
 	{
 		queryTree = (Query *) lfirst(queryTree_list_item);
-		planTree = lfirst(planTree_list);
-		planTree_list = lnext(planTree_list);
-		islastquery = (planTree_list == NIL);	/* assume lists are same
-												 * len */
+		islastquery = (lnext(queryTree_list_item) == NIL);
+
+		planTree = pg_plan_query(queryTree);
+		planTree_list = lappend(planTree_list, planTree);
 
 		if (queryTree->commandType == CMD_UTILITY)
 		{
@@ -707,7 +708,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
 	}
 
 	plan->qtlist = queryTree_list;
-	plan->ptlist = ptlist;
+	plan->ptlist = planTree_list;
 
 	return res;
 }
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index a70418637f729ae4c2225996a2591893155f2485..65b6bfbd6c0016036ea44629b694b7097261d0bc 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.148 2000/03/23 23:16:48 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.149 2000/04/04 21:44:39 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -377,22 +377,23 @@ ReadCommand(StringInfo inBuf)
 	return result;
 }
 
+
+/*
+ * Parse a query string and pass it through the rewriter.
+ *
+ * A list of Query nodes is returned, since the string might contain
+ * multiple queries and/or the rewriter might expand one query to several.
+ */
 List *
-pg_parse_and_plan(char *query_string,	/* string to execute */
-				  Oid *typev,	/* argument types */
-				  int nargs,	/* number of arguments */
-				  List **queryListP,	/* returned pointer to the parse
-										 * trees */
-				  CommandDest dest,		/* where results should go */
-				  bool aclOverride)
+pg_parse_and_rewrite(char *query_string,	/* string to execute */
+					 Oid *typev,			/* argument types */
+					 int nargs,				/* number of arguments */
+					 bool aclOverride)
 {
-	List	   *querytree_list = NIL;
-	List	   *plan_list = NIL;
+	List	   *querytree_list;
 	List	   *querytree_list_item;
 	Query	   *querytree;
-	Plan	   *plan;
 	List	   *new_list;
-	List	   *rewritten;
 
 	if (DebugPrintQuery)
 	{
@@ -448,15 +449,16 @@ pg_parse_and_plan(char *query_string,	/* string to execute */
 		else
 		{
 			/* rewrite regular queries */
-			rewritten = QueryRewrite(querytree);
+			List *rewritten = QueryRewrite(querytree);
 			new_list = nconc(new_list, rewritten);
 		}
 	}
 
 	querytree_list = new_list;
 
-	/*
-	 * Override ACL checking if requested
+	/* ----------------
+	 *	(3) If ACL override is requested, mark queries for no ACL check.
+	 * ----------------
 	 */
 	if (aclOverride)
 	{
@@ -503,87 +505,54 @@ pg_parse_and_plan(char *query_string,	/* string to execute */
 		}
 	}
 
-	foreach(querytree_list_item, querytree_list)
-	{
-		querytree = (Query *) lfirst(querytree_list_item);
-
-		/*
-		 * For each query that isn't a utility invocation, generate a
-		 * plan.
-		 */
-
-		if (querytree->commandType != CMD_UTILITY)
-		{
+	return querytree_list;
+}
 
-			if (IsAbortedTransactionBlockState())
-			{
-				/* ----------------
-				 *	 the EndCommand() stuff is to tell the frontend
-				 *	 that the command ended. -cim 6/1/90
-				 * ----------------
-				 */
-				char	   *tag = "*ABORT STATE*";
 
-				EndCommand(tag, dest);
+/* Generate a plan for a single query. */
+Plan *
+pg_plan_query(Query *querytree)
+{
+	Plan	   *plan;
 
-				elog(NOTICE, "(transaction aborted): %s",
-					 "queries ignored until END");
+	/* Utility commands have no plans. */
+	if (querytree->commandType == CMD_UTILITY)
+		return NULL;
 
-				if (queryListP)
-					*queryListP = NIL;
-				return NIL;
-			}
+	if (ShowPlannerStats)
+		ResetUsage();
 
-			if (ShowPlannerStats)
-				ResetUsage();
+	/* call that optimizer */
+	plan = planner(querytree);
 
-			/* call that optimizer */
-			plan = planner(querytree);
+	if (ShowPlannerStats)
+	{
+		fprintf(stderr, "! Planner Stats:\n");
+		ShowUsage();
+	}
 
-			if (ShowPlannerStats)
-			{
-				fprintf(stderr, "! Planner Stats:\n");
-				ShowUsage();
-			}
-			plan_list = lappend(plan_list, plan);
-#ifdef INDEXSCAN_PATCH
-			/* ----------------
-			 *	Print plan if debugging.
-			 *	This has been moved here to get debugging output
-			 *	also for queries in functions.	DZ - 27-8-1996
-			 * ----------------
-			 */
-			if (DebugPrintPlan || DebugPPrintPlan)
-			{
-				if (DebugPPrintPlan)
-				{
-					TPRINTF(TRACE_PRETTY_PLAN, "plan:");
-					nodeDisplay(plan);
-				}
-				else
-				{
-					TPRINTF(TRACE_PLAN, "plan:");
-					printf("\n%s\n\n", nodeToString(plan));
-				}
-			}
-#endif
+	/* ----------------
+	 *	Print plan if debugging.
+	 * ----------------
+	 */
+	if (DebugPrintPlan || DebugPPrintPlan)
+	{
+		if (DebugPPrintPlan)
+		{
+			TPRINTF(TRACE_PRETTY_PLAN, "plan:");
+			nodeDisplay(plan);
 		}
-
-		/*
-		 * If the command is an utility append a null plan. This is needed
-		 * to keep the plan_list aligned with the querytree_list or the
-		 * function executor will crash.  DZ - 30-8-1996
-		 */
 		else
-			plan_list = lappend(plan_list, NULL);
+		{
+			TPRINTF(TRACE_PLAN, "plan:");
+			printf("\n%s\n\n", nodeToString(plan));
+		}
 	}
 
-	if (queryListP)
-		*queryListP = querytree_list;
-
-	return plan_list;
+	return plan;
 }
 
+
 /* ----------------------------------------------------------------
  *		pg_exec_query()
  *
@@ -620,39 +589,31 @@ pg_exec_query_dest(char *query_string,	/* string to execute */
 										 * of superusers */
 {
 	List	   *querytree_list;
-	List	   *plan_list;
-	Query	   *querytree;
-	Plan	   *plan;
-	int			j;
 
-	/* plan the queries */
-	plan_list = pg_parse_and_plan(query_string, NULL, 0,
-								  &querytree_list, dest, aclOverride);
-
-	/* if we got a cancel signal whilst planning, quit */
-	if (QueryCancel)
-		CancelQuery();
-
-	/* OK, do it to it! */
+	/* parse and rewrite the queries */
+	querytree_list = pg_parse_and_rewrite(query_string, NULL, 0,
+										  aclOverride);
 
 	/*
 	 * NOTE: we do not use "foreach" here because we want to be sure the
-	 * list pointers have been advanced before the query is executed. We
+	 * list pointer has been advanced before the query is executed. We
 	 * need to do that because VACUUM has a nasty little habit of doing
 	 * CommitTransactionCommand at startup, and that will release the
-	 * memory holding our parse/plan lists :-(.  This needs a better
+	 * memory holding our parse list :-(.  This needs a better
 	 * solution --- currently, the code will crash if someone submits
 	 * "vacuum; something-else" in a single query string.  But memory
 	 * allocation needs redesigned anyway, so this will have to do for
 	 * now.
 	 */
-
 	while (querytree_list)
 	{
-		querytree = (Query *) lfirst(querytree_list);
+		Query	   *querytree = (Query *) lfirst(querytree_list);
+
 		querytree_list = lnext(querytree_list);
-		plan = (Plan *) lfirst(plan_list);
-		plan_list = lnext(plan_list);
+
+		/* if we got a cancel signal in parsing or prior command, quit */
+		if (QueryCancel)
+			CancelQuery();
 
 		if (querytree->commandType == CMD_UTILITY)
 		{
@@ -668,42 +629,38 @@ pg_exec_query_dest(char *query_string,	/* string to execute */
 			else if (Verbose)
 				TPRINTF(TRACE_VERBOSE, "ProcessUtility");
 
-			/*
-			 * We have to set query SnapShot in the case of FETCH or COPY TO.
-			 */
-			if (nodeTag(querytree->utilityStmt) == T_FetchStmt ||
-				(nodeTag(querytree->utilityStmt) == T_CopyStmt && 
-				((CopyStmt *)(querytree->utilityStmt))->direction != FROM))
-				SetQuerySnapshot();
 			ProcessUtility(querytree->utilityStmt, dest);
 		}
 		else
 		{
-#ifdef INDEXSCAN_PATCH
+			Plan	   *plan;
+			int			j;
 
-			/*
-			 * Print moved in pg_parse_and_plan.	DZ - 27-8-1996
-			 */
-#else
-			/* ----------------
-			 *	print plan if debugging
-			 * ----------------
-			 */
-			if (DebugPrintPlan || DebugPPrintPlan)
+			/* If aborted transaction, quit now */
+			if (IsAbortedTransactionBlockState())
 			{
-				if (DebugPPrintPlan)
-				{
-					TPRINTF(TRACE_PRETTY_PLAN, "plan:");
-					nodeDisplay(plan);
-				}
-				else
-				{
-					TPRINTF(TRACE_PLAN, "plan:");
-					printf("\n%s\n\n", nodeToString(plan));
-				}
+				/* ----------------
+				 *	 the EndCommand() stuff is to tell the frontend
+				 *	 that the command ended. -cim 6/1/90
+				 * ----------------
+				 */
+				char	   *tag = "*ABORT STATE*";
+
+				elog(NOTICE, "current transaction is aborted, "
+					 "queries ignored until end of transaction block");
+
+				EndCommand(tag, dest);
+
+				break;
 			}
-#endif
 
+			plan = pg_plan_query(querytree);
+
+			/* if we got a cancel signal whilst planning, quit */
+			if (QueryCancel)
+				CancelQuery();
+
+			/* Initialize snapshot state for query */
 			SetQuerySnapshot();
 
 			/*
@@ -1505,7 +1462,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.148 $ $Date: 2000/03/23 23:16:48 $\n");
+		puts("$Revision: 1.149 $ $Date: 2000/04/04 21:44:39 $\n");
 	}
 
 	/*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 62ad6d8f9571bd780b49c74ecfd8009857c68f28..d3ba5b319dd7a8072726d61ba698eb1bb02b20bd 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.84 2000/02/19 02:29:07 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.85 2000/04/04 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -136,6 +136,8 @@ ProcessUtility(Node *parsetree,
 				PS_SET_STATUS(commandTag = (stmt->ismove) ? "MOVE" : "FETCH");
 				CHECK_IF_ABORTED();
 
+				SetQuerySnapshot();
+
 				forward = (bool) (stmt->direction == FORWARD);
 
 				/*
@@ -255,6 +257,9 @@ ProcessUtility(Node *parsetree,
 				PS_SET_STATUS(commandTag = "COPY");
 				CHECK_IF_ABORTED();
 
+				if (stmt->direction != FROM)
+					SetQuerySnapshot();
+
 				DoCopy(stmt->relname,
 					   stmt->binary,
 					   stmt->oids,
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 283e517ccce18d726f88cbc183a90501d56a4500..8255770068fe80e73c0ff6b78b758b2ff354fdc4 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tcopprot.h,v 1.25 2000/02/20 14:28:28 petere Exp $
+ * $Id: tcopprot.h,v 1.26 2000/04/04 21:44:37 tgl Exp $
  *
  * OLD COMMENTS
  *	  This file was created so that other c files could get the two
@@ -29,12 +29,15 @@ extern bool InError;
 extern bool	ExitAfterAbort;
 
 #ifndef BOOTSTRAP_INCLUDE
-extern List *pg_parse_and_plan(char *query_string, Oid *typev, int nargs,
-				  List **queryListP, CommandDest dest,
-				  bool aclOverride);
+
+extern List *pg_parse_and_rewrite(char *query_string,
+								  Oid *typev, int nargs,
+								  bool aclOverride);
+extern Plan *pg_plan_query(Query *querytree);
 extern void pg_exec_query_acl_override(char *query_string);
-extern void
-			pg_exec_query_dest(char *query_string, CommandDest dest, bool aclOverride);
+extern void pg_exec_query_dest(char *query_string,
+							   CommandDest dest,
+							   bool aclOverride);
 
 #endif	 /* BOOTSTRAP_INCLUDE */