Skip to content

Commit fcbbf82

Browse files
committed
Code and docs review for multiple -c and -f options in psql.
Commit d5563d7 drew complaints from Coverity, which quite correctly complained that one copy of each -c or -f string was being leaked. What's more, simple_action_list_append was allocating enough space for still a third copy of each string as part of the SimpleActionListCell, even though that coding method had been superseded by a separate strdup operation. There were some other minor coding infelicities too. The documentation needed more work as well, eg it forgot to explain that -c causes psql not to accept any interactive input.
1 parent a91bdf6 commit fcbbf82

File tree

2 files changed

+121
-112
lines changed

2 files changed

+121
-112
lines changed

doc/src/sgml/ref/psql-ref.sgml

Lines changed: 79 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ PostgreSQL documentation
3939
queries interactively, issue them to
4040
<productname>PostgreSQL</productname>, and see the query results.
4141
Alternatively, input can be from a file or from command line
42-
arguments. In addition, it provides a number of meta-commands and various
43-
shell-like features to facilitate writing scripts and automating a wide
44-
variety of tasks.
42+
arguments. In addition, <application>psql</application> provides a
43+
number of meta-commands and various shell-like features to
44+
facilitate writing scripts and automating a wide variety of tasks.
4545
</para>
4646
</refsect1>
4747

@@ -90,42 +90,50 @@ PostgreSQL documentation
9090
<term><option>--command=<replaceable class="parameter">command</replaceable></></term>
9191
<listitem>
9292
<para>
93-
Specifies that <application>psql</application> is to execute the given
94-
command string, <replaceable class="parameter">command</replaceable>.
95-
This option can be repeated and combined in any order with
96-
the <option>-f</option> option.
93+
Specifies that <application>psql</application> is to execute the given
94+
command string, <replaceable class="parameter">command</replaceable>.
95+
This option can be repeated and combined in any order with
96+
the <option>-f</option> option. When either <option>-c</option>
97+
or <option>-f</option> is specified, <application>psql</application>
98+
does not read commands from standard input; instead it terminates
99+
after processing all the <option>-c</option> and <option>-f</option>
100+
options in sequence.
97101
</para>
98102
<para>
99-
<replaceable class="parameter">command</replaceable> must be either
100-
a command string that is completely parsable by the server (i.e.,
101-
it contains no <application>psql</application>-specific features),
102-
or a single backslash command. Thus you cannot mix
103-
<acronym>SQL</acronym> and <application>psql</application>
104-
meta-commands with this option. To achieve that, you could
105-
use repeated <option>-c</option> options or pipe the string
106-
into <application>psql</application>, for example:
107-
<literal>psql -c '\x' -c 'SELECT * FROM foo;'</literal> or
108-
<literal>echo '\x \\ SELECT * FROM foo;' | psql</literal>.
109-
(<literal>\\</> is the separator meta-command.)
103+
<replaceable class="parameter">command</replaceable> must be either
104+
a command string that is completely parsable by the server (i.e.,
105+
it contains no <application>psql</application>-specific features),
106+
or a single backslash command. Thus you cannot mix
107+
<acronym>SQL</acronym> and <application>psql</application>
108+
meta-commands within a <option>-c</option> option. To achieve that,
109+
you could use repeated <option>-c</option> options or pipe the string
110+
into <application>psql</application>, for example:
111+
<programlisting>
112+
psql -c '\x' -c 'SELECT * FROM foo;'
113+
</programlisting>
114+
or
115+
<programlisting>
116+
echo '\x \\ SELECT * FROM foo;' | psql
117+
</programlisting>
118+
(<literal>\\</> is the separator meta-command.)
110119
</para>
111120
<para>
112-
Each command string passed to <option>-c</option> is sent to the server
113-
as a single query. Because of this, the server executes it as a single
114-
transaction, even if a command string contains
115-
multiple <acronym>SQL</acronym> commands, unless there are
116-
explicit <command>BEGIN</>/<command>COMMIT</> commands included in the
117-
string to divide it into multiple transactions. Also, the server only
118-
returns the result of the last <acronym>SQL</acronym> command to the
119-
client. This is different from the behavior when the same string with
120-
multiple <acronym>SQL</acronym> commands is fed
121-
to <application>psql</application>'s standard input because
122-
then <application>psql</application> sends each <acronym>SQL</acronym>
123-
command separately.
121+
Each <acronym>SQL</acronym> command string passed
122+
to <option>-c</option> is sent to the server as a single query.
123+
Because of this, the server executes it as a single transaction even
124+
if the string contains multiple <acronym>SQL</acronym> commands,
125+
unless there are explicit <command>BEGIN</>/<command>COMMIT</>
126+
commands included in the string to divide it into multiple
127+
transactions. Also, <application>psql</application> only prints the
128+
result of the last <acronym>SQL</acronym> command in the string.
129+
This is different from the behavior when the same string is read from
130+
a file or fed to <application>psql</application>'s standard input,
131+
because then <application>psql</application> sends
132+
each <acronym>SQL</acronym> command separately.
124133
</para>
125134
<para>
126-
Putting more than one command in the <option>-c</option> string often
127-
has unexpected results. This is a result of the fact that the whole
128-
string is sent to the server as a single query.
135+
Because of this behavior, putting more than one command in a
136+
single <option>-c</option> string often has unexpected results.
129137
It's better to use repeated <option>-c</option> commands or feed
130138
multiple commands to <application>psql</application>'s standard input,
131139
either using <application>echo</application> as illustrated above, or
@@ -192,18 +200,26 @@ EOF
192200
<term><option>--file=<replaceable class="parameter">filename</replaceable></></term>
193201
<listitem>
194202
<para>
195-
Use the file <replaceable class="parameter">filename</replaceable>
196-
as the source of commands instead of reading commands interactively.
197-
This option can be repeated and combined in any order with
198-
the <option>-c</option> option. After the commands in
199-
every <option>-c</option> command string and <option>-f</option> file
200-
are processed, <application>psql</application> terminates. This option
201-
is in many ways equivalent to the meta-command <command>\i</command>.
203+
Read commands from the
204+
file <replaceable class="parameter">filename</replaceable>,
205+
rather than standard input.
206+
This option can be repeated and combined in any order with
207+
the <option>-c</option> option. When either <option>-c</option>
208+
or <option>-f</option> is specified, <application>psql</application>
209+
does not read commands from standard input; instead it terminates
210+
after processing all the <option>-c</option> and <option>-f</option>
211+
options in sequence.
212+
Except for that, this option is largely equivalent to the
213+
meta-command <command>\i</command>.
202214
</para>
203215

204216
<para>
205217
If <replaceable>filename</replaceable> is <literal>-</literal>
206-
(hyphen), then standard input is read.
218+
(hyphen), then standard input is read until an EOF indication
219+
or <command>\q</> meta-command. This can be used to intersperse
220+
interactive input with input from files. Note however that Readline
221+
is not used in this case (much as if <option>-n</option> had been
222+
specified).
207223
</para>
208224

209225
<para>
@@ -550,12 +566,13 @@ EOF
550566
<term><option>--single-transaction</option></term>
551567
<listitem>
552568
<para>
553-
When <application>psql</application> executes commands from a script
554-
and/or a <option>-c</option> option, adding this option
555-
wraps <command>BEGIN</>/<command>COMMIT</> around all of those
556-
commands as a whole to execute them as a single transaction. This
557-
ensures that either all the commands complete successfully, or no
558-
changes are applied.
569+
This option can only be used in combination with one or more
570+
<option>-c</option> and/or <option>-f</option> options. It causes
571+
<application>psql</application> to issue a <command>BEGIN</> command
572+
before the first such option and a <command>COMMIT</> command after
573+
the last one, thereby wrapping all the commands into a single
574+
transaction. This ensures that either all the commands complete
575+
successfully, or no changes are applied.
559576
</para>
560577

561578
<para>
@@ -3799,16 +3816,6 @@ PSQL_EDITOR_LINENUMBER_ARG='--line '
37993816
<title>Notes</title>
38003817

38013818
<itemizedlist>
3802-
<listitem>
3803-
<para>
3804-
In an earlier life <application>psql</application> allowed the
3805-
first argument of a single-letter backslash command to start
3806-
directly after the command, without intervening whitespace.
3807-
As of <productname>PostgreSQL</productname> 8.4 this is no
3808-
longer allowed.
3809-
</para>
3810-
</listitem>
3811-
38123819
<listitem>
38133820
<para><application>psql</application> works best with servers of the same
38143821
or an older major version. Backslash commands are particularly likely
@@ -3824,17 +3831,28 @@ PSQL_EDITOR_LINENUMBER_ARG='--line '
38243831
If you want to use <application>psql</application> to connect to several
38253832
servers of different major versions, it is recommended that you use the
38263833
newest version of <application>psql</application>. Alternatively, you
3827-
can keep a copy of <application>psql</application> from each major
3828-
version around and be sure to use the version that matches the
3834+
can keep around a copy of <application>psql</application> from each
3835+
major version and be sure to use the version that matches the
38293836
respective server. But in practice, this additional complication should
38303837
not be necessary.
38313838
</para>
38323839
</listitem>
38333840

38343841
<listitem>
38353842
<para>
3836-
Before <productname>PostgreSQL</productname> 9.6, <option>-c</option>
3837-
implied <option>-X</option>; this is no longer the case.
3843+
Before <productname>PostgreSQL</productname> 9.6,
3844+
the <option>-c</option> option implied <option>-X</option>
3845+
(<option>--no-psqlrc</>); this is no longer the case.
3846+
</para>
3847+
</listitem>
3848+
3849+
<listitem>
3850+
<para>
3851+
Before <productname>PostgreSQL</productname> 8.4,
3852+
<application>psql</application> allowed the
3853+
first argument of a single-letter backslash command to start
3854+
directly after the command, without intervening whitespace.
3855+
Now, some whitespace is required.
38383856
</para>
38393857
</listitem>
38403858
</itemizedlist>

src/bin/psql/startup.c

Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ enum _actions
5858
typedef struct SimpleActionListCell
5959
{
6060
struct SimpleActionListCell *next;
61-
int action;
62-
char *val;
61+
enum _actions action;
62+
char *val;
6363
} SimpleActionListCell;
6464

6565
typedef struct SimpleActionList
@@ -84,11 +84,11 @@ struct adhoc_opts
8484

8585
static void parse_psql_options(int argc, char *argv[],
8686
struct adhoc_opts * options);
87+
static void simple_action_list_append(SimpleActionList *list,
88+
enum _actions action, const char *val);
8789
static void process_psqlrc(char *argv0);
8890
static void process_psqlrc_file(char *filename);
8991
static void showVersion(void);
90-
static void simple_action_list_append(SimpleActionList *list,
91-
int action, const char *val);
9292
static void EstablishVariableSpace(void);
9393

9494
#define NOPAGER 0
@@ -172,9 +172,6 @@ main(int argc, char *argv[])
172172
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
173173
SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
174174

175-
options.actions.head = NULL;
176-
options.actions.tail = NULL;
177-
178175
parse_psql_options(argc, argv, &options);
179176

180177
/*
@@ -298,13 +295,13 @@ main(int argc, char *argv[])
298295
process_psqlrc(argv[0]);
299296

300297
/*
301-
* If any actions were given by caller, process them in the order in
302-
* which they were specified.
298+
* If any actions were given by user, process them in the order in which
299+
* they were specified. Note single_txn is only effective in this mode.
303300
*/
304301
if (options.actions.head != NULL)
305302
{
306-
PGresult *res;
307-
SimpleActionListCell *cell;
303+
PGresult *res;
304+
SimpleActionListCell *cell;
308305

309306
successResult = EXIT_SUCCESS; /* silence compiler */
310307

@@ -341,8 +338,8 @@ main(int argc, char *argv[])
341338

342339
scan_state = psql_scan_create();
343340
psql_scan_setup(scan_state,
344-
cell->val,
345-
strlen(cell->val));
341+
cell->val,
342+
strlen(cell->val));
346343

347344
successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
348345
? EXIT_SUCCESS : EXIT_FAILURE;
@@ -356,7 +353,7 @@ main(int argc, char *argv[])
356353
else
357354
{
358355
/* should never come here */
359-
Assert(0);
356+
Assert(false);
360357
}
361358

362359
if (successResult != EXIT_SUCCESS && pset.on_error_stop)
@@ -473,11 +470,11 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
473470
if (optarg[0] == '\\')
474471
simple_action_list_append(&options->actions,
475472
ACT_SINGLE_SLASH,
476-
pstrdup(optarg + 1));
473+
optarg + 1);
477474
else
478475
simple_action_list_append(&options->actions,
479476
ACT_SINGLE_QUERY,
480-
pstrdup(optarg));
477+
optarg);
481478
break;
482479
case 'd':
483480
options->dbname = pg_strdup(optarg);
@@ -490,8 +487,8 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
490487
break;
491488
case 'f':
492489
simple_action_list_append(&options->actions,
493-
ACT_FILE,
494-
pg_strdup(optarg));
490+
ACT_FILE,
491+
optarg);
495492
break;
496493
case 'F':
497494
pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
@@ -672,6 +669,33 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
672669
}
673670

674671

672+
/*
673+
* Append a new item to the end of the SimpleActionList.
674+
* Note that "val" is copied if it's not NULL.
675+
*/
676+
static void
677+
simple_action_list_append(SimpleActionList *list,
678+
enum _actions action, const char *val)
679+
{
680+
SimpleActionListCell *cell;
681+
682+
cell = (SimpleActionListCell *) pg_malloc(sizeof(SimpleActionListCell));
683+
684+
cell->next = NULL;
685+
cell->action = action;
686+
if (val)
687+
cell->val = pg_strdup(val);
688+
else
689+
cell->val = NULL;
690+
691+
if (list->tail)
692+
list->tail->next = cell;
693+
else
694+
list->head = cell;
695+
list->tail = cell;
696+
}
697+
698+
675699
/*
676700
* Load .psqlrc file, if found.
677701
*/
@@ -945,39 +969,6 @@ show_context_hook(const char *newval)
945969
}
946970

947971

948-
/*
949-
* Support for list of actions. SimpleStringList cannot be used due possible
950-
* combination different actions with the requirement to save the order.
951-
*/
952-
static void
953-
simple_action_list_append(SimpleActionList *list, int action, const char *val)
954-
{
955-
SimpleActionListCell *cell;
956-
size_t vallen = 0;
957-
958-
if (val)
959-
vallen = strlen(val);
960-
961-
cell = (SimpleActionListCell *)
962-
pg_malloc(offsetof(SimpleActionListCell, val) + vallen + 1);
963-
964-
cell->next = NULL;
965-
cell->action = action;
966-
if (val)
967-
{
968-
cell->val = pg_malloc(vallen + 1);
969-
strcpy(cell->val, val);
970-
}
971-
else
972-
cell->val = NULL;
973-
974-
if (list->tail)
975-
list->tail->next = cell;
976-
else
977-
list->head = cell;
978-
list->tail = cell;
979-
}
980-
981972
static void
982973
EstablishVariableSpace(void)
983974
{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy