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

Reply via email to