diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c index 8a6437f..18b0d58 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,132 @@ top: st->listen = 1; } + else if (pg_strcasecmp(argv[0], "setshell") == 0) + { + int j, + retval, + retvalglob = 0; + char res[64], + 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 clientDone(st, false); + } + if (argc > 2) + { + for (j = 3; j < argc; j++) + { + char *commandLoc2 = strdup(commandLoc); + 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 clientDone(st, false); + } + 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 clientDone(st, false); + } + + if (fgets(res, sizeof(res), respipe) == NULL) + { + fprintf(stderr, "%s: error getting parameter\n", argv[0]); + st->ecnt++; + return clientDone(st, false); + } + + retval = pclose(respipe); + if (retval == -1) + { + fprintf(stderr, "%s: error closing shell script\n", argv[0]); + st->ecnt++; + return clientDone(st, false); + } + /* Transform the parameter into an integer */ + retval = atoi(res); + if (retval == 0) + { + fprintf(stderr, "%s: error input integer\n", argv[0]); + st->ecnt++; + return clientDone(st, false); + } + /* 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 clientDone(st, false); + } +#ifdef DEBUG + printf("shell parameter name: %s, value: %s", argv[1], res); +#endif + st->listen = 1; + } + else if (pg_strcasecmp(argv[0], "shell") == 0) + { + int j, + retval, + retvalglob; + char commandLoc[SHELL_COMMAND_SIZE]; + + 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); + 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 +1439,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 options dbname + + + \setshell varname scriptname [ arguments ] + + + + + Sets variable varname from the output of the call of scriptname. + It is possible to use as arguments variables already set with set or set random. + Or use 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. + + + + Example: + +\setshell variable_name script_name :var_previously_defined script_arg + + + + + + + + + \shell command [ arguments ] + + + + + Possibility to launch a shell command directly in + pgbench with command. The user is free to use as many + arguments<\> as he wants depending on the measurement needings. + + + + Example: + +\shell shell_command shell_arguments + + + + + + As an example, the full definition of the built-in TPC-B-like transaction is: