]> granicus.if.org Git - postgresql/commitdiff
Remove pgbench's restriction on placement of -M switch.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 11 Aug 2017 19:19:40 +0000 (15:19 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 11 Aug 2017 19:19:40 +0000 (15:19 -0400)
Previously the -M switch had to appear before any switch that directly
or indirectly specified a benchmarking script.  This was both confusing
and inadequately documented, as per gripe from Tatsuo Ishii.  We can
remove the restriction at the cost of making an extra pass over the
lists of SQL commands, which seems like a cheap price (the string scans
themselves likely cost much more).  The change is just to not extract
parameters from the SQL commands until we have finished parsing the
switches and know the final value of -M.

Per discussion, we'll treat this as a low-grade bug fix and sneak it
into v10, rather than holding it for v11.

Tom Lane, reviewed by Tatsuo Ishii and Fabien Coelho

Discussion: https://postgr.es/m/20170802.110328.1963639094551443169.t-ishii@sraoss.co.jp
Discussion: https://postgr.es/m/10208.1502465077@sss.pgh.pa.us

src/bin/pgbench/pgbench.c

index 4d364a1db4cb219358b78f9ebd5614d3e264fd03..ae78c7b1d46fe06041f9017e982247b7a31bbccb 100644 (file)
@@ -2844,15 +2844,18 @@ init(bool is_no_vacuum)
 }
 
 /*
- * Parse the raw sql and replace :param to $n.
+ * Replace :param with $n throughout the command's SQL text, which
+ * is a modifiable string in cmd->argv[0].
  */
 static bool
-parseQuery(Command *cmd, const char *raw_sql)
+parseQuery(Command *cmd)
 {
        char       *sql,
                           *p;
 
-       sql = pg_strdup(raw_sql);
+       /* We don't want to scribble on cmd->argv[0] until done */
+       sql = pg_strdup(cmd->argv[0]);
+
        cmd->argc = 1;
 
        p = sql;
@@ -2874,7 +2877,8 @@ parseQuery(Command *cmd, const char *raw_sql)
 
                if (cmd->argc >= MAX_ARGS)
                {
-                       fprintf(stderr, "statement has too many arguments (maximum is %d): %s\n", MAX_ARGS - 1, raw_sql);
+                       fprintf(stderr, "statement has too many arguments (maximum is %d): %s\n",
+                                       MAX_ARGS - 1, cmd->argv[0]);
                        pg_free(name);
                        return false;
                }
@@ -2886,6 +2890,7 @@ parseQuery(Command *cmd, const char *raw_sql)
                cmd->argc++;
        }
 
+       pg_free(cmd->argv[0]);
        cmd->argv[0] = sql;
        return true;
 }
@@ -2983,9 +2988,15 @@ process_sql_command(PQExpBuffer buf, const char *source)
        my_command = (Command *) pg_malloc0(sizeof(Command));
        my_command->command_num = num_commands++;
        my_command->type = SQL_COMMAND;
-       my_command->argc = 0;
        initSimpleStats(&my_command->stats);
 
+       /*
+        * Install query text as the sole argv string.  If we are using a
+        * non-simple query mode, we'll extract parameters from it later.
+        */
+       my_command->argv[0] = pg_strdup(p);
+       my_command->argc = 1;
+
        /*
         * If SQL command is multi-line, we only want to save the first line as
         * the "line" label.
@@ -3000,21 +3011,6 @@ process_sql_command(PQExpBuffer buf, const char *source)
        else
                my_command->line = pg_strdup(p);
 
-       switch (querymode)
-       {
-               case QUERY_SIMPLE:
-                       my_command->argv[0] = pg_strdup(p);
-                       my_command->argc++;
-                       break;
-               case QUERY_EXTENDED:
-               case QUERY_PREPARED:
-                       if (!parseQuery(my_command, p))
-                               exit(1);
-                       break;
-               default:
-                       exit(1);
-       }
-
        return my_command;
 }
 
@@ -3896,11 +3892,6 @@ main(int argc, char **argv)
                                break;
                        case 'M':
                                benchmarking_option_set = true;
-                               if (num_scripts > 0)
-                               {
-                                       fprintf(stderr, "query mode (-M) should be specified before any transaction scripts (-f or -b)\n");
-                                       exit(1);
-                               }
                                for (querymode = 0; querymode < NUM_QUERYMODE; querymode++)
                                        if (strcmp(optarg, QUERYMODE[querymode]) == 0)
                                                break;
@@ -4006,6 +3997,24 @@ main(int argc, char **argv)
                internal_script_used = true;
        }
 
+       /* if not simple query mode, parse the script(s) to find parameters */
+       if (querymode != QUERY_SIMPLE)
+       {
+               for (i = 0; i < num_scripts; i++)
+               {
+                       Command   **commands = sql_script[i].commands;
+                       int                     j;
+
+                       for (j = 0; commands[j] != NULL; j++)
+                       {
+                               if (commands[j]->type != SQL_COMMAND)
+                                       continue;
+                               if (!parseQuery(commands[j]))
+                                       exit(1);
+                       }
+               }
+       }
+
        /* compute total_weight */
        for (i = 0; i < num_scripts; i++)
                /* cannot overflow: weight is 32b, total_weight 64b */