diff options
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 4605eedd77..6ffe015136 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -754,7 +754,7 @@ ProcessClientWriteInterrupt(bool blocked) * commands are not processed any further than the raw parse stage. */ List * -pg_parse_query(const char *query_string) +pg_parse_query_internal(const char *query_string, List **querysource_list) { List *raw_parsetree_list; @@ -763,7 +763,7 @@ pg_parse_query(const char *query_string) if (log_parser_stats) ResetUsage(); - raw_parsetree_list = raw_parser(query_string); + raw_parsetree_list = raw_parser(query_string, querysource_list); if (log_parser_stats) ShowUsage("PARSER STATISTICS"); @@ -786,6 +786,18 @@ pg_parse_query(const char *query_string) return raw_parsetree_list; } +List * +pg_parse_query(const char *query_string) +{ + return pg_parse_query_internal(query_string, NULL); +} + +List * +pg_parse_query_get_source(const char *query_string, List **querysource_list) +{ + return pg_parse_query_internal(query_string, querysource_list); +} + /* * Given a raw parsetree (gram.y output), and optionally information about * types of parameter symbols ($n), perform parse analysis and rule rewriting. @@ -1044,6 +1056,8 @@ exec_simple_query(const char *query_string) MemoryContext oldcontext; List *parsetree_list; ListCell *parsetree_item; + List *querysource_list; + ListCell *querysource_item; bool save_log_statement_stats = log_statement_stats; bool was_logged = false; bool isTopLevel; @@ -1092,7 +1106,7 @@ exec_simple_query(const char *query_string) * Do basic parsing of the query or queries (this should be safe even if * we are in aborted transaction state!) */ - parsetree_list = pg_parse_query(query_string); + parsetree_list = pg_parse_query_get_source(query_string, &querysource_list); #ifdef XCP if (IS_PGXC_LOCAL_COORDINATOR && list_length(parsetree_list) > 1) @@ -1159,9 +1173,10 @@ exec_simple_query(const char *query_string) /* * Run through the raw parsetree(s) and process each one. */ - foreach(parsetree_item, parsetree_list) + forboth(parsetree_item, parsetree_list, querysource_item, querysource_list) { Node *parsetree = (Node *) lfirst(parsetree_item); + char *querysource = ((Value *) lfirst(querysource_item))->val.str; bool snapshot_set = false; const char *commandTag; char completionTag[COMPLETION_TAG_BUFSIZE]; @@ -1274,10 +1289,23 @@ exec_simple_query(const char *query_string) * We don't have to copy anything into the portal, because everything * we are passing here is in MessageContext, which will outlive the * portal anyway. + * + * The query_string may contain multiple commands separated by ';' and + * we have a separate parsetree corresponding to each such command. + * Since we later may send down the query to the remote nodes + * (especially for utility queries), using the query_string is a + * problem because the same query will be sent out multiple times, one + * for each command processed. So we taught the parser to return the + * portion of the query_string along with the parsetree and use that + * while defining a portal below. + * + * XXX Since the portal expects to see a valid query_string, if the + * substring is available, use the original query_string. Not elegant, + * but far better than what we were doing earlier */ PortalDefineQuery(portal, NULL, - query_string, + querysource ? querysource : query_string, commandTag, plantree_list, NULL); |