mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 00:03:09 -04:00
psql: Support multiple -c and -f options, and allow mixing them.
To support this, we must reconcile some historical anomalies in the behavior of -c. In particular, as a backward-incompatibility, -c no longer implies --no-psqlrc. Pavel Stehule (code) and Catalin Iacob (documentation). Review by Michael Paquier and myself. Proposed behavior per Tom Lane.
This commit is contained in:
parent
385f337c9f
commit
d5563d7df9
@ -38,9 +38,10 @@ PostgreSQL documentation
|
|||||||
<productname>PostgreSQL</productname>. It enables you to type in
|
<productname>PostgreSQL</productname>. It enables you to type in
|
||||||
queries interactively, issue them to
|
queries interactively, issue them to
|
||||||
<productname>PostgreSQL</productname>, and see the query results.
|
<productname>PostgreSQL</productname>, and see the query results.
|
||||||
Alternatively, input can be from a file. In addition, it provides a
|
Alternatively, input can be from a file or from command line
|
||||||
number of meta-commands and various shell-like features to
|
arguments. In addition, it provides a number of meta-commands and various
|
||||||
facilitate writing scripts and automating a wide variety of tasks.
|
shell-like features to facilitate writing scripts and automating a wide
|
||||||
|
variety of tasks.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@ -89,11 +90,10 @@ PostgreSQL documentation
|
|||||||
<term><option>--command=<replaceable class="parameter">command</replaceable></></term>
|
<term><option>--command=<replaceable class="parameter">command</replaceable></></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Specifies that <application>psql</application> is to execute one
|
Specifies that <application>psql</application> is to execute the given
|
||||||
command string, <replaceable class="parameter">command</replaceable>,
|
command string, <replaceable class="parameter">command</replaceable>.
|
||||||
and then exit. This is useful in shell scripts. Start-up files
|
This option can be repeated and combined in any order with
|
||||||
(<filename>psqlrc</filename> and <filename>~/.psqlrc</filename>) are
|
the <option>-f</option> option.
|
||||||
ignored with this option.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<replaceable class="parameter">command</replaceable> must be either
|
<replaceable class="parameter">command</replaceable> must be either
|
||||||
@ -102,25 +102,34 @@ PostgreSQL documentation
|
|||||||
or a single backslash command. Thus you cannot mix
|
or a single backslash command. Thus you cannot mix
|
||||||
<acronym>SQL</acronym> and <application>psql</application>
|
<acronym>SQL</acronym> and <application>psql</application>
|
||||||
meta-commands with this option. To achieve that, you could
|
meta-commands with this option. To achieve that, you could
|
||||||
pipe the string into <application>psql</application>, for example:
|
use repeated <option>-c</option> options or pipe the string
|
||||||
|
into <application>psql</application>, for example:
|
||||||
|
<literal>psql -c '\x' -c 'SELECT * FROM foo;'</literal> or
|
||||||
<literal>echo '\x \\ SELECT * FROM foo;' | psql</literal>.
|
<literal>echo '\x \\ SELECT * FROM foo;' | psql</literal>.
|
||||||
(<literal>\\</> is the separator meta-command.)
|
(<literal>\\</> is the separator meta-command.)
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If the command string contains multiple SQL commands, they are
|
Each command string passed to <option>-c</option> is sent to the server
|
||||||
processed in a single transaction, unless there are explicit
|
as a single query. Because of this, the server executes it as a single
|
||||||
<command>BEGIN</>/<command>COMMIT</> commands included in the
|
transaction, even if a command string contains
|
||||||
string to divide it into multiple transactions. This is
|
multiple <acronym>SQL</acronym> commands, unless there are
|
||||||
different from the behavior when the same string is fed to
|
explicit <command>BEGIN</>/<command>COMMIT</> commands included in the
|
||||||
<application>psql</application>'s standard input. Also, only
|
string to divide it into multiple transactions. Also, the server only
|
||||||
the result of the last SQL command is returned.
|
returns the result of the last <acronym>SQL</acronym> command to the
|
||||||
|
client. This is different from the behavior when the same string with
|
||||||
|
multiple <acronym>SQL</acronym> commands is fed
|
||||||
|
to <application>psql</application>'s standard input because
|
||||||
|
then <application>psql</application> sends each <acronym>SQL</acronym>
|
||||||
|
command separately.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Because of these legacy behaviors, putting more than one command in
|
Putting more than one command in the <option>-c</option> string often
|
||||||
the <option>-c</option> string often has unexpected results. It's
|
has unexpected results. This is a result of the fact that the whole
|
||||||
better to feed multiple commands to <application>psql</application>'s
|
string is sent to the server as a single query.
|
||||||
standard input, either using <application>echo</application> as
|
It's better to use repeated <option>-c</option> commands or feed
|
||||||
illustrated above, or via a shell here-document, for example:
|
multiple commands to <application>psql</application>'s standard input,
|
||||||
|
either using <application>echo</application> as illustrated above, or
|
||||||
|
via a shell here-document, for example:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
psql <<EOF
|
psql <<EOF
|
||||||
\x
|
\x
|
||||||
@ -185,9 +194,11 @@ EOF
|
|||||||
<para>
|
<para>
|
||||||
Use the file <replaceable class="parameter">filename</replaceable>
|
Use the file <replaceable class="parameter">filename</replaceable>
|
||||||
as the source of commands instead of reading commands interactively.
|
as the source of commands instead of reading commands interactively.
|
||||||
After the file is processed, <application>psql</application>
|
This option can be repeated and combined in any order with
|
||||||
terminates. This is in many ways equivalent to the meta-command
|
the <option>-c</option> option. After the commands in
|
||||||
<command>\i</command>.
|
every <option>-c</option> command string and <option>-f</option> file
|
||||||
|
are processed, <application>psql</application> terminates. This option
|
||||||
|
is in many ways equivalent to the meta-command <command>\i</command>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -539,20 +550,21 @@ EOF
|
|||||||
<term><option>--single-transaction</option></term>
|
<term><option>--single-transaction</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
When <application>psql</application> executes a script, adding
|
When <application>psql</application> executes commands from a script
|
||||||
this option wraps <command>BEGIN</>/<command>COMMIT</> around the
|
and/or a <option>-c</option> option, adding this option
|
||||||
script to execute it as a single transaction. This ensures that
|
wraps <command>BEGIN</>/<command>COMMIT</> around all of those
|
||||||
either all the commands complete successfully, or no changes are
|
commands as a whole to execute them as a single transaction. This
|
||||||
applied.
|
ensures that either all the commands complete successfully, or no
|
||||||
|
changes are applied.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If the script itself uses <command>BEGIN</>, <command>COMMIT</>,
|
If the commands themselves
|
||||||
|
contain <command>BEGIN</>, <command>COMMIT</>,
|
||||||
or <command>ROLLBACK</>, this option will not have the desired
|
or <command>ROLLBACK</>, this option will not have the desired
|
||||||
effects.
|
effects. Also, if an individual command cannot be executed inside a
|
||||||
Also, if the script contains any command that cannot be executed
|
transaction block, specifying this option will cause the whole
|
||||||
inside a transaction block, specifying this option will cause that
|
transaction to fail.
|
||||||
command (and hence the whole transaction) to fail.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -3725,7 +3737,7 @@ PSQL_EDITOR_LINENUMBER_ARG='--line '
|
|||||||
<term><filename>psqlrc</filename> and <filename>~/.psqlrc</filename></term>
|
<term><filename>psqlrc</filename> and <filename>~/.psqlrc</filename></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Unless it is passed an <option>-X</option> or <option>-c</option> option,
|
Unless it is passed an <option>-X</option> option,
|
||||||
<application>psql</application> attempts to read and execute commands
|
<application>psql</application> attempts to read and execute commands
|
||||||
from the system-wide startup file (<filename>psqlrc</filename>) and then
|
from the system-wide startup file (<filename>psqlrc</filename>) and then
|
||||||
the user's personal startup file (<filename>~/.psqlrc</filename>), after
|
the user's personal startup file (<filename>~/.psqlrc</filename>), after
|
||||||
@ -3819,6 +3831,12 @@ PSQL_EDITOR_LINENUMBER_ARG='--line '
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Before <productname>PostgreSQL</productname> 9.6, <option>-c</option>
|
||||||
|
implied <option>-X</option>; this is no longer the case.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -916,7 +916,7 @@ exec_command(const char *cmd,
|
|||||||
include_relative = (strcmp(cmd, "ir") == 0
|
include_relative = (strcmp(cmd, "ir") == 0
|
||||||
|| strcmp(cmd, "include_relative") == 0);
|
|| strcmp(cmd, "include_relative") == 0);
|
||||||
expand_tilde(&fname);
|
expand_tilde(&fname);
|
||||||
success = (process_file(fname, false, include_relative) == EXIT_SUCCESS);
|
success = (process_file(fname, include_relative) == EXIT_SUCCESS);
|
||||||
free(fname);
|
free(fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2288,13 +2288,12 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
|
|||||||
* the file from where the currently processed file (if any) is located.
|
* the file from where the currently processed file (if any) is located.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
process_file(char *filename, bool single_txn, bool use_relative_path)
|
process_file(char *filename, bool use_relative_path)
|
||||||
{
|
{
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
int result;
|
int result;
|
||||||
char *oldfilename;
|
char *oldfilename;
|
||||||
char relpath[MAXPGPATH];
|
char relpath[MAXPGPATH];
|
||||||
PGresult *res;
|
|
||||||
|
|
||||||
if (!filename)
|
if (!filename)
|
||||||
{
|
{
|
||||||
@ -2339,37 +2338,8 @@ process_file(char *filename, bool single_txn, bool use_relative_path)
|
|||||||
oldfilename = pset.inputfile;
|
oldfilename = pset.inputfile;
|
||||||
pset.inputfile = filename;
|
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);
|
||||||
|
|
||||||
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)
|
if (fd != stdin)
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ typedef enum _backslashResult
|
|||||||
extern backslashResult HandleSlashCmds(PsqlScanState scan_state,
|
extern backslashResult HandleSlashCmds(PsqlScanState scan_state,
|
||||||
PQExpBuffer query_buf);
|
PQExpBuffer query_buf);
|
||||||
|
|
||||||
extern int process_file(char *filename, bool single_txn, bool use_relative_path);
|
extern int process_file(char *filename, bool use_relative_path);
|
||||||
|
|
||||||
extern bool do_pset(const char *param,
|
extern bool do_pset(const char *param,
|
||||||
const char *value,
|
const char *value,
|
||||||
|
@ -50,13 +50,24 @@ PsqlSettings pset;
|
|||||||
*/
|
*/
|
||||||
enum _actions
|
enum _actions
|
||||||
{
|
{
|
||||||
ACT_NOTHING = 0,
|
|
||||||
ACT_SINGLE_SLASH,
|
|
||||||
ACT_LIST_DB,
|
|
||||||
ACT_SINGLE_QUERY,
|
ACT_SINGLE_QUERY,
|
||||||
|
ACT_SINGLE_SLASH,
|
||||||
ACT_FILE
|
ACT_FILE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct SimpleActionListCell
|
||||||
|
{
|
||||||
|
struct SimpleActionListCell *next;
|
||||||
|
int action;
|
||||||
|
char *val;
|
||||||
|
} SimpleActionListCell;
|
||||||
|
|
||||||
|
typedef struct SimpleActionList
|
||||||
|
{
|
||||||
|
SimpleActionListCell *head;
|
||||||
|
SimpleActionListCell *tail;
|
||||||
|
} SimpleActionList;
|
||||||
|
|
||||||
struct adhoc_opts
|
struct adhoc_opts
|
||||||
{
|
{
|
||||||
char *dbname;
|
char *dbname;
|
||||||
@ -64,11 +75,11 @@ struct adhoc_opts
|
|||||||
char *port;
|
char *port;
|
||||||
char *username;
|
char *username;
|
||||||
char *logfilename;
|
char *logfilename;
|
||||||
enum _actions action;
|
|
||||||
char *action_string;
|
|
||||||
bool no_readline;
|
bool no_readline;
|
||||||
bool no_psqlrc;
|
bool no_psqlrc;
|
||||||
bool single_txn;
|
bool single_txn;
|
||||||
|
bool list_dbs;
|
||||||
|
SimpleActionList actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void parse_psql_options(int argc, char *argv[],
|
static void parse_psql_options(int argc, char *argv[],
|
||||||
@ -76,6 +87,8 @@ static void parse_psql_options(int argc, char *argv[],
|
|||||||
static void process_psqlrc(char *argv0);
|
static void process_psqlrc(char *argv0);
|
||||||
static void process_psqlrc_file(char *filename);
|
static void process_psqlrc_file(char *filename);
|
||||||
static void showVersion(void);
|
static void showVersion(void);
|
||||||
|
static void simple_action_list_append(SimpleActionList *list,
|
||||||
|
int action, const char *val);
|
||||||
static void EstablishVariableSpace(void);
|
static void EstablishVariableSpace(void);
|
||||||
|
|
||||||
#define NOPAGER 0
|
#define NOPAGER 0
|
||||||
@ -159,6 +172,9 @@ main(int argc, char *argv[])
|
|||||||
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
|
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
|
||||||
SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
|
SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
|
||||||
|
|
||||||
|
options.actions.head = NULL;
|
||||||
|
options.actions.tail = NULL;
|
||||||
|
|
||||||
parse_psql_options(argc, argv, &options);
|
parse_psql_options(argc, argv, &options);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -166,14 +182,11 @@ main(int argc, char *argv[])
|
|||||||
* as if the user had specified "-f -". This lets single-transaction mode
|
* as if the user had specified "-f -". This lets single-transaction mode
|
||||||
* work in this case.
|
* work in this case.
|
||||||
*/
|
*/
|
||||||
if (options.action == ACT_NOTHING && pset.notty)
|
if (options.actions.head == NULL && pset.notty)
|
||||||
{
|
simple_action_list_append(&options.actions, ACT_FILE, NULL);
|
||||||
options.action = ACT_FILE;
|
|
||||||
options.action_string = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bail out if -1 was specified but will be ignored. */
|
/* Bail out if -1 was specified but will be ignored. */
|
||||||
if (options.single_txn && options.action != ACT_FILE && options.action == ACT_NOTHING)
|
if (options.single_txn && options.actions.head == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, _("%s: -1 can only be used in non-interactive mode\n"), pset.progname);
|
fprintf(stderr, _("%s: -1 can only be used in non-interactive mode\n"), pset.progname);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -217,8 +230,7 @@ main(int argc, char *argv[])
|
|||||||
keywords[3] = "password";
|
keywords[3] = "password";
|
||||||
values[3] = password;
|
values[3] = password;
|
||||||
keywords[4] = "dbname";
|
keywords[4] = "dbname";
|
||||||
values[4] = (options.action == ACT_LIST_DB &&
|
values[4] = (options.list_dbs && options.dbname == NULL) ?
|
||||||
options.dbname == NULL) ?
|
|
||||||
"postgres" : options.dbname;
|
"postgres" : options.dbname;
|
||||||
keywords[5] = "fallback_application_name";
|
keywords[5] = "fallback_application_name";
|
||||||
values[5] = pset.progname;
|
values[5] = pset.progname;
|
||||||
@ -259,7 +271,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
SyncVariables();
|
SyncVariables();
|
||||||
|
|
||||||
if (options.action == ACT_LIST_DB)
|
if (options.list_dbs)
|
||||||
{
|
{
|
||||||
int success;
|
int success;
|
||||||
|
|
||||||
@ -279,52 +291,91 @@ main(int argc, char *argv[])
|
|||||||
pset.progname, options.logfilename, strerror(errno));
|
pset.progname, options.logfilename, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (!options.no_psqlrc)
|
||||||
* Now find something to do
|
process_psqlrc(argv[0]);
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* process file given by -f
|
* If any actions were given by caller, process them in the order in
|
||||||
|
* which they were specified.
|
||||||
*/
|
*/
|
||||||
if (options.action == ACT_FILE)
|
if (options.actions.head != NULL)
|
||||||
{
|
{
|
||||||
if (!options.no_psqlrc)
|
PGresult *res;
|
||||||
process_psqlrc(argv[0]);
|
SimpleActionListCell *cell;
|
||||||
|
|
||||||
successResult = process_file(options.action_string, options.single_txn, false);
|
successResult = EXIT_SUCCESS; /* silence compiler */
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if (options.single_txn)
|
||||||
* process slash command if one was given to -c
|
{
|
||||||
*/
|
if ((res = PSQLexec("BEGIN")) == NULL)
|
||||||
else if (options.action == ACT_SINGLE_SLASH)
|
{
|
||||||
{
|
if (pset.on_error_stop)
|
||||||
PsqlScanState scan_state;
|
{
|
||||||
|
successResult = EXIT_USER;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
|
||||||
if (pset.echo == PSQL_ECHO_ALL)
|
for (cell = options.actions.head; cell; cell = cell->next)
|
||||||
puts(options.action_string);
|
{
|
||||||
|
if (cell->action == ACT_SINGLE_QUERY)
|
||||||
|
{
|
||||||
|
if (pset.echo == PSQL_ECHO_ALL)
|
||||||
|
puts(cell->val);
|
||||||
|
|
||||||
scan_state = psql_scan_create();
|
successResult = SendQuery(cell->val)
|
||||||
psql_scan_setup(scan_state,
|
? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
options.action_string,
|
}
|
||||||
strlen(options.action_string));
|
else if (cell->action == ACT_SINGLE_SLASH)
|
||||||
|
{
|
||||||
|
PsqlScanState scan_state;
|
||||||
|
|
||||||
successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
|
if (pset.echo == PSQL_ECHO_ALL)
|
||||||
? EXIT_SUCCESS : EXIT_FAILURE;
|
puts(cell->val);
|
||||||
|
|
||||||
psql_scan_destroy(scan_state);
|
scan_state = psql_scan_create();
|
||||||
}
|
psql_scan_setup(scan_state,
|
||||||
|
cell->val,
|
||||||
|
strlen(cell->val));
|
||||||
|
|
||||||
/*
|
successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
|
||||||
* If the query given to -c was a normal one, send it
|
? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
*/
|
|
||||||
else if (options.action == ACT_SINGLE_QUERY)
|
|
||||||
{
|
|
||||||
if (pset.echo == PSQL_ECHO_ALL)
|
|
||||||
puts(options.action_string);
|
|
||||||
|
|
||||||
successResult = SendQuery(options.action_string)
|
psql_scan_destroy(scan_state);
|
||||||
? EXIT_SUCCESS : EXIT_FAILURE;
|
}
|
||||||
|
else if (cell->action == ACT_FILE)
|
||||||
|
{
|
||||||
|
successResult = process_file(cell->val, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* should never come here */
|
||||||
|
Assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (successResult != EXIT_SUCCESS && pset.on_error_stop)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.single_txn)
|
||||||
|
{
|
||||||
|
if ((res = PSQLexec("COMMIT")) == NULL)
|
||||||
|
{
|
||||||
|
if (pset.on_error_stop)
|
||||||
|
{
|
||||||
|
successResult = EXIT_USER;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -332,9 +383,6 @@ main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!options.no_psqlrc)
|
|
||||||
process_psqlrc(argv[0]);
|
|
||||||
|
|
||||||
connection_warnings(true);
|
connection_warnings(true);
|
||||||
if (!pset.quiet)
|
if (!pset.quiet)
|
||||||
printf(_("Type \"help\" for help.\n\n"));
|
printf(_("Type \"help\" for help.\n\n"));
|
||||||
@ -419,14 +467,14 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
|
|||||||
SetVariable(pset.vars, "ECHO", "errors");
|
SetVariable(pset.vars, "ECHO", "errors");
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
options->action_string = pg_strdup(optarg);
|
|
||||||
if (optarg[0] == '\\')
|
if (optarg[0] == '\\')
|
||||||
{
|
simple_action_list_append(&options->actions,
|
||||||
options->action = ACT_SINGLE_SLASH;
|
ACT_SINGLE_SLASH,
|
||||||
options->action_string++;
|
pstrdup(optarg + 1));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
options->action = ACT_SINGLE_QUERY;
|
simple_action_list_append(&options->actions,
|
||||||
|
ACT_SINGLE_QUERY,
|
||||||
|
pstrdup(optarg));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
options->dbname = pg_strdup(optarg);
|
options->dbname = pg_strdup(optarg);
|
||||||
@ -438,8 +486,9 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
|
|||||||
SetVariableBool(pset.vars, "ECHO_HIDDEN");
|
SetVariableBool(pset.vars, "ECHO_HIDDEN");
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
options->action = ACT_FILE;
|
simple_action_list_append(&options->actions,
|
||||||
options->action_string = pg_strdup(optarg);
|
ACT_FILE,
|
||||||
|
pg_strdup(optarg));
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
|
pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
|
||||||
@ -452,7 +501,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
|
|||||||
pset.popt.topt.format = PRINT_HTML;
|
pset.popt.topt.format = PRINT_HTML;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
options->action = ACT_LIST_DB;
|
options->list_dbs = true;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
options->logfilename = pg_strdup(optarg);
|
options->logfilename = pg_strdup(optarg);
|
||||||
@ -675,11 +724,11 @@ process_psqlrc_file(char *filename)
|
|||||||
|
|
||||||
/* check for minor version first, then major, then no version */
|
/* check for minor version first, then major, then no version */
|
||||||
if (access(psqlrc_minor, R_OK) == 0)
|
if (access(psqlrc_minor, R_OK) == 0)
|
||||||
(void) process_file(psqlrc_minor, false, false);
|
(void) process_file(psqlrc_minor, false);
|
||||||
else if (access(psqlrc_major, R_OK) == 0)
|
else if (access(psqlrc_major, R_OK) == 0)
|
||||||
(void) process_file(psqlrc_major, false, false);
|
(void) process_file(psqlrc_major, false);
|
||||||
else if (access(filename, R_OK) == 0)
|
else if (access(filename, R_OK) == 0)
|
||||||
(void) process_file(filename, false, false);
|
(void) process_file(filename, false);
|
||||||
|
|
||||||
free(psqlrc_minor);
|
free(psqlrc_minor);
|
||||||
free(psqlrc_major);
|
free(psqlrc_major);
|
||||||
@ -893,6 +942,39 @@ show_context_hook(const char *newval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support for list of actions. SimpleStringList cannot be used due possible
|
||||||
|
* combination different actions with the requirement to save the order.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
simple_action_list_append(SimpleActionList *list, int action, const char *val)
|
||||||
|
{
|
||||||
|
SimpleActionListCell *cell;
|
||||||
|
size_t vallen = 0;
|
||||||
|
|
||||||
|
if (val)
|
||||||
|
vallen = strlen(val);
|
||||||
|
|
||||||
|
cell = (SimpleActionListCell *)
|
||||||
|
pg_malloc(offsetof(SimpleActionListCell, val) + vallen + 1);
|
||||||
|
|
||||||
|
cell->next = NULL;
|
||||||
|
cell->action = action;
|
||||||
|
if (val)
|
||||||
|
{
|
||||||
|
cell->val = pg_malloc(vallen + 1);
|
||||||
|
strcpy(cell->val, val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cell->val = NULL;
|
||||||
|
|
||||||
|
if (list->tail)
|
||||||
|
list->tail->next = cell;
|
||||||
|
else
|
||||||
|
list->head = cell;
|
||||||
|
list->tail = cell;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
EstablishVariableSpace(void)
|
EstablishVariableSpace(void)
|
||||||
{
|
{
|
||||||
|
@ -400,7 +400,7 @@ sub poll_query_until
|
|||||||
while ($attempts < $max_attempts)
|
while ($attempts < $max_attempts)
|
||||||
{
|
{
|
||||||
my $cmd =
|
my $cmd =
|
||||||
[ 'psql', '-At', '-c', $query, '-d', $self->connstr($dbname) ];
|
[ 'psql', '-XAt', '-c', $query, '-d', $self->connstr($dbname) ];
|
||||||
my $result = IPC::Run::run $cmd, '>', \$stdout, '2>', \$stderr;
|
my $result = IPC::Run::run $cmd, '>', \$stdout, '2>', \$stderr;
|
||||||
|
|
||||||
chomp($stdout);
|
chomp($stdout);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user