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

Commit 511ae62

Browse files
committed
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an unrecognized value, psql would bleat but store the new value anyway, and then fall back to a default setting for the behavior controlled by the variable. This was agreed to be a not particularly good idea. With this patch, invalid values result in an error message and no change in state. (But this applies only to variables that affect psql's behavior; purely informational variables such as ENCODING can still be set to random values.) To do this, modify the API for psql's assign-hook functions so that they can return an OK/not OK result, and give them the responsibility for printing error messages when they reject a value. Adjust the APIs for ParseVariableBool and ParseVariableNum to support the new behavior conveniently. In passing, document the variable VERSION, which had somehow escaped that. And improve the quite-inadequate commenting in psql/variables.c. Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
1 parent 46aae59 commit 511ae62

File tree

10 files changed

+356
-182
lines changed

10 files changed

+356
-182
lines changed

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

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3078,10 +3078,8 @@ bar
30783078
by <application>psql</application>. They represent certain option
30793079
settings that can be changed at run time by altering the value of
30803080
the variable, or in some cases represent changeable state of
3081-
<application>psql</application>. Although
3082-
you can use these variables for other purposes, this is not
3083-
recommended, as the program behavior might grow really strange
3084-
really quickly. By convention, all specially treated variables' names
3081+
<application>psql</application>.
3082+
By convention, all specially treated variables' names
30853083
consist of all upper-case ASCII letters (and possibly digits and
30863084
underscores). To ensure maximum compatibility in the future, avoid
30873085
using such variable names for your own purposes. A list of all specially
@@ -3170,12 +3168,11 @@ bar
31703168
start-up, use the switch <option>-a</option>. If set to
31713169
<literal>queries</literal>,
31723170
<application>psql</application> prints each query to standard output
3173-
as it is sent to the server. The switch for this is
3171+
as it is sent to the server. The switch to select this behavior is
31743172
<option>-e</option>. If set to <literal>errors</literal>, then only
31753173
failed queries are displayed on standard error output. The switch
3176-
for this is <option>-b</option>. If unset, or if set to
3177-
<literal>none</literal> (or any other value than those above) then
3178-
no queries are displayed.
3174+
for this behavior is <option>-b</option>. If unset, or if set to
3175+
<literal>none</literal>, then no queries are displayed.
31793176
</para>
31803177
</listitem>
31813178
</varlistentry>
@@ -3201,6 +3198,9 @@ bar
32013198
<listitem>
32023199
<para>
32033200
The current client character set encoding.
3201+
This is set every time you connect to a database (including
3202+
program start-up), and when you change the encoding
3203+
with <literal>\encoding</>, but it can be unset.
32043204
</para>
32053205
</listitem>
32063206
</varlistentry>
@@ -3241,9 +3241,8 @@ bar
32413241
list. If set to a value of <literal>ignoredups</literal>, lines
32423242
matching the previous history line are not entered. A value of
32433243
<literal>ignoreboth</literal> combines the two options. If
3244-
unset, or if set to <literal>none</literal> (or any other value
3245-
than those above), all lines read in interactive mode are
3246-
saved on the history list.
3244+
unset, or if set to <literal>none</literal> (the default), all lines
3245+
read in interactive mode are saved on the history list.
32473246
</para>
32483247
<note>
32493248
<para>
@@ -3312,7 +3311,7 @@ bar
33123311
to an interactive session of <application>psql</application>
33133312
will terminate the application. If set to a numeric value,
33143313
that many <acronym>EOF</> characters are ignored before the
3315-
application terminates. If the variable is set but has no
3314+
application terminates. If the variable is set but not to a
33163315
numeric value, the default is 10.
33173316
</para>
33183317
<note>
@@ -3477,6 +3476,16 @@ bar
34773476
</listitem>
34783477
</varlistentry>
34793478

3479+
<varlistentry>
3480+
<term><varname>VERSION</varname></term>
3481+
<listitem>
3482+
<para>
3483+
This variable is set at program start-up to
3484+
reflect <application>psql</>'s version. It can be unset or changed.
3485+
</para>
3486+
</listitem>
3487+
</varlistentry>
3488+
34803489
</variablelist>
34813490

34823491
</refsect3>

src/bin/psql/command.c

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -248,31 +248,37 @@ exec_command(const char *cmd,
248248
*opt2,
249249
*opt3,
250250
*opt4;
251-
enum trivalue reuse_previous;
251+
enum trivalue reuse_previous = TRI_DEFAULT;
252252

253253
opt1 = read_connect_arg(scan_state);
254254
if (opt1 != NULL && strncmp(opt1, prefix, sizeof(prefix) - 1) == 0)
255255
{
256-
reuse_previous =
257-
ParseVariableBool(opt1 + sizeof(prefix) - 1, prefix) ?
258-
TRI_YES : TRI_NO;
256+
bool on_off;
259257

260-
free(opt1);
261-
opt1 = read_connect_arg(scan_state);
258+
success = ParseVariableBool(opt1 + sizeof(prefix) - 1,
259+
"-reuse-previous",
260+
&on_off);
261+
if (success)
262+
{
263+
reuse_previous = on_off ? TRI_YES : TRI_NO;
264+
free(opt1);
265+
opt1 = read_connect_arg(scan_state);
266+
}
262267
}
263-
else
264-
reuse_previous = TRI_DEFAULT;
265268

266-
opt2 = read_connect_arg(scan_state);
267-
opt3 = read_connect_arg(scan_state);
268-
opt4 = read_connect_arg(scan_state);
269+
if (success) /* give up if reuse_previous was invalid */
270+
{
271+
opt2 = read_connect_arg(scan_state);
272+
opt3 = read_connect_arg(scan_state);
273+
opt4 = read_connect_arg(scan_state);
269274

270-
success = do_connect(reuse_previous, opt1, opt2, opt3, opt4);
275+
success = do_connect(reuse_previous, opt1, opt2, opt3, opt4);
271276

277+
free(opt2);
278+
free(opt3);
279+
free(opt4);
280+
}
272281
free(opt1);
273-
free(opt2);
274-
free(opt3);
275-
free(opt4);
276282
}
277283

278284
/* \cd */
@@ -1208,10 +1214,7 @@ exec_command(const char *cmd,
12081214

12091215
if (result &&
12101216
!SetVariable(pset.vars, opt, result))
1211-
{
1212-
psql_error("\\%s: error while setting variable\n", cmd);
12131217
success = false;
1214-
}
12151218

12161219
if (result)
12171220
free(result);
@@ -1325,10 +1328,8 @@ exec_command(const char *cmd,
13251328
}
13261329

13271330
if (!SetVariable(pset.vars, opt0, newval))
1328-
{
1329-
psql_error("\\%s: error while setting variable\n", cmd);
13301331
success = false;
1331-
}
1332+
13321333
free(newval);
13331334
}
13341335
free(opt0);
@@ -1564,7 +1565,7 @@ exec_command(const char *cmd,
15641565
OT_NORMAL, NULL, false);
15651566

15661567
if (opt)
1567-
pset.timing = ParseVariableBool(opt, "\\timing");
1568+
success = ParseVariableBool(opt, "\\timing", &pset.timing);
15681569
else
15691570
pset.timing = !pset.timing;
15701571
if (!pset.quiet)
@@ -1589,10 +1590,8 @@ exec_command(const char *cmd,
15891590
success = false;
15901591
}
15911592
else if (!SetVariable(pset.vars, opt, NULL))
1592-
{
1593-
psql_error("\\%s: error while setting variable\n", cmd);
15941593
success = false;
1595-
}
1594+
15961595
free(opt);
15971596
}
15981597

@@ -2593,7 +2592,6 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
25932592
psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, latex-longtable, troff-ms\n");
25942593
return false;
25952594
}
2596-
25972595
}
25982596

25992597
/* set table line style */
@@ -2612,7 +2610,6 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
26122610
psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n");
26132611
return false;
26142612
}
2615-
26162613
}
26172614

26182615
/* set unicode border line style */
@@ -2665,7 +2662,6 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
26652662
{
26662663
if (value)
26672664
popt->topt.border = atoi(value);
2668-
26692665
}
26702666

26712667
/* set expanded/vertical mode */
@@ -2676,7 +2672,17 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
26762672
if (value && pg_strcasecmp(value, "auto") == 0)
26772673
popt->topt.expanded = 2;
26782674
else if (value)
2679-
popt->topt.expanded = ParseVariableBool(value, param);
2675+
{
2676+
bool on_off;
2677+
2678+
if (ParseVariableBool(value, NULL, &on_off))
2679+
popt->topt.expanded = on_off ? 1 : 0;
2680+
else
2681+
{
2682+
PsqlVarEnumError(param, value, "on, off, auto");
2683+
return false;
2684+
}
2685+
}
26802686
else
26812687
popt->topt.expanded = !popt->topt.expanded;
26822688
}
@@ -2685,7 +2691,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
26852691
else if (strcmp(param, "numericlocale") == 0)
26862692
{
26872693
if (value)
2688-
popt->topt.numericLocale = ParseVariableBool(value, param);
2694+
return ParseVariableBool(value, param, &popt->topt.numericLocale);
26892695
else
26902696
popt->topt.numericLocale = !popt->topt.numericLocale;
26912697
}
@@ -2740,7 +2746,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
27402746
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
27412747
{
27422748
if (value)
2743-
popt->topt.tuples_only = ParseVariableBool(value, param);
2749+
return ParseVariableBool(value, param, &popt->topt.tuples_only);
27442750
else
27452751
popt->topt.tuples_only = !popt->topt.tuples_only;
27462752
}
@@ -2772,10 +2778,14 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
27722778
popt->topt.pager = 2;
27732779
else if (value)
27742780
{
2775-
if (ParseVariableBool(value, param))
2776-
popt->topt.pager = 1;
2777-
else
2778-
popt->topt.pager = 0;
2781+
bool on_off;
2782+
2783+
if (!ParseVariableBool(value, NULL, &on_off))
2784+
{
2785+
PsqlVarEnumError(param, value, "on, off, always");
2786+
return false;
2787+
}
2788+
popt->topt.pager = on_off ? 1 : 0;
27792789
}
27802790
else if (popt->topt.pager == 1)
27812791
popt->topt.pager = 0;
@@ -2794,7 +2804,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
27942804
else if (strcmp(param, "footer") == 0)
27952805
{
27962806
if (value)
2797-
popt->topt.default_footer = ParseVariableBool(value, param);
2807+
return ParseVariableBool(value, param, &popt->topt.default_footer);
27982808
else
27992809
popt->topt.default_footer = !popt->topt.default_footer;
28002810
}

src/bin/psql/common.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,6 @@ StoreQueryTuple(const PGresult *result)
841841

842842
if (!SetVariable(pset.vars, varname, value))
843843
{
844-
psql_error("could not set variable \"%s\"\n", varname);
845844
free(varname);
846845
success = false;
847846
break;

src/bin/psql/input.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ finishInput(void)
541541
{
542542
int hist_size;
543543

544-
hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1, true);
544+
hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1);
545545
(void) saveHistory(psql_history, hist_size);
546546
free(psql_history);
547547
psql_history = NULL;

src/bin/psql/mainloop.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ MainLoop(FILE *source)
162162
/* This tries to mimic bash's IGNOREEOF feature. */
163163
count_eof++;
164164

165-
if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false))
165+
if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10))
166166
{
167167
if (!pset.quiet)
168168
printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);

0 commit comments

Comments
 (0)