Hi
2015-09-21 16:46 GMT+02:00 Adam Brightwell <
[email protected]>:
> Pavel,
>
> > with -1 option support
>
> FWIW, I have tried to apply this patch against master (7f11724) and
> there is a minor error, see below.
>
> From patch:
>
> patching file src/bin/psql/settings.h
> Hunk #2 FAILED at 135.
> 1 out of 2 hunks FAILED -- saving rejects to file
> src/bin/psql/settings.h.rej
>
> From settings.h.rej:
>
> --- src/bin/psql/settings.h
> +++ src/bin/psql/settings.h
> @@ -135,6 +141,7 @@
> const char *prompt2;
> const char *prompt3;
> PGVerbosity verbosity; /* current error verbosity level */
> + GroupCommand *group_commands;
> } PsqlSettings;
>
> extern PsqlSettings pset;
>
yes, it was broken by context visibility patch.
fixed patch attached
Regards
Pavel
>
> -Adam
>
> --
> Adam Brightwell - [email protected]
> Database Engineer - www.crunchydatasolutions.com
>
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
new file mode 100644
index 212dbfa..c932bb2
*** a/doc/src/sgml/ref/psql-ref.sgml
--- b/doc/src/sgml/ref/psql-ref.sgml
*************** EOF
*** 223,228 ****
--- 223,242 ----
</varlistentry>
<varlistentry>
+ <term><option>-g <replaceable class="parameter">command(s)</replaceable></></term>
+ <term><option>--group-command=<replaceable class="parameter">command(s)</replaceable></></term>
+ <listitem>
+ <para>
+ Specifies that <application>psql</application> is to execute one or
+ more command strings, <replaceable class="parameter">commands</replaceable>,
+ and then exit. This is useful in shell scripts. Start-up files
+ (<filename>psqlrc</filename> and <filename>~/.psqlrc</filename>) are
+ ignored with this option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-h <replaceable class="parameter">hostname</replaceable></></term>
<term><option>--host=<replaceable class="parameter">hostname</replaceable></></term>
<listitem>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
new file mode 100644
index 50d3ff5..73ed5c1
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** process_file(char *filename, bool single
*** 2293,2299 ****
int result;
char *oldfilename;
char relpath[MAXPGPATH];
- PGresult *res;
if (!filename)
{
--- 2293,2298 ----
*************** process_file(char *filename, bool single
*** 2338,2374 ****
oldfilename = pset.inputfile;
pset.inputfile = filename;
! if (single_txn)
! {
! if ((res = PSQLexec("BEGIN")) == NULL)
! {
! if (pset.on_error_stop)
! {
! result = EXIT_USER;
! goto error;
! }
! }
! else
! PQclear(res);
! }
!
! result = MainLoop(fd);
!
! if (single_txn)
! {
! if ((res = PSQLexec("COMMIT")) == NULL)
! {
! if (pset.on_error_stop)
! {
! result = EXIT_USER;
! goto error;
! }
! }
! else
! PQclear(res);
! }
- error:
if (fd != stdin)
fclose(fd);
--- 2337,2344 ----
oldfilename = pset.inputfile;
pset.inputfile = filename;
! result = MainLoop(fd, single_txn);
if (fd != stdin)
fclose(fd);
*************** error:
*** 2376,2383 ****
return result;
}
-
-
static const char *
_align2string(enum printFormat in)
{
--- 2346,2351 ----
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
new file mode 100644
index 5b63e76..2ef4ea6
*** a/src/bin/psql/help.c
--- b/src/bin/psql/help.c
*************** usage(unsigned short int pager)
*** 83,88 ****
--- 83,90 ----
fprintf(output, _(" -c, --command=COMMAND run only single command (SQL or internal) and exit\n"));
fprintf(output, _(" -d, --dbname=DBNAME database name to connect to (default: \"%s\")\n"), env);
fprintf(output, _(" -f, --file=FILENAME execute commands from file, then exit\n"));
+ fprintf(output, _(" -g, --group-command=COMMAND\n"
+ " run more groups of commands (SQL or internal) and exit\n"));
fprintf(output, _(" -l, --list list available databases, then exit\n"));
fprintf(output, _(" -v, --set=, --variable=NAME=VALUE\n"
" set psql variable NAME to VALUE\n"
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
new file mode 100644
index b6cef94..4147238
*** a/src/bin/psql/mainloop.c
--- b/src/bin/psql/mainloop.c
***************
*** 24,31 ****
* This loop is re-entrant. May be called by \i command
* which reads input from a file.
*/
! int
! MainLoop(FILE *source)
{
PsqlScanState scan_state; /* lexer working state */
volatile PQExpBuffer query_buf; /* buffer for query being accumulated */
--- 24,31 ----
* This loop is re-entrant. May be called by \i command
* which reads input from a file.
*/
! static int
! _MainLoop(FILE *source)
{
PsqlScanState scan_state; /* lexer working state */
volatile PQExpBuffer query_buf; /* buffer for query being accumulated */
*************** MainLoop(FILE *source)
*** 43,48 ****
--- 43,49 ----
volatile promptStatus_t prompt_status = PROMPT_READY;
volatile int count_eof = 0;
volatile bool die_on_error = false;
+ GroupCommand *cmd = pset.group_commands;
/* Save the prior command source */
FILE *prev_cmd_source;
*************** MainLoop(FILE *source)
*** 135,140 ****
--- 136,155 ----
prompt_status = PROMPT_READY;
line = gets_interactive(get_prompt(prompt_status));
}
+ else if (pset.group_commands != NULL)
+ {
+ /* Is there some unprocessed group command? */
+ if (cmd != NULL)
+ {
+ line = cmd->actions;
+ cmd = cmd->next;
+ }
+ else
+ {
+ successResult = EXIT_SUCCESS;
+ break;
+ }
+ }
else
{
line = gets_fromFile(source);
*************** MainLoop(FILE *source)
*** 451,456 ****
--- 466,508 ----
return successResult;
} /* MainLoop() */
+ /*
+ * Transactional MainLoop
+ *
+ * allow to execute all statements in single transaction
+ */
+ int
+ MainLoop(FILE *source, bool single_txn)
+ {
+ int result;
+ PGresult *res;
+
+ if (single_txn)
+ {
+ if ((res = PSQLexec("BEGIN")) == NULL)
+ {
+ if (pset.on_error_stop)
+ return EXIT_USER;
+ }
+ else
+ PQclear(res);
+ }
+
+ result = _MainLoop(source);
+
+ if (single_txn)
+ {
+ if ((res = PSQLexec("COMMIT")) == NULL)
+ {
+ if (pset.on_error_stop)
+ return EXIT_USER;
+ }
+ else
+ PQclear(res);
+ }
+
+ return result;
+ }
/*
* psqlscan.c is #include'd here instead of being compiled on its own.
diff --git a/src/bin/psql/mainloop.h b/src/bin/psql/mainloop.h
new file mode 100644
index 8f1325c..53c9a11
*** a/src/bin/psql/mainloop.h
--- b/src/bin/psql/mainloop.h
***************
*** 10,15 ****
#include "postgres_fe.h"
! int MainLoop(FILE *source);
#endif /* MAINLOOP_H */
--- 10,15 ----
#include "postgres_fe.h"
! int MainLoop(FILE *source, bool single_txn);
#endif /* MAINLOOP_H */
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
new file mode 100644
index 1885bb1..29455ac
*** a/src/bin/psql/settings.h
--- b/src/bin/psql/settings.h
*************** enum trivalue
*** 77,82 ****
--- 77,88 ----
TRI_YES
};
+ typedef struct _GroupCommand
+ {
+ char *actions;
+ struct _GroupCommand *next;
+ } GroupCommand;
+
typedef struct _psqlSettings
{
PGconn *db; /* connection to backend */
*************** typedef struct _psqlSettings
*** 130,135 ****
--- 136,142 ----
const char *prompt3;
PGVerbosity verbosity; /* current error verbosity level */
PGContextVisibility show_context; /* current context display level */
+ GroupCommand *group_commands;
} PsqlSettings;
extern PsqlSettings pset;
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
new file mode 100644
index 7aa997d..df334b4
*** a/src/bin/psql/startup.c
--- b/src/bin/psql/startup.c
*************** enum _actions
*** 54,60 ****
ACT_SINGLE_SLASH,
ACT_LIST_DB,
ACT_SINGLE_QUERY,
! ACT_FILE
};
struct adhoc_opts
--- 54,61 ----
ACT_SINGLE_SLASH,
ACT_LIST_DB,
ACT_SINGLE_QUERY,
! ACT_FILE,
! ACT_GROUP_COMMANDS
};
struct adhoc_opts
*************** main(int argc, char *argv[])
*** 159,164 ****
--- 160,167 ----
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
+ pset.group_commands = NULL;
+
parse_psql_options(argc, argv, &options);
/*
*************** main(int argc, char *argv[])
*** 327,332 ****
--- 330,342 ----
? EXIT_SUCCESS : EXIT_FAILURE;
}
+ else if (options.action == ACT_GROUP_COMMANDS)
+ {
+ pset.notty = true;
+ SetVariableBool(pset.vars, "SINGLELINE");
+ successResult = MainLoop(NULL, options.single_txn);
+ }
+
/*
* or otherwise enter interactive main loop
*/
*************** main(int argc, char *argv[])
*** 339,345 ****
if (!pset.quiet)
printf(_("Type \"help\" for help.\n\n"));
initializeInput(options.no_readline ? 0 : 1);
! successResult = MainLoop(stdin);
}
/* clean up */
--- 349,355 ----
if (!pset.quiet)
printf(_("Type \"help\" for help.\n\n"));
initializeInput(options.no_readline ? 0 : 1);
! successResult = MainLoop(stdin, false);
}
/* clean up */
*************** parse_psql_options(int argc, char *argv[
*** 371,376 ****
--- 381,387 ----
{"file", required_argument, NULL, 'f'},
{"field-separator", required_argument, NULL, 'F'},
{"field-separator-zero", no_argument, NULL, 'z'},
+ {"group-command", required_argument, NULL, 'g'},
{"host", required_argument, NULL, 'h'},
{"html", no_argument, NULL, 'H'},
{"list", no_argument, NULL, 'l'},
*************** parse_psql_options(int argc, char *argv[
*** 402,410 ****
int optindex;
int c;
memset(options, 0, sizeof *options);
! while ((c = getopt_long(argc, argv, "aAbc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
long_options, &optindex)) != -1)
{
switch (c)
--- 413,424 ----
int optindex;
int c;
+ bool cmd_opt_is_used = false;
+ bool group_cmd_opt_is_used = false;
+
memset(options, 0, sizeof *options);
! while ((c = getopt_long(argc, argv, "aAbc:d:eEf:F:g:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
long_options, &optindex)) != -1)
{
switch (c)
*************** parse_psql_options(int argc, char *argv[
*** 419,424 ****
--- 433,440 ----
SetVariable(pset.vars, "ECHO", "errors");
break;
case 'c':
+ cmd_opt_is_used = true;
+
options->action_string = pg_strdup(optarg);
if (optarg[0] == '\\')
{
*************** parse_psql_options(int argc, char *argv[
*** 445,450 ****
--- 461,487 ----
pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
pset.popt.topt.fieldSep.separator_zero = false;
break;
+ case 'g':
+ {
+ GroupCommand *cmd = pg_malloc(sizeof(GroupCommand));
+ GroupCommand *ptr = pset.group_commands;
+
+ group_cmd_opt_is_used = true;
+
+ if (ptr == NULL)
+ pset.group_commands = cmd;
+ else
+ {
+ while (ptr->next != NULL)
+ ptr = ptr->next;
+
+ ptr->next = cmd;
+ }
+ cmd->next = NULL;
+ cmd->actions = pg_strdup(optarg);
+ options->action = ACT_GROUP_COMMANDS;
+ }
+ break;
case 'h':
options->host = pg_strdup(optarg);
break;
*************** parse_psql_options(int argc, char *argv[
*** 601,606 ****
--- 638,650 ----
}
}
+ if (cmd_opt_is_used && group_cmd_opt_is_used)
+ {
+ fprintf(stderr, _("%s: options -c/--command and -g/--group_command cannot be used together\n"),
+ pset.progname);
+ exit(EXIT_FAILURE);
+ }
+
/*
* if we still have arguments, use it as the database name and username
*/
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers