From: Pavan Deolasee Date: Fri, 19 Oct 2018 05:08:03 +0000 (+0530) Subject: Another improvement to handle multi-command queries correctly. X-Git-Tag: XL_10_R1~8 X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=80a61d377b2160e748485d58761851dc66656a7e;p=postgres-xl.git Another improvement to handle multi-command queries correctly. The new facilities in PG10 offer ways to split and detect the individual commands in a multi-command query. But we were failing to use that correctly at a few places. This was detected by isolation tester, but there was also an existing bug masked by incorrect acceptance of expected output. To be fair, the falling test case was copied to xl_known_bugs. So this was a known issue for a while. This now fixes the regression and isolation test. --- diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 37d4c2d239..48c08ec64c 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -183,6 +183,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString, */ if (!sentToRemote) parsetree_list = AddRemoteQueryNode(parsetree_list, queryString, + stmt_location, stmt_len, EXEC_ON_ALL_NODES); #endif diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index a8b9f8a145..d1b739269c 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -79,7 +79,11 @@ static CombineType get_plan_combine_type(CmdType commandType, char baselocatorty * duplicated queries on Datanodes. */ List * -AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType remoteExecType) +AddRemoteQueryNode(List *stmts, + const char *queryString, + int stmt_location, + int stmt_len, + RemoteQueryExecType remoteExecType) { List *result = stmts; @@ -93,7 +97,15 @@ AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType rem { RemoteQuery *step = makeNode(RemoteQuery); step->combine_type = COMBINE_TYPE_SAME; - step->sql_statement = (char *) queryString; + if (stmt_location == -1) + step->sql_statement = (char *) queryString; + else + { + step->sql_statement = pnstrdup(queryString + stmt_location, + stmt_len == 0 ? + strlen(queryString) - stmt_location : + stmt_len); + } step->exec_type = remoteExecType; result = lappend(result, step); } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 3ae1a302d6..afcdf3e937 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -90,12 +90,17 @@ #include "pgxc/pause.h" #endif -static void ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, +static void ExecUtilityStmtOnNodes(const char *queryString, + int stmt_location, + int stmt_len, + ExecNodes *nodes, bool sentToRemote, RemoteQueryExecType exec_type, bool is_temp, bool add_context); static void ExecUtilityStmtOnNodesInternal(const char *queryString, + int stmt_location, + int stmt_len, ExecNodes *nodes, bool sentToRemote, RemoteQueryExecType exec_type, @@ -128,6 +133,8 @@ static void ProcessUtilitySlow(ParseState *pstate, #ifdef PGXC static void ExecDropStmt(DropStmt *stmt, const char *queryString, + int stmt_location, + int stmt_len, bool sentToRemote, bool isTopLevel); #else @@ -550,7 +557,7 @@ ProcessUtilityPre(PlannedStmt *pstmt, /* Clean also remote Coordinators */ sprintf(query, "CLEAN CONNECTION TO ALL FOR DATABASE %s;", quote_identifier(stmt->dbname)); - ExecUtilityStmtOnNodes(query, NULL, sentToRemote, + ExecUtilityStmtOnNodes(query, -1, 0, NULL, sentToRemote, EXEC_ON_ALL_NODES, false, false); } break; @@ -717,7 +724,7 @@ ProcessUtilityPre(PlannedStmt *pstmt, * connections, then clean local pooler */ if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, + ExecUtilityStmtOnNodes(queryString, -1, 0, NULL, sentToRemote, EXEC_ON_ALL_NODES, false, false); CleanConnection((CleanConnStmt *) parsetree); break; @@ -884,7 +891,8 @@ ProcessUtilityPre(PlannedStmt *pstmt, * Send queryString to remote nodes, if needed. */ if (IS_PGXC_LOCAL_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, + ExecUtilityStmtOnNodes(queryString, pstmt->stmt_location, + pstmt->stmt_len, NULL, sentToRemote, exec_type, is_temp, add_context); @@ -1319,7 +1327,8 @@ ProcessUtilityPost(PlannedStmt *pstmt, } if (IS_PGXC_LOCAL_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, + ExecUtilityStmtOnNodes(queryString, pstmt->stmt_location, + pstmt->stmt_len, NULL, sentToRemote, exec_type, is_temp, add_context); } /* @@ -1860,7 +1869,8 @@ standard_ProcessUtility(PlannedStmt *pstmt, sentToRemote, completionTag); else - ExecDropStmt(stmt, queryString, sentToRemote, isTopLevel); + ExecDropStmt(stmt, queryString, pstmt->stmt_location, + pstmt->stmt_len, sentToRemote, isTopLevel); } break; @@ -2107,8 +2117,10 @@ ProcessUtilitySlow(ParseState *pstate, * Coordinator, if not already done so */ if (!sentToRemote) - stmts = AddRemoteQueryNode(stmts, queryString, is_local - ? EXEC_ON_NONE + stmts = AddRemoteQueryNode(stmts, queryString, + pstmt->stmt_location, + pstmt->stmt_len, + is_local ? EXEC_ON_NONE : (is_temp ? EXEC_ON_DATANODES : EXEC_ON_ALL_NODES)); /* ... and do it */ @@ -2244,7 +2256,9 @@ ProcessUtilitySlow(ParseState *pstate, relid, &is_temp); - stmts = AddRemoteQueryNode(stmts, queryString, exec_type); + stmts = AddRemoteQueryNode(stmts, queryString, + pstmt->stmt_location, pstmt->stmt_len, + exec_type); } } @@ -2681,7 +2695,9 @@ ProcessUtilitySlow(ParseState *pstate, break; case T_DropStmt: - ExecDropStmt((DropStmt *) parsetree, queryString, sentToRemote, isTopLevel); + ExecDropStmt((DropStmt *) parsetree, queryString, + pstmt->stmt_location, pstmt->stmt_len, + sentToRemote, isTopLevel); /* no commands stashed for DROP */ commandCollected = true; break; @@ -2824,6 +2840,8 @@ static void #ifdef PGXC ExecDropStmt(DropStmt *stmt, const char *queryString, + int stmt_location, + int stmt_len, bool sentToRemote, bool isTopLevel) #else @@ -2864,7 +2882,8 @@ ExecDropStmt(DropStmt *stmt, bool isTopLevel) { if (prevent_xact_chain) SetRequireRemoteTransactionAutoCommit(); - ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, + ExecUtilityStmtOnNodes(queryString, stmt_location, + stmt_len, NULL, sentToRemote, exec_type, is_temp, false); } } @@ -2883,7 +2902,8 @@ ExecDropStmt(DropStmt *stmt, bool isTopLevel) RemoveObjects(stmt); #ifdef PGXC if (IS_PGXC_LOCAL_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, + ExecUtilityStmtOnNodes(queryString, stmt_location, + stmt_len, NULL, sentToRemote, exec_type, is_temp, false); } #endif @@ -4622,8 +4642,13 @@ GetCommandLogLevel(Node *parsetree) #ifdef PGXC static void -ExecUtilityStmtOnNodesInternal(const char *queryString, ExecNodes *nodes, bool sentToRemote, - RemoteQueryExecType exec_type, bool is_temp) +ExecUtilityStmtOnNodesInternal(const char *queryString, + int stmt_location, + int stmt_len, + ExecNodes *nodes, + bool sentToRemote, + RemoteQueryExecType exec_type, + bool is_temp) { /* Return if query is launched on no nodes */ if (exec_type == EXEC_ON_NONE) @@ -4646,7 +4671,12 @@ ExecUtilityStmtOnNodesInternal(const char *queryString, ExecNodes *nodes, bool s RemoteQuery *step = makeNode(RemoteQuery); step->combine_type = COMBINE_TYPE_SAME; step->exec_nodes = nodes; - step->sql_statement = pstrdup(queryString); + if (stmt_location == -1) + step->sql_statement = pstrdup(queryString); + else + step->sql_statement = pnstrdup(queryString + stmt_location, + stmt_len == 0 ? strlen(queryString) - stmt_location : + stmt_len); step->exec_type = exec_type; ExecRemoteUtility(step); pfree(step->sql_statement); @@ -4669,13 +4699,19 @@ ExecUtilityStmtOnNodesInternal(const char *queryString, ExecNodes *nodes, bool s * context message containing the failed node names. */ static void -ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, - bool sentToRemote, RemoteQueryExecType exec_type, - bool is_temp, bool add_context) +ExecUtilityStmtOnNodes(const char *queryString, + int stmt_location, + int stmt_len, + ExecNodes *nodes, + bool sentToRemote, + RemoteQueryExecType exec_type, + bool is_temp, + bool add_context) { PG_TRY(); { - ExecUtilityStmtOnNodesInternal(queryString, nodes, sentToRemote, + ExecUtilityStmtOnNodesInternal(queryString, stmt_location, stmt_len, + nodes, sentToRemote, exec_type, is_temp); } PG_CATCH(); diff --git a/src/include/pgxc/planner.h b/src/include/pgxc/planner.h index af4569b21a..2269063e50 100644 --- a/src/include/pgxc/planner.h +++ b/src/include/pgxc/planner.h @@ -183,7 +183,10 @@ typedef struct extern PlannedStmt *pgxc_direct_planner(Query *query, int cursorOptions, ParamListInfo boundParams); -extern List *AddRemoteQueryNode(List *stmts, const char *queryString, +extern List *AddRemoteQueryNode(List *stmts, + const char *queryString, + int stmt_location, + int stmt_len, RemoteQueryExecType remoteExecType); extern PlannedStmt *pgxc_planner(Query *query, int cursorOptions, ParamListInfo boundParams); diff --git a/src/test/regress/expected/xc_misc.out b/src/test/regress/expected/xc_misc.out index 83d9ae62c0..f728dd1d43 100644 --- a/src/test/regress/expected/xc_misc.out +++ b/src/test/regress/expected/xc_misc.out @@ -55,8 +55,11 @@ SET check_function_bodies = false; create function f1 () returns setof my_tab1 as $$ create table my_tab2 (a int); select * from my_tab1; $$ language sql; ERROR: function "f1" already exists with same argument types select f1(); -ERROR: Unexpected response from Datanode -CONTEXT: SQL function "f1" statement 1 + f1 +----- + (1) +(1 row) + SET check_function_bodies = true; drop function f1(); -- Test pl-pgsql functions containing utility statements