Hi 2015-09-21 16:46 GMT+02:00 Adam Brightwell < adam.brightw...@crunchydatasolutions.com>:
> 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 - adam.brightw...@crunchydatasolutions.com > 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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers