I didn't send the good patch yesterday. => --; Here is the latest version. Regards,
-- Michael Paquier NIPPON TELEGRAPH AND TELEPHONE CORPORATION NTT Open Source Software Center
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c index 8a6437f..0bc6bfe 100644 --- a/contrib/pgbench/pgbench.c +++ b/contrib/pgbench/pgbench.c @@ -159,6 +159,7 @@ typedef struct } Variable; #define MAX_FILES 128 /* max number of SQL script files allowed */ +#define SHELL_COMMAND_SIZE 256 /* maximum size allowed for shell command */ /* * structures used in custom query mode @@ -992,7 +993,168 @@ top: st->listen = 1; } + else if (pg_strcasecmp(argv[0], "setshell") == 0) + { + int j, + retval, + retvalglob = 0; + char res[64], + *var = NULL, + commandLoc[SHELL_COMMAND_SIZE]; + FILE *respipe = NULL; + + /* construction of the command line with all the transmitted arguments */ + retval = snprintf(commandLoc,SHELL_COMMAND_SIZE-1,"%s",argv[2]); + if (retval < 0 + || retval > SHELL_COMMAND_SIZE-1) + { + fprintf(stderr, "Error loading parameter by setshell: too many characters\n"); + st->ecnt++; + return true; + } + if (argc > 2) + { + for (j = 3; j < argc; j++) + { + char *commandLoc2 = strdup(commandLoc); + /* + * before adding the command argument, check if it is an existing :variable + * and put the associated value + */ + if (*argv[j] == ':') + { + if ((var = getVariable(st, argv[j] + 1)) == NULL) + { + fprintf(stderr, "%s: undefined variable %s\n", argv[0], argv[j]); + st->ecnt++; + return true; + } + retval = snprintf(commandLoc,SHELL_COMMAND_SIZE-1,"%s %s", commandLoc2, var); + } + else + { + /* then continue building the command */ + retval = snprintf(commandLoc,SHELL_COMMAND_SIZE-1,"%s %s", commandLoc2, argv[j]); + } + retvalglob += retval; + if (retval < 0 + || retvalglob > SHELL_COMMAND_SIZE-1) + { + fprintf(stderr, "Error loading parameter by setshell: too many characters\n"); + free(commandLoc2); + st->ecnt++; + return true; + } + free(commandLoc2); + } + } + + /* + * Data treatment + * prototype: /setshell aid skewerand +additional arguments + */ + respipe = popen(commandLoc,"r"); + if (respipe == NULL) + { + fprintf(stderr, "%s: error launching shell script\n", argv[0]); + st->ecnt++; + return true; + } + + if (fgets(res, sizeof(res), respipe) == NULL) + { + fprintf(stderr, "%s: error getting parameter\n", argv[0]); + st->ecnt++; + return true; + } + + retval = pclose(respipe); + if (retval == -1) + { + fprintf(stderr, "%s: error closing shell script\n", argv[0]); + st->ecnt++; + return true; + } + /* Transform the parameter into an integer */ + retval = atoi(res); + if (retval == 0) + { + fprintf(stderr, "%s: error input integer\n", argv[0]); + st->ecnt++; + return true; + } + /* ready to put the variable */ + snprintf(res, sizeof(res), "%d", retval); + + if (putVariable(st, argv[1], res) == false) + { + fprintf(stderr, "%s: out of memory\n", argv[0]); + st->ecnt++; + return true; + } +#ifdef DEBUG + printf("shell parameter name: %s, value: %s\n", argv[1], res); +#endif + st->listen = 1; + } + else if (pg_strcasecmp(argv[0], "shell") == 0) + { + int j, + retval, + retvalglob; + char commandLoc[SHELL_COMMAND_SIZE], + *var = NULL; + + retval = snprintf(commandLoc,SHELL_COMMAND_SIZE-1,"%s",argv[1]); + if (retval < 0 + || retval > SHELL_COMMAND_SIZE-1) + { + fprintf(stderr, "Error launching shell command: too many characters\n"); + st->ecnt++; + return true; + } + retvalglob = retval; + + for (j = 2; j < argc; j++) + { + char *commandLoc2 = strdup(commandLoc); + /* before building the command analyze if it is a pgbench variable already defined */ + if (*argv[j] == ':') + { + if ((var = getVariable(st, argv[j] + 1)) == NULL) + { + fprintf(stderr, "%s: undefined variable %s\n", argv[0], argv[j]); + st->ecnt++; + return true; + } + retval = snprintf(commandLoc,SHELL_COMMAND_SIZE-1,"%s %s", commandLoc2, var); + } + else + { + /* Then build the command */ + retval = snprintf(commandLoc,SHELL_COMMAND_SIZE-1,"%s %s", commandLoc2, argv[j]); + } + retvalglob += retval; + if (retval < 0 + || retvalglob > SHELL_COMMAND_SIZE-1) + { + fprintf(stderr, "Error launching shell command: too many characters\n"); + free(commandLoc2); + st->ecnt++; + return true; + } + free(commandLoc2); + } + retval = system(commandLoc); + if (retval < 0) + { + fprintf(stderr, "Error launching shell command: command not launched\n"); + st->ecnt++; + return true; + } + st->listen = 1; + } goto top; } @@ -1313,6 +1475,22 @@ process_commands(char *buf) fprintf(stderr, "%s: extra argument \"%s\" ignored\n", my_commands->argv[0], my_commands->argv[j]); } + else if (pg_strcasecmp(my_commands->argv[0], "setshell") == 0) + { + if (my_commands->argc < 3) + { + fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]); + return NULL; + } + } + else if (pg_strcasecmp(my_commands->argv[0], "shell") == 0) + { + if (my_commands->argc < 1) + { + fprintf(stderr, "%s: missing command\n", my_commands->argv[0]); + return NULL; + } + } else { fprintf(stderr, "Invalid command %s\n", my_commands->argv[0]); diff --git a/doc/src/sgml/pgbench.sgml b/doc/src/sgml/pgbench.sgml index f535312..0782cb1 100644 --- a/doc/src/sgml/pgbench.sgml +++ b/doc/src/sgml/pgbench.sgml @@ -466,6 +466,52 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> </varlistentry> </variablelist> + <varlistentry> + <term> + <literal>\setshell <replaceable></> <replaceable>varname</> <replaceable>scriptname</> [ <replaceable>arguments</> ]</literal> + </term> + + <listitem> + <para> + Sets variable <replaceable>varname</> from the output of the call of <replaceable>scriptname</>. + It is possible to use as <replaceable>arguments</> variables already set with set or set random. + Or use <replaceable>arguments</> as arguments for the script call. + The user is free to set up the arguments depending on the needs for his tests. + Possibility to use C, perl or other script types in this feature. + </para> + + <para> + Example: + <programlisting> +\setshell variable_name script_name :var_previously_defined script_arg + </programlisting> + </para> + </listitem> + </varlistentry> + </variablelist> + + <varlistentry> + <term> + <literal>\shell <replaceable></> <replaceable>command</> [ <replaceable>arguments</> ]</literal> + </term> + + <listitem> + <para> + Possibility to launch a shell command directly in + pgbench with <replaceable>command</>. The user is free to use as many + <replaceable>arguments<\> as he wants depending on the measurement needings. + </para> + + <para> + Example: + <programlisting> +\shell shell_command shell_arguments + </programlisting> + </para> + </listitem> + </varlistentry> + </variablelist> + <para> As an example, the full definition of the built-in TPC-B-like transaction is:
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers