Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 928311a

Browse files
committed
Clean up weird corner cases in lexing of psql meta-command arguments.
These changes allow backtick command evaluation and psql variable interpolation to happen on substrings of a single meta-command argument. Formerly, no such evaluations happened at all if the backtick or colon wasn't the first character of the argument, and we considered an argument completed as soon as we'd processed one backtick, variable reference, or quoted substring. A string like 'FOO'BAR was thus taken as two arguments not one, not exactly what one would expect. In the new coding, an argument is considered terminated only by unquoted whitespace or backslash. Also, clean up a bunch of omissions, infelicities and outright errors in the psql documentation of variables and metacommand argument syntax.
1 parent e86fdb0 commit 928311a

File tree

4 files changed

+275
-247
lines changed

4 files changed

+275
-247
lines changed

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

Lines changed: 103 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ PostgreSQL documentation
156156
Use the file <replaceable class="parameter">filename</replaceable>
157157
as the source of commands instead of reading commands interactively.
158158
After the file is processed, <application>psql</application>
159-
terminates. This is in many ways equivalent to the internal
160-
command <command>\i</command>.
159+
terminates. This is in many ways equivalent to the meta-command
160+
<command>\i</command>.
161161
</para>
162162

163163
<para>
@@ -223,7 +223,7 @@ PostgreSQL documentation
223223
<listitem>
224224
<para>
225225
List all available databases, then exit. Other non-connection
226-
options are ignored. This is similar to the internal command
226+
options are ignored. This is similar to the meta-command
227227
<command>\list</command>.
228228
</para>
229229
</listitem>
@@ -393,9 +393,9 @@ PostgreSQL documentation
393393
<listitem>
394394
<para>
395395
Perform a variable assignment, like the <command>\set</command>
396-
internal command. Note that you must separate name and value, if
396+
meta-command. Note that you must separate name and value, if
397397
any, by an equal sign on the command line. To unset a variable,
398-
leave off the equal sign. To just set a variable without a value,
398+
leave off the equal sign. To set a variable with an empty value,
399399
use the equal sign but leave off the value. These assignments are
400400
done during a very early stage of start-up, so variables reserved
401401
for internal purposes might get overwritten later.
@@ -659,32 +659,32 @@ testdb=&gt;
659659
</para>
660660

661661
<para>
662-
To include whitespace into an argument you can quote it with a
663-
single quote. To include a single quote into such an argument,
664-
use two single quotes. Anything contained in single quotes is
662+
To include whitespace in an argument you can quote it with
663+
single quotes. To include a single quote in an argument,
664+
write two single quotes within single-quoted text.
665+
Anything contained in single quotes is
665666
furthermore subject to C-like substitutions for
666667
<literal>\n</literal> (new line), <literal>\t</literal> (tab),
668+
<literal>\b</literal> (backspace), <literal>\r</literal> (carriage return),
669+
<literal>\f</literal> (form feed),
667670
<literal>\</literal><replaceable>digits</replaceable> (octal), and
668671
<literal>\x</literal><replaceable>digits</replaceable> (hexadecimal).
672+
A backslash preceding any other character within single-quoted text
673+
quotes that single character, whatever it is.
669674
</para>
670675

671676
<para>
672-
If an unquoted argument begins with a colon (<literal>:</literal>),
673-
it is taken as a <application>psql</> variable and the value of the
674-
variable is used as the argument instead. If the variable name is
675-
surrounded by single quotes (e.g. <literal>:'var'</literal>), it
676-
will be escaped as an SQL literal and the result will be used as
677-
the argument. If the variable name is surrounded by double quotes,
678-
it will be escaped as an SQL identifier and the result will be used
679-
as the argument.
677+
Within an argument, text that is enclosed in backquotes
678+
(<literal>`</literal>) is taken as a command line that is passed to the
679+
shell. The output of the command (with any trailing newline removed)
680+
replaces the backquoted text.
680681
</para>
681682

682683
<para>
683-
Arguments that are enclosed in backquotes (<literal>`</literal>)
684-
are taken as a command line that is passed to the shell. The
685-
output of the command (with any trailing newline removed) is taken
686-
as the argument value. The above escape sequences also apply in
687-
backquotes.
684+
If an unquoted colon (<literal>:</literal>) followed by a
685+
<application>psql</> variable name appears within an argument, it is
686+
replaced by the variable's value, as described in <xref
687+
linkend="APP-PSQL-interpolation" endterm="APP-PSQL-interpolation-title">.
688688
</para>
689689

690690
<para>
@@ -1803,15 +1803,16 @@ lo_import 152801
18031803
<term><literal>\prompt [ <replaceable class="parameter">text</replaceable> ] <replaceable class="parameter">name</replaceable></literal></term>
18041804
<listitem>
18051805
<para>
1806-
Prompts the user to set variable <replaceable
1807-
class="parameter">name</>. An optional prompt, <replaceable
1806+
Prompts the user to supply text, which is assigned to the variable
1807+
<replaceable class="parameter">name</>.
1808+
An optional prompt string, <replaceable
18081809
class="parameter">text</>, can be specified. (For multiword
1809-
prompts, use single quotes.)
1810+
prompts, surround the text with single quotes.)
18101811
</para>
18111812

18121813
<para>
18131814
By default, <literal>\prompt</> uses the terminal for input and
1814-
output. However, if the <option>-f</> command line switch is
1815+
output. However, if the <option>-f</> command line switch was
18151816
used, <literal>\prompt</> uses standard input and standard output.
18161817
</para>
18171818
</listitem>
@@ -2197,14 +2198,19 @@ lo_import 152801
21972198

21982199
<listitem>
21992200
<para>
2200-
Sets the internal variable <replaceable
2201+
Sets the <application>psql</> variable <replaceable
22012202
class="parameter">name</replaceable> to <replaceable
2202-
class="parameter">value</replaceable> or, if more than one value
2203-
is given, to the concatenation of all of them. If no second
2204-
argument is given, the variable is just set with no value. To
2203+
class="parameter">value</replaceable>, or if more than one value
2204+
is given, to the concatenation of all of them. If only one
2205+
argument is given, the variable is set with an empty value. To
22052206
unset a variable, use the <command>\unset</command> command.
22062207
</para>
22072208

2209+
<para>
2210+
<command>\set</> without any arguments displays the names and values
2211+
of all currently-set <application>psql</> variables.
2212+
</para>
2213+
22082214
<para>
22092215
Valid variable names can contain letters, digits, and
22102216
underscores. See the section <xref
@@ -2221,7 +2227,7 @@ lo_import 152801
22212227

22222228
<note>
22232229
<para>
2224-
This command is totally separate from the <acronym>SQL</acronym>
2230+
This command is unrelated to the <acronym>SQL</acronym>
22252231
command <xref linkend="SQL-SET">.
22262232
</para>
22272233
</note>
@@ -2293,6 +2299,18 @@ lo_import 152801
22932299
</varlistentry>
22942300

22952301

2302+
<varlistentry>
2303+
<term><literal>\unset <replaceable class="parameter">name</replaceable></literal></term>
2304+
2305+
<listitem>
2306+
<para>
2307+
Unsets (deletes) the <application>psql</> variable <replaceable
2308+
class="parameter">name</replaceable>.
2309+
</para>
2310+
</listitem>
2311+
</varlistentry>
2312+
2313+
22962314
<varlistentry>
22972315
<term><literal>\w</literal> <replaceable class="parameter">filename</replaceable></term>
22982316
<term><literal>\w</literal> <literal>|</><replaceable class="parameter">command</replaceable></term>
@@ -2467,18 +2485,28 @@ lo_import 152801
24672485

24682486
<para>
24692487
To set a variable, use the <application>psql</application> meta-command
2470-
<command>\set</command>:
2488+
<command>\set</command>. For example,
24712489
<programlisting>
24722490
testdb=&gt; <userinput>\set foo bar</userinput>
24732491
</programlisting>
24742492
sets the variable <literal>foo</literal> to the value
24752493
<literal>bar</literal>. To retrieve the content of the variable, precede
2476-
the name with a colon and use it as the argument of any slash
2477-
command:
2494+
the name with a colon, for example:
24782495
<programlisting>
24792496
testdb=&gt; <userinput>\echo :foo</userinput>
24802497
bar
2481-
</programlisting></para>
2498+
</programlisting>
2499+
This works in both regular SQL commands and meta-commands; there is
2500+
more detail in <xref linkend="APP-PSQL-interpolation"
2501+
endterm="APP-PSQL-interpolation-title">, below.
2502+
</para>
2503+
2504+
<para>
2505+
If you call <command>\set</command> without a second argument, the
2506+
variable is set, with an empty string as value. To unset (i.e., delete)
2507+
a variable, use the command <command>\unset</command>. To show the
2508+
values of all variables, call <command>\set</command> without any argument.
2509+
</para>
24822510

24832511
<note>
24842512
<para>
@@ -2495,12 +2523,6 @@ bar
24952523
</para>
24962524
</note>
24972525

2498-
<para>
2499-
If you call <command>\set</command> without a second argument, the
2500-
variable is set, with an empty string as value. To unset (or delete) a
2501-
variable, use the command <command>\unset</command>.
2502-
</para>
2503-
25042526
<para>
25052527
A number of these variables are treated specially
25062528
by <application>psql</application>. They represent certain option
@@ -2863,47 +2885,57 @@ bar
28632885

28642886
</refsect3>
28652887

2866-
<refsect3>
2867-
<title><acronym>SQL</acronym> Interpolation</title>
2888+
<refsect3 id="APP-PSQL-interpolation">
2889+
<title id="APP-PSQL-interpolation-title"><acronym>SQL</acronym> Interpolation</title>
28682890

28692891
<para>
2870-
An additional useful feature of <application>psql</application>
2892+
A key feature of <application>psql</application>
28712893
variables is that you can substitute (<quote>interpolate</quote>)
2872-
them into regular <acronym>SQL</acronym> statements.
2873-
<application>psql</application> provides special facilities for
2874-
ensuring that values used as SQL literals and identifiers are
2875-
properly escaped. The syntax for interpolating a value without
2876-
any special escaping is again to prepend the variable name with a colon
2877-
(<literal>:</literal>):
2894+
them into regular <acronym>SQL</acronym> statements, as well as the
2895+
arguments of meta-commands. Furthermore,
2896+
<application>psql</application> provides facilities for
2897+
ensuring that variable values used as SQL literals and identifiers are
2898+
properly quoted. The syntax for interpolating a value without
2899+
any quoting is to prepend the variable name with a colon
2900+
(<literal>:</literal>). For example,
28782901
<programlisting>
28792902
testdb=&gt; <userinput>\set foo 'my_table'</userinput>
28802903
testdb=&gt; <userinput>SELECT * FROM :foo;</userinput>
28812904
</programlisting>
2882-
would then query the table <literal>my_table</literal>. Note that this
2905+
would query the table <literal>my_table</literal>. Note that this
28832906
may be unsafe: the value of the variable is copied literally, so it can
2884-
even contain unbalanced quotes or backslash commands. You must make sure
2907+
contain unbalanced quotes, or even backslash commands. You must make sure
28852908
that it makes sense where you put it.
28862909
</para>
28872910

28882911
<para>
28892912
When a value is to be used as an SQL literal or identifier, it is
2890-
safest to arrange for it to be escaped. To escape the value of
2913+
safest to arrange for it to be quoted. To quote the value of
28912914
a variable as an SQL literal, write a colon followed by the variable
2892-
name in single quotes. To escape the value an SQL identifier, write
2893-
a colon followed by the variable name in double quotes. The previous
2894-
example would be more safely written this way:
2915+
name in single quotes. To quote the value as an SQL identifier, write
2916+
a colon followed by the variable name in double quotes.
2917+
These constructs deal correctly with quotes and other special
2918+
characters embedded within the variable value.
2919+
The previous example would be more safely written this way:
28952920
<programlisting>
28962921
testdb=&gt; <userinput>\set foo 'my_table'</userinput>
28972922
testdb=&gt; <userinput>SELECT * FROM :"foo";</userinput>
28982923
</programlisting>
2899-
Variable interpolation will not be performed into quoted
2900-
<acronym>SQL</acronym> entities.
29012924
</para>
29022925

29032926
<para>
2904-
One possible use of this mechanism is to
2905-
copy the contents of a file into a table column. First load the file into a
2906-
variable and then proceed as above:
2927+
Variable interpolation will not be performed within quoted
2928+
<acronym>SQL</acronym> literals and identifiers. Therefore, a
2929+
construction such as <literal>':foo'</> doesn't work to produce a quoted
2930+
literal from a variable's value (and it would be unsafe if it did work,
2931+
since it wouldn't correctly handle quotes embedded in the value).
2932+
</para>
2933+
2934+
<para>
2935+
One example use of this mechanism is to
2936+
copy the contents of a file into a table column.
2937+
First load the file into a variable and then interpolate the variable's
2938+
value as a quoted string:
29072939
<programlisting>
29082940
testdb=&gt; <userinput>\set content `cat my_file.txt`</userinput>
29092941
testdb=&gt; <userinput>INSERT INTO my_table VALUES (:'content');</userinput>
@@ -2914,17 +2946,20 @@ testdb=&gt; <userinput>INSERT INTO my_table VALUES (:'content');</userinput>
29142946

29152947
<para>
29162948
Since colons can legally appear in SQL commands, an apparent attempt
2917-
at interpolation (such as <literal>:name</literal>,
2949+
at interpolation (that is, <literal>:name</literal>,
29182950
<literal>:'name'</literal>, or <literal>:"name"</literal>) is not
2919-
changed unless the named variable is currently set. In any case, you
2951+
replaced unless the named variable is currently set. In any case, you
29202952
can escape a colon with a backslash to protect it from substitution.
2921-
(The colon syntax for variables is standard <acronym>SQL</acronym> for
2953+
</para>
2954+
2955+
<para>
2956+
The colon syntax for variables is standard <acronym>SQL</acronym> for
29222957
embedded query languages, such as <application>ECPG</application>.
2923-
The colon syntax for array slices and type casts are
2924-
<productname>PostgreSQL</productname> extensions, hence the
2925-
conflict. The colon syntax for escaping a variable's value as an
2926-
SQL literal or identifier is a <application>psql</application>
2927-
extension.)
2958+
The colon syntaxes for array slices and type casts are
2959+
<productname>PostgreSQL</productname> extensions, which can sometimes
2960+
conflict with the standard usage. The colon-quote syntax for escaping a
2961+
variable's value as an SQL literal or identifier is a
2962+
<application>psql</application> extension.
29282963
</para>
29292964

29302965
</refsect3>

src/bin/psql/command.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ HandleSlashCmds(PsqlScanState scan_state,
121121
/* eat any remaining arguments after a valid command */
122122
/* note we suppress evaluation of backticks here */
123123
while ((arg = psql_scan_slash_option(scan_state,
124-
OT_VERBATIM, NULL, false)))
124+
OT_NO_EVAL, NULL, false)))
125125
{
126126
psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
127127
free(arg);

src/bin/psql/psqlscan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ enum slash_option_type
3333
OT_SQLIDHACK, /* SQL identifier, but don't downcase */
3434
OT_FILEPIPE, /* it's a filename or pipe */
3535
OT_WHOLE_LINE, /* just snarf the rest of the line */
36-
OT_VERBATIM /* literal (no backticks or variables) */
36+
OT_NO_EVAL /* no expansion of backticks or variables */
3737
};
3838

3939

0 commit comments

Comments
 (0)