Skip to content

Commit 1773e07

Browse files
committed
Improve consistency of parsing of psql's magic variables.
For simple boolean variables such as ON_ERROR_STOP, psql has for a long time recognized variant spellings of "on" and "off" (such as "1"/"0"), and it also made a point of warning you if you'd misspelled the setting. But these conveniences did not exist for other keyword-valued variables. In particular, though ECHO_HIDDEN and ON_ERROR_ROLLBACK include "on" and "off" as possible values, none of the alternative spellings for those were recognized; and to make matters worse the code would just silently assume "on" was meant for any unrecognized spelling. Several people have reported getting bitten by this, so let's fix it. In detail, this patch: * Allows all spellings recognized by ParseVariableBool() for ECHO_HIDDEN and ON_ERROR_ROLLBACK. * Reports a warning for unrecognized values for COMP_KEYWORD_CASE, ECHO, ECHO_HIDDEN, HISTCONTROL, ON_ERROR_ROLLBACK, and VERBOSITY. * Recognizes all values for all these variables case-insensitively; previously there was a mishmash of case-sensitive and case-insensitive behaviors. Back-patch to all supported branches. There is a small risk of breaking existing scripts that were accidentally failing to malfunction; but the consensus is that the chance of detecting real problems and preventing future mistakes outweighs this.
1 parent 4c136b0 commit 1773e07

File tree

5 files changed

+79
-51
lines changed

5 files changed

+79
-51
lines changed

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

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ EOF
157157
Echo the actual queries generated by <command>\d</command> and other backslash
158158
commands. You can use this to study <application>psql</application>'s
159159
internal operations. This is equivalent to
160-
setting the variable <varname>ECHO_HIDDEN</varname> from within
161-
<application>psql</application>.
160+
setting the variable <varname>ECHO_HIDDEN</varname> to <literal>on</>.
162161
</para>
163162
</listitem>
164163
</varlistentry>
@@ -317,8 +316,8 @@ EOF
317316
quietly. By default, it prints welcome messages and various
318317
informational output. If this option is used, none of this
319318
happens. This is useful with the <option>-c</option> option.
320-
Within <application>psql</application> you can also set the
321-
<varname>QUIET</varname> variable to achieve the same effect.
319+
This is equivalent to setting the variable <varname>QUIET</varname>
320+
to <literal>on</>.
322321
</para>
323322
</listitem>
324323
</varlistentry>
@@ -2582,8 +2581,9 @@ bar
25822581
<term><varname>ECHO_HIDDEN</varname></term>
25832582
<listitem>
25842583
<para>
2585-
When this variable is set and a backslash command queries the
2586-
database, the query is first shown. This way you can study the
2584+
When this variable is set to <literal>on</> and a backslash command
2585+
queries the database, the query is first shown.
2586+
This feature helps you to study
25872587
<productname>PostgreSQL</productname> internals and provide
25882588
similar functionality in your own programs. (To select this behavior
25892589
on program start-up, use the switch <option>-E</option>.) If you set
@@ -2741,16 +2741,16 @@ bar
27412741
<term><varname>ON_ERROR_ROLLBACK</varname></term>
27422742
<listitem>
27432743
<para>
2744-
When <literal>on</>, if a statement in a transaction block
2744+
When set to <literal>on</>, if a statement in a transaction block
27452745
generates an error, the error is ignored and the transaction
2746-
continues. When <literal>interactive</>, such errors are only
2746+
continues. When set to <literal>interactive</>, such errors are only
27472747
ignored in interactive sessions, and not when reading script
2748-
files. When <literal>off</> (the default), a statement in a
2748+
files. When unset or set to <literal>off</>, a statement in a
27492749
transaction block that generates an error aborts the entire
2750-
transaction. The on_error_rollback-on mode works by issuing an
2750+
transaction. The error rollback mode works by issuing an
27512751
implicit <command>SAVEPOINT</> for you, just before each command
2752-
that is in a transaction block, and rolls back to the savepoint
2753-
on error.
2752+
that is in a transaction block, and then rolling back to the
2753+
savepoint if the command fails.
27542754
</para>
27552755
</listitem>
27562756
</varlistentry>
@@ -2760,7 +2760,8 @@ bar
27602760
<listitem>
27612761
<para>
27622762
By default, command processing continues after an error. When this
2763-
variable is set, it will instead stop immediately. In interactive mode,
2763+
variable is set to <literal>on</>, processing will instead stop
2764+
immediately. In interactive mode,
27642765
<application>psql</application> will return to the command prompt;
27652766
otherwise, <application>psql</application> will exit, returning
27662767
error code 3 to distinguish this case from fatal error
@@ -2802,8 +2803,8 @@ bar
28022803
<term><varname>QUIET</varname></term>
28032804
<listitem>
28042805
<para>
2805-
This variable is equivalent to the command line option
2806-
<option>-q</option>. It is probably not too useful in
2806+
Setting this variable to <literal>on</> is equivalent to the command
2807+
line option <option>-q</option>. It is probably not too useful in
28072808
interactive mode.
28082809
</para>
28092810
</listitem>
@@ -2813,8 +2814,8 @@ bar
28132814
<term><varname>SINGLELINE</varname></term>
28142815
<listitem>
28152816
<para>
2816-
This variable is equivalent to the command line option
2817-
<option>-S</option>.
2817+
Setting this variable to <literal>on</> is equivalent to the command
2818+
line option <option>-S</option>.
28182819
</para>
28192820
</listitem>
28202821
</varlistentry>
@@ -2823,8 +2824,8 @@ bar
28232824
<term><varname>SINGLESTEP</varname></term>
28242825
<listitem>
28252826
<para>
2826-
This variable is equivalent to the command line option
2827-
<option>-s</option>.
2827+
Setting this variable to <literal>on</> is equivalent to the command
2828+
line option <option>-s</option>.
28282829
</para>
28292830
</listitem>
28302831
</varlistentry>

src/bin/psql/command.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,7 @@ exec_command(const char *cmd,
12521252
OT_NORMAL, NULL, false);
12531253

12541254
if (opt)
1255-
pset.timing = ParseVariableBool(opt);
1255+
pset.timing = ParseVariableBool(opt, "\\timing");
12561256
else
12571257
pset.timing = !pset.timing;
12581258
if (!pset.quiet)
@@ -2159,10 +2159,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
21592159
}
21602160

21612161
/* set expanded/vertical mode */
2162-
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
2162+
else if (strcmp(param, "x") == 0 ||
2163+
strcmp(param, "expanded") == 0 ||
2164+
strcmp(param, "vertical") == 0)
21632165
{
21642166
if (value)
2165-
popt->topt.expanded = ParseVariableBool(value);
2167+
popt->topt.expanded = ParseVariableBool(value, param);
21662168
else
21672169
popt->topt.expanded = !popt->topt.expanded;
21682170
if (!quiet)
@@ -2175,7 +2177,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
21752177
else if (strcmp(param, "numericlocale") == 0)
21762178
{
21772179
if (value)
2178-
popt->topt.numericLocale = ParseVariableBool(value);
2180+
popt->topt.numericLocale = ParseVariableBool(value, param);
21792181
else
21802182
popt->topt.numericLocale = !popt->topt.numericLocale;
21812183
if (!quiet)
@@ -2232,7 +2234,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
22322234
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
22332235
{
22342236
if (value)
2235-
popt->topt.tuples_only = ParseVariableBool(value);
2237+
popt->topt.tuples_only = ParseVariableBool(value, param);
22362238
else
22372239
popt->topt.tuples_only = !popt->topt.tuples_only;
22382240
if (!quiet)
@@ -2286,10 +2288,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
22862288
if (value && pg_strcasecmp(value, "always") == 0)
22872289
popt->topt.pager = 2;
22882290
else if (value)
2289-
if (ParseVariableBool(value))
2291+
{
2292+
if (ParseVariableBool(value, param))
22902293
popt->topt.pager = 1;
22912294
else
22922295
popt->topt.pager = 0;
2296+
}
22932297
else if (popt->topt.pager == 1)
22942298
popt->topt.pager = 0;
22952299
else
@@ -2309,7 +2313,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
23092313
else if (strcmp(param, "footer") == 0)
23102314
{
23112315
if (value)
2312-
popt->default_footer = ParseVariableBool(value);
2316+
popt->default_footer = ParseVariableBool(value, param);
23132317
else
23142318
popt->default_footer = !popt->default_footer;
23152319
if (!quiet)

src/bin/psql/startup.c

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -637,31 +637,31 @@ showVersion(void)
637637
static void
638638
autocommit_hook(const char *newval)
639639
{
640-
pset.autocommit = ParseVariableBool(newval);
640+
pset.autocommit = ParseVariableBool(newval, "AUTOCOMMIT");
641641
}
642642

643643
static void
644644
on_error_stop_hook(const char *newval)
645645
{
646-
pset.on_error_stop = ParseVariableBool(newval);
646+
pset.on_error_stop = ParseVariableBool(newval, "ON_ERROR_STOP");
647647
}
648648

649649
static void
650650
quiet_hook(const char *newval)
651651
{
652-
pset.quiet = ParseVariableBool(newval);
652+
pset.quiet = ParseVariableBool(newval, "QUIET");
653653
}
654654

655655
static void
656656
singleline_hook(const char *newval)
657657
{
658-
pset.singleline = ParseVariableBool(newval);
658+
pset.singleline = ParseVariableBool(newval, "SINGLELINE");
659659
}
660660

661661
static void
662662
singlestep_hook(const char *newval)
663663
{
664-
pset.singlestep = ParseVariableBool(newval);
664+
pset.singlestep = ParseVariableBool(newval, "SINGLESTEP");
665665
}
666666

667667
static void
@@ -675,25 +675,31 @@ echo_hook(const char *newval)
675675
{
676676
if (newval == NULL)
677677
pset.echo = PSQL_ECHO_NONE;
678-
else if (strcmp(newval, "queries") == 0)
678+
else if (pg_strcasecmp(newval, "queries") == 0)
679679
pset.echo = PSQL_ECHO_QUERIES;
680-
else if (strcmp(newval, "all") == 0)
680+
else if (pg_strcasecmp(newval, "all") == 0)
681681
pset.echo = PSQL_ECHO_ALL;
682+
else if (pg_strcasecmp(newval, "none") == 0)
683+
pset.echo = PSQL_ECHO_NONE;
682684
else
685+
{
686+
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
687+
newval, "ECHO", "none");
683688
pset.echo = PSQL_ECHO_NONE;
689+
}
684690
}
685691

686692
static void
687693
echo_hidden_hook(const char *newval)
688694
{
689695
if (newval == NULL)
690696
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
691-
else if (strcmp(newval, "noexec") == 0)
697+
else if (pg_strcasecmp(newval, "noexec") == 0)
692698
pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC;
693-
else if (pg_strcasecmp(newval, "off") == 0)
694-
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
695-
else
699+
else if (ParseVariableBool(newval, "ECHO_HIDDEN"))
696700
pset.echo_hidden = PSQL_ECHO_HIDDEN_ON;
701+
else /* ParseVariableBool printed msg if needed */
702+
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
697703
}
698704

699705
static void
@@ -703,25 +709,31 @@ on_error_rollback_hook(const char *newval)
703709
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
704710
else if (pg_strcasecmp(newval, "interactive") == 0)
705711
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
706-
else if (pg_strcasecmp(newval, "off") == 0)
707-
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
708-
else
712+
else if (ParseVariableBool(newval, "ON_ERROR_ROLLBACK"))
709713
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON;
714+
else /* ParseVariableBool printed msg if needed */
715+
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
710716
}
711717

712718
static void
713719
histcontrol_hook(const char *newval)
714720
{
715721
if (newval == NULL)
716722
pset.histcontrol = hctl_none;
717-
else if (strcmp(newval, "ignorespace") == 0)
723+
else if (pg_strcasecmp(newval, "ignorespace") == 0)
718724
pset.histcontrol = hctl_ignorespace;
719-
else if (strcmp(newval, "ignoredups") == 0)
725+
else if (pg_strcasecmp(newval, "ignoredups") == 0)
720726
pset.histcontrol = hctl_ignoredups;
721-
else if (strcmp(newval, "ignoreboth") == 0)
727+
else if (pg_strcasecmp(newval, "ignoreboth") == 0)
722728
pset.histcontrol = hctl_ignoreboth;
729+
else if (pg_strcasecmp(newval, "none") == 0)
730+
pset.histcontrol = hctl_none;
723731
else
732+
{
733+
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
734+
newval, "HISTCONTROL", "none");
724735
pset.histcontrol = hctl_none;
736+
}
725737
}
726738

727739
static void
@@ -747,14 +759,18 @@ verbosity_hook(const char *newval)
747759
{
748760
if (newval == NULL)
749761
pset.verbosity = PQERRORS_DEFAULT;
750-
else if (strcmp(newval, "default") == 0)
762+
else if (pg_strcasecmp(newval, "default") == 0)
751763
pset.verbosity = PQERRORS_DEFAULT;
752-
else if (strcmp(newval, "terse") == 0)
764+
else if (pg_strcasecmp(newval, "terse") == 0)
753765
pset.verbosity = PQERRORS_TERSE;
754-
else if (strcmp(newval, "verbose") == 0)
766+
else if (pg_strcasecmp(newval, "verbose") == 0)
755767
pset.verbosity = PQERRORS_VERBOSE;
756768
else
769+
{
770+
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
771+
newval, "VERBOSITY", "default");
757772
pset.verbosity = PQERRORS_DEFAULT;
773+
}
758774

759775
if (pset.db)
760776
PQsetErrorVerbosity(pset.db, pset.verbosity);

src/bin/psql/variables.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,16 @@ GetVariable(VariableSpace space, const char *name)
4949
}
5050

5151
/*
52-
* Try to interpret value as boolean value. Valid values are: true,
53-
* false, yes, no, on, off, 1, 0; as well as unique prefixes thereof.
52+
* Try to interpret "value" as boolean value.
53+
*
54+
* Valid values are: true, false, yes, no, on, off, 1, 0; as well as unique
55+
* prefixes thereof.
56+
*
57+
* "name" is the name of the variable we're assigning to, to use in error
58+
* report if any. Pass name == NULL to suppress the error report.
5459
*/
5560
bool
56-
ParseVariableBool(const char *value)
61+
ParseVariableBool(const char *value, const char *name)
5762
{
5863
size_t len;
5964

@@ -82,7 +87,9 @@ ParseVariableBool(const char *value)
8287
else
8388
{
8489
/* NULL is treated as false, so a non-matching value is 'true' */
85-
psql_error("unrecognized boolean value; assuming \"on\".\n");
90+
if (name)
91+
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
92+
value, name, "on");
8693
return true;
8794
}
8895
/* suppress compiler warning */

src/bin/psql/variables.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ typedef struct _variable *VariableSpace;
3939
VariableSpace CreateVariableSpace(void);
4040
const char *GetVariable(VariableSpace space, const char *name);
4141

42-
bool ParseVariableBool(const char *val);
42+
bool ParseVariableBool(const char *value, const char *name);
4343
int ParseVariableNum(const char *val,
4444
int defaultval,
4545
int faultval,

0 commit comments

Comments
 (0)