diff options
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index b09401652b8..97b9b170b92 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.560 2008/12/09 15:59:39 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.561 2008/12/13 02:00:19 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -685,6 +685,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(ActiveSnapshotSet()); + TRACE_POSTGRESQL_QUERY_PLAN_START(); if (log_planner_stats) @@ -872,6 +875,7 @@ exec_simple_query(const char *query_string) foreach(parsetree_item, parsetree_list) { Node *parsetree = (Node *) lfirst(parsetree_item); + bool snapshot_set = false; const char *commandTag; char completionTag[COMPLETION_TAG_BUFSIZE]; List *querytree_list, @@ -914,6 +918,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)) + { + PushActiveSnapshot(GetTransactionSnapshot()); + snapshot_set = true; + } + + /* * OK to analyze, rewrite, and plan this query. * * Switch to appropriate context for constructing querytrees (again, @@ -924,7 +937,11 @@ 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 */ + if (snapshot_set) + PopActiveSnapshot(); /* If we got a cancel signal in analysis or planning, quit */ CHECK_FOR_INTERRUPTS(); @@ -939,7 +956,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, @@ -1178,6 +1195,7 @@ exec_parse_message(const char *query_string, /* string to execute */ if (parsetree_list != NIL) { Query *query; + bool snapshot_set = false; int i; raw_parse_tree = (Node *) linitial(parsetree_list); @@ -1203,6 +1221,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)) + { + PushActiveSnapshot(GetTransactionSnapshot()); + snapshot_set = true; + } + + /* * 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(). @@ -1249,9 +1276,13 @@ 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 */ + if (snapshot_set) + PopActiveSnapshot(); } else { @@ -1375,6 +1406,7 @@ exec_bind_message(StringInfo input_message) List *plan_list; MemoryContext oldContext; bool save_log_statement_stats = log_statement_stats; + bool snapshot_set = false; char msec_str[32]; /* Get the fixed part of the message */ @@ -1495,6 +1527,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)) + { + PushActiveSnapshot(GetTransactionSnapshot()); + snapshot_set = true; + } + + /* * Fetch parameters, if any, and store in the portal's memory context. */ if (numParams > 0) @@ -1682,7 +1725,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 ... */ @@ -1691,6 +1734,10 @@ exec_bind_message(StringInfo input_message) cplan = NULL; } + /* Done with the snapshot used for parameter I/O and parsing/planning */ + if (snapshot_set) + PopActiveSnapshot(); + /* * Define portal and start execution. */ |