Hi 2015-08-26 13:12 GMT+02:00 Pavel Stehule <pavel.steh...@gmail.com>:
> Hi > > 2015-07-29 21:05 GMT+02:00 Pavel Stehule <pavel.steh...@gmail.com>: > >> Hi >> >> here is proof concept patch >> >> It should be cleaned, but it demonstrates a work well >> >> [pavel@localhost psql]$ ./psql -C 'select 10 x; select 20 y;' -C "\l" >> postgres >> x >> ---- >> 10 >> (1 row) >> >> y >> ---- >> 20 >> (1 row) >> >> List of databases >> Name | Owner | Encoding | Collate | Ctype | Access >> privileges >> >> -----------+----------+----------+-------------+-------------+----------------------- >> postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | >> template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | >> =c/postgres + >> | | | | | >> postgres=CTc/postgres >> template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | >> =c/postgres + >> | | | | | >> postgres=CTc/postgres >> (3 rows) >> >> >> 2015-07-28 18:46 GMT+02:00 Andrew Dunstan <and...@dunslane.net>: >> >>> >>> On 07/28/2015 11:52 AM, Pavel Stehule wrote: >>> >>>> >>>> >>>> 2015-07-28 15:16 GMT+02:00 Andrew Dunstan <and...@dunslane.net <mailto: >>>> and...@dunslane.net>>: >>>> >>>> >>>> On 07/28/2015 12:08 AM, Pavel Stehule wrote: >>>> >>>> >>>> >>>> 2015-07-28 5:24 GMT+02:00 Pavel Stehule >>>> <pavel.steh...@gmail.com <mailto:pavel.steh...@gmail.com> >>>> <mailto:pavel.steh...@gmail.com >>>> <mailto:pavel.steh...@gmail.com>>>: >>>> >>>> >>>> >>>> 2015-07-27 21:57 GMT+02:00 Andrew Dunstan >>>> <and...@dunslane.net <mailto:and...@dunslane.net> >>>> <mailto:and...@dunslane.net <mailto:and...@dunslane.net>>>: >>>> >>>> >>>> >>>> On 07/27/2015 02:53 PM, Pavel Stehule wrote: >>>> >>>> >>>> >>>> >>>> >>>> I am trying to run parallel execution >>>> >>>> psql -At -c "select datname from pg_database" >>>> postgres | >>>> xargs -n 1 -P 3 psql -c "select current_database()" >>>> >>>> >>>> >>>> >>>> I don't think it's going to be a hugely important >>>> feature, but >>>> I don't see a problem with creating a new option (-C >>>> seems >>>> fine) which would have the same effect as if the >>>> arguments >>>> were contatenated into a file which is then used with >>>> -f. IIRC >>>> -c has some special characteristics which means it's >>>> probably >>>> best not to try to extend it for this feature. >>>> >>>> >>>> ok, I'll try to write patch. >>>> >>>> >>>> I have a question. Can be -C option multiple? >>>> >>>> The SQL is without problem, but what about \x command? >>>> >>>> postgres=# \dt \dn select 10; >>>> No relations found. >>>> List of schemas >>>> ┌──────┬───────┐ >>>> │ Name │ Owner │ >>>> ╞══════╪═══════╡ >>>> └──────┴───────┘ >>>> (0 rows) >>>> >>>> \dn: extra argument "10;" ignored >>>> >>>> >>>> >>>> I don't understand the question. >>>> >>>> You should include one sql or psql command per -C option, ISTM. e.g. >>>> >>>> psql -C '\dt' -C '\dn' -C 'select 10;' >>>> >>>> >>>> Isn't that what we're talking about with this whole proposal? >>>> >>>> >>>> >>>> I am searching some agreement, how to solve a current "-c" limits. I am >>>> 100% for >>> psql -C '\dt' -C '\dn' -C 'select 10;' <<< >>>> >>>> >>>> >>> I think you're probably best off leaving -c alone. If there are issues >>> to be solved for -c they should be handled separately from the feature we >>> agree on. >>> >>> cheers >>> >>> andrew >>> >>> >>> >>> >> > here is finished patch - cleaned, tested - the significant change is using > -g --group-command instead "-C" > > [pavel@localhost psql]$ ./psql postgres -g "select 10; select 20" -g > "select 30" > ?column? > ---------- > 10 > (1 row) > > ?column? > ---------- > 20 > (1 row) > > ?column? > ---------- > 30 > (1 row) > > Regards > > with -1 option support > Pavel >
commit bef661b7c822f4fe9f004bf55645a3e47e514bc8 Author: Pavel Stehule <pavel.steh...@gooddata.com> Date: Wed Aug 26 13:03:56 2015 +0200 inital diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index f996865..750c4ae 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -223,6 +223,20 @@ EOF </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 index 6181a61..277e980 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -2292,7 +2292,6 @@ process_file(char *filename, bool single_txn, bool use_relative_path) int result; char *oldfilename; char relpath[MAXPGPATH]; - PGresult *res; if (!filename) { @@ -2337,37 +2336,8 @@ process_file(char *filename, bool single_txn, bool use_relative_path) 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); + result = MainLoop(fd, single_txn); - 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); @@ -2375,8 +2345,6 @@ error: return result; } - - static const char * _align2string(enum printFormat in) { diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index d3e3114..55aa423 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -79,6 +79,8 @@ usage(unsigned short int pager) 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 e.g.: -v ON_ERROR_STOP=1\n")); diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c index b6cef94..4147238 100644 --- a/src/bin/psql/mainloop.c +++ b/src/bin/psql/mainloop.c @@ -24,8 +24,8 @@ * This loop is re-entrant. May be called by \i command * which reads input from a file. */ -int -MainLoop(FILE *source) +static int +_MainLoop(FILE *source) { PsqlScanState scan_state; /* lexer working state */ volatile PQExpBuffer query_buf; /* buffer for query being accumulated */ @@ -43,6 +43,7 @@ MainLoop(FILE *source) 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; @@ -135,6 +136,20 @@ MainLoop(FILE *source) 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); @@ -451,6 +466,43 @@ MainLoop(FILE *source) 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 index 8f1325c..53c9a11 100644 --- a/src/bin/psql/mainloop.h +++ b/src/bin/psql/mainloop.h @@ -10,6 +10,6 @@ #include "postgres_fe.h" -int MainLoop(FILE *source); +int MainLoop(FILE *source, bool single_txn); #endif /* MAINLOOP_H */ diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h index d34dc28..d23d67a 100644 --- a/src/bin/psql/settings.h +++ b/src/bin/psql/settings.h @@ -77,6 +77,12 @@ enum trivalue TRI_YES }; +typedef struct _GroupCommand +{ + char *actions; + struct _GroupCommand *next; +} GroupCommand; + typedef struct _psqlSettings { PGconn *db; /* connection to backend */ @@ -129,6 +135,7 @@ typedef struct _psqlSettings const char *prompt2; const char *prompt3; PGVerbosity verbosity; /* current error verbosity level */ + GroupCommand *group_commands; } PsqlSettings; extern PsqlSettings pset; diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 28ba75a..4c9383f 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -54,7 +54,8 @@ enum _actions ACT_SINGLE_SLASH, ACT_LIST_DB, ACT_SINGLE_QUERY, - ACT_FILE + ACT_FILE, + ACT_GROUP_COMMANDS }; struct adhoc_opts @@ -158,6 +159,8 @@ main(int argc, char *argv[]) SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2); SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); + pset.group_commands = NULL; + parse_psql_options(argc, argv, &options); /* @@ -326,6 +329,13 @@ main(int argc, char *argv[]) ? 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 */ @@ -338,7 +348,7 @@ main(int argc, char *argv[]) if (!pset.quiet) printf(_("Type \"help\" for help.\n\n")); initializeInput(options.no_readline ? 0 : 1); - successResult = MainLoop(stdin); + successResult = MainLoop(stdin, false); } /* clean up */ @@ -370,6 +380,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) {"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'}, @@ -401,9 +412,12 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) 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:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01", + 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) @@ -418,6 +432,8 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) SetVariable(pset.vars, "ECHO", "errors"); break; case 'c': + cmd_opt_is_used = true; + options->action_string = pg_strdup(optarg); if (optarg[0] == '\\') { @@ -444,6 +460,27 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) 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; @@ -600,6 +637,13 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) } } + 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