Another improvement to handle multi-command queries correctly.
authorPavan Deolasee <[email protected]>
Fri, 19 Oct 2018 05:08:03 +0000 (10:38 +0530)
committerPavan Deolasee <[email protected]>
Fri, 19 Oct 2018 05:29:46 +0000 (10:59 +0530)
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.

src/backend/commands/schemacmds.c
src/backend/pgxc/plan/planner.c
src/backend/tcop/utility.c
src/include/pgxc/planner.h
src/test/regress/expected/xc_misc.out

index 37d4c2d239945071c799378174668d86e8bbfb78..48c08ec64c3a40918b482e521dedebaaa30ed789 100644 (file)
@@ -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
 
index a8b9f8a1457902ebff2325a035cf07398892c369..d1b739269c5291390fa7ca9cb985a7ac268fd6f2 100644 (file)
@@ -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);
        }
index 3ae1a302d640ef8fabab2e1c90171e5758219bb7..afcdf3e9376ead55a64547eefac9ac49b05b103b 100644 (file)
 #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();
index af4569b21ae2122bd00c64abf92221b015b6f0c7..2269063e50072ac91c3d21ca478894359642efc3 100644 (file)
@@ -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);
index 83d9ae62c0db80ed69e42ee4b6207f8a4480438a..f728dd1d4325795380514db88d593f651963717a 100644 (file)
@@ -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