diff options
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index c3531b58449..85a266172f8 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.2.2 2008/04/02 18:32:00 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.542.2.3 2008/12/13 02:00:29 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -674,6 +674,9 @@ pg_plan_query(Query *querytree, int cursorOptions, ParamListInfo boundParams) if (querytree->commandType == CMD_UTILITY) return NULL; + /* Planner must have a snapshot in case it calls user-defined functions. */ + Assert(ActiveSnapshot != NULL); + if (log_planner_stats) ResetUsage(); @@ -866,6 +869,7 @@ exec_simple_query(const char *query_string) foreach(parsetree_item, parsetree_list) { Node *parsetree = (Node *) lfirst(parsetree_item); + Snapshot mySnapshot = NULL; const char *commandTag; char completionTag[COMPLETION_TAG_BUFSIZE]; List *querytree_list, @@ -908,6 +912,15 @@ exec_simple_query(const char *query_string) CHECK_FOR_INTERRUPTS(); /* + * Set up a snapshot if parse analysis/planning will need one. + */ + if (analyze_requires_snapshot(parsetree)) + { + mySnapshot = CopySnapshot(GetTransactionSnapshot()); + ActiveSnapshot = mySnapshot; + } + + /* * OK to analyze, rewrite, and plan this query. * * Switch to appropriate context for constructing querytrees (again, @@ -918,7 +931,12 @@ exec_simple_query(const char *query_string) querytree_list = pg_analyze_and_rewrite(parsetree, query_string, NULL, 0); - plantree_list = pg_plan_queries(querytree_list, 0, NULL, true); + plantree_list = pg_plan_queries(querytree_list, 0, NULL, false); + + /* Done with the snapshot used for parsing/planning */ + ActiveSnapshot = NULL; + if (mySnapshot) + FreeSnapshot(mySnapshot); /* If we got a cancel signal in analysis or planning, quit */ CHECK_FOR_INTERRUPTS(); @@ -933,7 +951,7 @@ exec_simple_query(const char *query_string) /* * We don't have to copy anything into the portal, because everything - * we are passsing here is in MessageContext, which will outlive the + * we are passing here is in MessageContext, which will outlive the * portal anyway. */ PortalDefineQuery(portal, @@ -1168,6 +1186,7 @@ exec_parse_message(const char *query_string, /* string to execute */ if (parsetree_list != NIL) { Query *query; + Snapshot mySnapshot = NULL; int i; raw_parse_tree = (Node *) linitial(parsetree_list); @@ -1193,6 +1212,15 @@ exec_parse_message(const char *query_string, /* string to execute */ "commands ignored until end of transaction block"))); /* + * Set up a snapshot if parse analysis/planning will need one. + */ + if (analyze_requires_snapshot(raw_parse_tree)) + { + mySnapshot = CopySnapshot(GetTransactionSnapshot()); + ActiveSnapshot = mySnapshot; + } + + /* * OK to analyze, rewrite, and plan this query. Note that the * originally specified parameter set is not required to be complete, * so we have to use parse_analyze_varparams(). @@ -1239,9 +1267,14 @@ exec_parse_message(const char *query_string, /* string to execute */ } else { - stmt_list = pg_plan_queries(querytree_list, 0, NULL, true); + stmt_list = pg_plan_queries(querytree_list, 0, NULL, false); fully_planned = true; } + + /* Done with the snapshot used for parsing/planning */ + ActiveSnapshot = NULL; + if (mySnapshot) + FreeSnapshot(mySnapshot); } else { @@ -1365,6 +1398,7 @@ exec_bind_message(StringInfo input_message) List *plan_list; MemoryContext oldContext; bool save_log_statement_stats = log_statement_stats; + Snapshot mySnapshot = NULL; char msec_str[32]; /* Get the fixed part of the message */ @@ -1487,6 +1521,17 @@ exec_bind_message(StringInfo input_message) saved_stmt_name = NULL; /* + * Set a snapshot if we have parameters to fetch (since the input + * functions might need it) or the query isn't a utility command (and + * hence could require redoing parse analysis and planning). + */ + if (numParams > 0 || analyze_requires_snapshot(psrc->raw_parse_tree)) + { + mySnapshot = CopySnapshot(GetTransactionSnapshot()); + ActiveSnapshot = mySnapshot; + } + + /* * Fetch parameters, if any, and store in the portal's memory context. */ if (numParams > 0) @@ -1674,7 +1719,7 @@ exec_bind_message(StringInfo input_message) */ oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); query_list = copyObject(cplan->stmt_list); - plan_list = pg_plan_queries(query_list, 0, params, true); + plan_list = pg_plan_queries(query_list, 0, params, false); MemoryContextSwitchTo(oldContext); /* We no longer need the cached plan refcount ... */ @@ -1683,6 +1728,11 @@ exec_bind_message(StringInfo input_message) cplan = NULL; } + /* Done with the snapshot used for parameter I/O and parsing/planning */ + ActiveSnapshot = NULL; + if (mySnapshot) + FreeSnapshot(mySnapshot); + /* * Define portal and start execution. */ @@ -3434,6 +3484,9 @@ PostgresMain(int argc, char *argv[], const char *username) */ debug_query_string = NULL; + /* No active snapshot any more either */ + ActiveSnapshot = NULL; + /* * Abort the current transaction in order to recover. */ |