From 1dd56fdae41367ca0fdef5c14849a7e755a8ed32 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 12 Mar 2008 23:58:35 +0000
Subject: [PATCH] Fix pg_plan_queries() to restore the previous setting of
 ActiveSnapshot (probably NULL) before exiting.  Up to now it's just left the
 variable as it set it, which means that after we're done processing the
 current client message, ActiveSnapshot is probably pointing at garbage
 (because this function is typically run in MessageContext which will get
 reset).  There doesn't seem to have been any code path in which that mattered
 before 8.3, but now the plancache module might try to use the stale value if
 the next client message is a Bind for a prepared statement that is in need of
 replanning.  Per report from Alex Hunsaker.

---
 src/backend/tcop/postgres.c | 52 +++++++++++++++++++++++++------------
 1 file changed, 35 insertions(+), 17 deletions(-)

diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 325411df09..a6afecaba6 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.542 2008/01/26 19:55:08 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.542.2.1 2008/03/12 23:58:35 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -729,31 +729,49 @@ List *
 pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams,
 				bool needSnapshot)
 {
-	List	   *stmt_list = NIL;
-	ListCell   *query_list;
+	List	   * volatile stmt_list = NIL;
+	Snapshot	saveActiveSnapshot = ActiveSnapshot;
 
-	foreach(query_list, querytrees)
+	/* PG_TRY to ensure previous ActiveSnapshot is restored on error */
+	PG_TRY();
 	{
-		Query	   *query = (Query *) lfirst(query_list);
-		Node	   *stmt;
+		Snapshot	mySnapshot = NULL;
+		ListCell   *query_list;
 
-		if (query->commandType == CMD_UTILITY)
+		foreach(query_list, querytrees)
 		{
-			/* Utility commands have no plans. */
-			stmt = query->utilityStmt;
-		}
-		else
-		{
-			if (needSnapshot)
+			Query	   *query = (Query *) lfirst(query_list);
+			Node	   *stmt;
+
+			if (query->commandType == CMD_UTILITY)
+			{
+				/* Utility commands have no plans. */
+				stmt = query->utilityStmt;
+			}
+			else
 			{
-				ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
-				needSnapshot = false;
+				if (needSnapshot && mySnapshot == NULL)
+				{
+					mySnapshot = CopySnapshot(GetTransactionSnapshot());
+					ActiveSnapshot = mySnapshot;
+				}
+				stmt = (Node *) pg_plan_query(query, cursorOptions,
+											  boundParams);
 			}
-			stmt = (Node *) pg_plan_query(query, cursorOptions, boundParams);
+
+			stmt_list = lappend(stmt_list, stmt);
 		}
 
-		stmt_list = lappend(stmt_list, stmt);
+		if (mySnapshot)
+			FreeSnapshot(mySnapshot);
+	}
+	PG_CATCH();
+	{
+		ActiveSnapshot = saveActiveSnapshot;
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
+	ActiveSnapshot = saveActiveSnapshot;
 
 	return stmt_list;
 }
-- 
2.50.1