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: