aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-03-12 23:58:35 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-03-12 23:58:35 +0000
commit1dd56fdae41367ca0fdef5c14849a7e755a8ed32 (patch)
tree418a877474808d5e84d8f2ef07f09852724e9542
parentd2ab94dac23bab41d25f7f5c7814d7d3a4d5b1c4 (diff)
downloadpostgresql-1dd56fdae41367ca0fdef5c14849a7e755a8ed32.tar.gz
postgresql-1dd56fdae41367ca0fdef5c14849a7e755a8ed32.zip
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.
-rw-r--r--src/backend/tcop/postgres.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 325411df09c..a6afecaba60 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;
}