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

Commit c352499

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 4e241f7 commit c352499

File tree

7 files changed

+123
-75
lines changed

7 files changed

+123
-75
lines changed

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

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@ EOF
161161
Echo the actual queries generated by <command>\d</command> and other backslash
162162
commands. You can use this to study <application>psql</application>'s
163163
internal operations. This is equivalent to
164-
setting the variable <varname>ECHO_HIDDEN</varname> from within
165-
<application>psql</application>.
164+
setting the variable <varname>ECHO_HIDDEN</varname> to <literal>on</>.
166165
</para>
167166
</listitem>
168167
</varlistentry>
@@ -321,8 +320,8 @@ EOF
321320
quietly. By default, it prints welcome messages and various
322321
informational output. If this option is used, none of this
323322
happens. This is useful with the <option>-c</option> option.
324-
Within <application>psql</application> you can also set the
325-
<varname>QUIET</varname> variable to achieve the same effect.
323+
This is equivalent to setting the variable <varname>QUIET</varname>
324+
to <literal>on</>.
326325
</para>
327326
</listitem>
328327
</varlistentry>
@@ -2824,8 +2823,9 @@ bar
28242823
<term><varname>ECHO_HIDDEN</varname></term>
28252824
<listitem>
28262825
<para>
2827-
When this variable is set and a backslash command queries the
2828-
database, the query is first shown. This way you can study the
2826+
When this variable is set to <literal>on</> and a backslash command
2827+
queries the database, the query is first shown.
2828+
This feature helps you to study
28292829
<productname>PostgreSQL</productname> internals and provide
28302830
similar functionality in your own programs. (To select this behavior
28312831
on program start-up, use the switch <option>-E</option>.) If you set
@@ -2985,16 +2985,16 @@ bar
29852985
</term>
29862986
<listitem>
29872987
<para>
2988-
When <literal>on</>, if a statement in a transaction block
2988+
When set to <literal>on</>, if a statement in a transaction block
29892989
generates an error, the error is ignored and the transaction
2990-
continues. When <literal>interactive</>, such errors are only
2990+
continues. When set to <literal>interactive</>, such errors are only
29912991
ignored in interactive sessions, and not when reading script
2992-
files. When <literal>off</> (the default), a statement in a
2992+
files. When unset or set to <literal>off</>, a statement in a
29932993
transaction block that generates an error aborts the entire
2994-
transaction. The on_error_rollback-on mode works by issuing an
2994+
transaction. The error rollback mode works by issuing an
29952995
implicit <command>SAVEPOINT</> for you, just before each command
2996-
that is in a transaction block, and rolls back to the savepoint
2997-
on error.
2996+
that is in a transaction block, and then rolling back to the
2997+
savepoint if the command fails.
29982998
</para>
29992999
</listitem>
30003000
</varlistentry>
@@ -3004,7 +3004,8 @@ bar
30043004
<listitem>
30053005
<para>
30063006
By default, command processing continues after an error. When this
3007-
variable is set, it will instead stop immediately. In interactive mode,
3007+
variable is set to <literal>on</>, processing will instead stop
3008+
immediately. In interactive mode,
30083009
<application>psql</application> will return to the command prompt;
30093010
otherwise, <application>psql</application> will exit, returning
30103011
error code 3 to distinguish this case from fatal error
@@ -3046,8 +3047,8 @@ bar
30463047
<term><varname>QUIET</varname></term>
30473048
<listitem>
30483049
<para>
3049-
This variable is equivalent to the command line option
3050-
<option>-q</option>. It is probably not too useful in
3050+
Setting this variable to <literal>on</> is equivalent to the command
3051+
line option <option>-q</option>. It is probably not too useful in
30513052
interactive mode.
30523053
</para>
30533054
</listitem>
@@ -3057,8 +3058,8 @@ bar
30573058
<term><varname>SINGLELINE</varname></term>
30583059
<listitem>
30593060
<para>
3060-
This variable is equivalent to the command line option
3061-
<option>-S</option>.
3061+
Setting this variable to <literal>on</> is equivalent to the command
3062+
line option <option>-S</option>.
30623063
</para>
30633064
</listitem>
30643065
</varlistentry>
@@ -3067,8 +3068,8 @@ bar
30673068
<term><varname>SINGLESTEP</varname></term>
30683069
<listitem>
30693070
<para>
3070-
This variable is equivalent to the command line option
3071-
<option>-s</option>.
3071+
Setting this variable to <literal>on</> is equivalent to the command
3072+
line option <option>-s</option>.
30723073
</para>
30733074
</listitem>
30743075
</varlistentry>

src/bin/psql/command.c

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

13611361
if (opt)
1362-
pset.timing = ParseVariableBool(opt);
1362+
pset.timing = ParseVariableBool(opt, "\\timing");
13631363
else
13641364
pset.timing = !pset.timing;
13651365
if (!pset.quiet)
@@ -2323,12 +2323,14 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
23232323
}
23242324

23252325
/* set expanded/vertical mode */
2326-
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
2326+
else if (strcmp(param, "x") == 0 ||
2327+
strcmp(param, "expanded") == 0 ||
2328+
strcmp(param, "vertical") == 0)
23272329
{
23282330
if (value && pg_strcasecmp(value, "auto") == 0)
23292331
popt->topt.expanded = 2;
23302332
else if (value)
2331-
popt->topt.expanded = ParseVariableBool(value);
2333+
popt->topt.expanded = ParseVariableBool(value, param);
23322334
else
23332335
popt->topt.expanded = !popt->topt.expanded;
23342336
}
@@ -2337,7 +2339,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
23372339
else if (strcmp(param, "numericlocale") == 0)
23382340
{
23392341
if (value)
2340-
popt->topt.numericLocale = ParseVariableBool(value);
2342+
popt->topt.numericLocale = ParseVariableBool(value, param);
23412343
else
23422344
popt->topt.numericLocale = !popt->topt.numericLocale;
23432345
}
@@ -2392,7 +2394,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
23922394
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
23932395
{
23942396
if (value)
2395-
popt->topt.tuples_only = ParseVariableBool(value);
2397+
popt->topt.tuples_only = ParseVariableBool(value, param);
23962398
else
23972399
popt->topt.tuples_only = !popt->topt.tuples_only;
23982400
}
@@ -2423,10 +2425,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
24232425
if (value && pg_strcasecmp(value, "always") == 0)
24242426
popt->topt.pager = 2;
24252427
else if (value)
2426-
if (ParseVariableBool(value))
2428+
{
2429+
if (ParseVariableBool(value, param))
24272430
popt->topt.pager = 1;
24282431
else
24292432
popt->topt.pager = 0;
2433+
}
24302434
else if (popt->topt.pager == 1)
24312435
popt->topt.pager = 0;
24322436
else
@@ -2437,7 +2441,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
24372441
else if (strcmp(param, "footer") == 0)
24382442
{
24392443
if (value)
2440-
popt->topt.default_footer = ParseVariableBool(value);
2444+
popt->topt.default_footer = ParseVariableBool(value, param);
24412445
else
24422446
popt->topt.default_footer = !popt->topt.default_footer;
24432447
}

src/bin/psql/settings.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
#define DEFAULT_PROMPT2 "%/%R%# "
2828
#define DEFAULT_PROMPT3 ">> "
2929

30+
/*
31+
* Note: these enums should generally be chosen so that zero corresponds
32+
* to the default behavior.
33+
*/
34+
3035
typedef enum
3136
{
3237
PSQL_ECHO_NONE,
@@ -48,6 +53,14 @@ typedef enum
4853
PSQL_ERROR_ROLLBACK_ON
4954
} PSQL_ERROR_ROLLBACK;
5055

56+
typedef enum
57+
{
58+
PSQL_COMP_CASE_PRESERVE_UPPER,
59+
PSQL_COMP_CASE_PRESERVE_LOWER,
60+
PSQL_COMP_CASE_UPPER,
61+
PSQL_COMP_CASE_LOWER
62+
} PSQL_COMP_CASE;
63+
5164
typedef enum
5265
{
5366
hctl_none = 0,
@@ -108,6 +121,7 @@ typedef struct _psqlSettings
108121
PSQL_ECHO echo;
109122
PSQL_ECHO_HIDDEN echo_hidden;
110123
PSQL_ERROR_ROLLBACK on_error_rollback;
124+
PSQL_COMP_CASE comp_case;
111125
HistControl histcontrol;
112126
const char *prompt1;
113127
const char *prompt2;

src/bin/psql/startup.c

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -680,31 +680,31 @@ showVersion(void)
680680
static void
681681
autocommit_hook(const char *newval)
682682
{
683-
pset.autocommit = ParseVariableBool(newval);
683+
pset.autocommit = ParseVariableBool(newval, "AUTOCOMMIT");
684684
}
685685

686686
static void
687687
on_error_stop_hook(const char *newval)
688688
{
689-
pset.on_error_stop = ParseVariableBool(newval);
689+
pset.on_error_stop = ParseVariableBool(newval, "ON_ERROR_STOP");
690690
}
691691

692692
static void
693693
quiet_hook(const char *newval)
694694
{
695-
pset.quiet = ParseVariableBool(newval);
695+
pset.quiet = ParseVariableBool(newval, "QUIET");
696696
}
697697

698698
static void
699699
singleline_hook(const char *newval)
700700
{
701-
pset.singleline = ParseVariableBool(newval);
701+
pset.singleline = ParseVariableBool(newval, "SINGLELINE");
702702
}
703703

704704
static void
705705
singlestep_hook(const char *newval)
706706
{
707-
pset.singlestep = ParseVariableBool(newval);
707+
pset.singlestep = ParseVariableBool(newval, "SINGLESTEP");
708708
}
709709

710710
static void
@@ -718,25 +718,31 @@ echo_hook(const char *newval)
718718
{
719719
if (newval == NULL)
720720
pset.echo = PSQL_ECHO_NONE;
721-
else if (strcmp(newval, "queries") == 0)
721+
else if (pg_strcasecmp(newval, "queries") == 0)
722722
pset.echo = PSQL_ECHO_QUERIES;
723-
else if (strcmp(newval, "all") == 0)
723+
else if (pg_strcasecmp(newval, "all") == 0)
724724
pset.echo = PSQL_ECHO_ALL;
725+
else if (pg_strcasecmp(newval, "none") == 0)
726+
pset.echo = PSQL_ECHO_NONE;
725727
else
728+
{
729+
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
730+
newval, "ECHO", "none");
726731
pset.echo = PSQL_ECHO_NONE;
732+
}
727733
}
728734

729735
static void
730736
echo_hidden_hook(const char *newval)
731737
{
732738
if (newval == NULL)
733739
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
734-
else if (strcmp(newval, "noexec") == 0)
740+
else if (pg_strcasecmp(newval, "noexec") == 0)
735741
pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC;
736-
else if (pg_strcasecmp(newval, "off") == 0)
737-
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
738-
else
742+
else if (ParseVariableBool(newval, "ECHO_HIDDEN"))
739743
pset.echo_hidden = PSQL_ECHO_HIDDEN_ON;
744+
else /* ParseVariableBool printed msg if needed */
745+
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
740746
}
741747

742748
static void
@@ -746,25 +752,52 @@ on_error_rollback_hook(const char *newval)
746752
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
747753
else if (pg_strcasecmp(newval, "interactive") == 0)
748754
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
749-
else if (pg_strcasecmp(newval, "off") == 0)
755+
else if (ParseVariableBool(newval, "ON_ERROR_ROLLBACK"))
756+
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON;
757+
else /* ParseVariableBool printed msg if needed */
750758
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
759+
}
760+
761+
static void
762+
comp_keyword_case_hook(const char *newval)
763+
{
764+
if (newval == NULL)
765+
pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER;
766+
else if (pg_strcasecmp(newval, "preserve-upper") == 0)
767+
pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER;
768+
else if (pg_strcasecmp(newval, "preserve-lower") == 0)
769+
pset.comp_case = PSQL_COMP_CASE_PRESERVE_LOWER;
770+
else if (pg_strcasecmp(newval, "upper") == 0)
771+
pset.comp_case = PSQL_COMP_CASE_UPPER;
772+
else if (pg_strcasecmp(newval, "lower") == 0)
773+
pset.comp_case = PSQL_COMP_CASE_LOWER;
751774
else
752-
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON;
775+
{
776+
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
777+
newval, "COMP_KEYWORD_CASE", "preserve-upper");
778+
pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER;
779+
}
753780
}
754781

755782
static void
756783
histcontrol_hook(const char *newval)
757784
{
758785
if (newval == NULL)
759786
pset.histcontrol = hctl_none;
760-
else if (strcmp(newval, "ignorespace") == 0)
787+
else if (pg_strcasecmp(newval, "ignorespace") == 0)
761788
pset.histcontrol = hctl_ignorespace;
762-
else if (strcmp(newval, "ignoredups") == 0)
789+
else if (pg_strcasecmp(newval, "ignoredups") == 0)
763790
pset.histcontrol = hctl_ignoredups;
764-
else if (strcmp(newval, "ignoreboth") == 0)
791+
else if (pg_strcasecmp(newval, "ignoreboth") == 0)
765792
pset.histcontrol = hctl_ignoreboth;
793+
else if (pg_strcasecmp(newval, "none") == 0)
794+
pset.histcontrol = hctl_none;
766795
else
796+
{
797+
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
798+
newval, "HISTCONTROL", "none");
767799
pset.histcontrol = hctl_none;
800+
}
768801
}
769802

770803
static void
@@ -790,14 +823,18 @@ verbosity_hook(const char *newval)
790823
{
791824
if (newval == NULL)
792825
pset.verbosity = PQERRORS_DEFAULT;
793-
else if (strcmp(newval, "default") == 0)
826+
else if (pg_strcasecmp(newval, "default") == 0)
794827
pset.verbosity = PQERRORS_DEFAULT;
795-
else if (strcmp(newval, "terse") == 0)
828+
else if (pg_strcasecmp(newval, "terse") == 0)
796829
pset.verbosity = PQERRORS_TERSE;
797-
else if (strcmp(newval, "verbose") == 0)
830+
else if (pg_strcasecmp(newval, "verbose") == 0)
798831
pset.verbosity = PQERRORS_VERBOSE;
799832
else
833+
{
834+
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
835+
newval, "VERBOSITY", "default");
800836
pset.verbosity = PQERRORS_DEFAULT;
837+
}
801838

802839
if (pset.db)
803840
PQsetErrorVerbosity(pset.db, pset.verbosity);
@@ -818,6 +855,7 @@ EstablishVariableSpace(void)
818855
SetVariableAssignHook(pset.vars, "ECHO", echo_hook);
819856
SetVariableAssignHook(pset.vars, "ECHO_HIDDEN", echo_hidden_hook);
820857
SetVariableAssignHook(pset.vars, "ON_ERROR_ROLLBACK", on_error_rollback_hook);
858+
SetVariableAssignHook(pset.vars, "COMP_KEYWORD_CASE", comp_keyword_case_hook);
821859
SetVariableAssignHook(pset.vars, "HISTCONTROL", histcontrol_hook);
822860
SetVariableAssignHook(pset.vars, "PROMPT1", prompt1_hook);
823861
SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook);

0 commit comments

Comments
 (0)