Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+79-61
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

+42-51
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)