Commit 28551797 authored by Tom Lane's avatar Tom Lane

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.
parent ba66c9d0
...@@ -173,8 +173,7 @@ EOF ...@@ -173,8 +173,7 @@ EOF
Echo the actual queries generated by <command>\d</command> and other backslash Echo the actual queries generated by <command>\d</command> and other backslash
commands. You can use this to study <application>psql</application>'s commands. You can use this to study <application>psql</application>'s
internal operations. This is equivalent to internal operations. This is equivalent to
setting the variable <varname>ECHO_HIDDEN</varname> from within setting the variable <varname>ECHO_HIDDEN</varname> to <literal>on</>.
<application>psql</application>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -333,8 +332,8 @@ EOF ...@@ -333,8 +332,8 @@ EOF
quietly. By default, it prints welcome messages and various quietly. By default, it prints welcome messages and various
informational output. If this option is used, none of this informational output. If this option is used, none of this
happens. This is useful with the <option>-c</option> option. happens. This is useful with the <option>-c</option> option.
Within <application>psql</application> you can also set the This is equivalent to setting the variable <varname>QUIET</varname>
<varname>QUIET</varname> variable to achieve the same effect. to <literal>on</>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -2884,8 +2883,9 @@ bar ...@@ -2884,8 +2883,9 @@ bar
<term><varname>ECHO_HIDDEN</varname></term> <term><varname>ECHO_HIDDEN</varname></term>
<listitem> <listitem>
<para> <para>
When this variable is set and a backslash command queries the When this variable is set to <literal>on</> and a backslash command
database, the query is first shown. This way you can study the queries the database, the query is first shown.
This feature helps you to study
<productname>PostgreSQL</productname> internals and provide <productname>PostgreSQL</productname> internals and provide
similar functionality in your own programs. (To select this behavior similar functionality in your own programs. (To select this behavior
on program start-up, use the switch <option>-E</option>.) If you set on program start-up, use the switch <option>-E</option>.) If you set
...@@ -3046,16 +3046,16 @@ bar ...@@ -3046,16 +3046,16 @@ bar
</term> </term>
<listitem> <listitem>
<para> <para>
When <literal>on</>, if a statement in a transaction block When set to <literal>on</>, if a statement in a transaction block
generates an error, the error is ignored and the transaction generates an error, the error is ignored and the transaction
continues. When <literal>interactive</>, such errors are only continues. When set to <literal>interactive</>, such errors are only
ignored in interactive sessions, and not when reading script ignored in interactive sessions, and not when reading script
files. When <literal>off</> (the default), a statement in a files. When unset or set to <literal>off</>, a statement in a
transaction block that generates an error aborts the entire transaction block that generates an error aborts the entire
transaction. The on_error_rollback-on mode works by issuing an transaction. The error rollback mode works by issuing an
implicit <command>SAVEPOINT</> for you, just before each command implicit <command>SAVEPOINT</> for you, just before each command
that is in a transaction block, and rolls back to the savepoint that is in a transaction block, and then rolling back to the
on error. savepoint if the command fails.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -3065,7 +3065,8 @@ bar ...@@ -3065,7 +3065,8 @@ bar
<listitem> <listitem>
<para> <para>
By default, command processing continues after an error. When this By default, command processing continues after an error. When this
variable is set, it will instead stop immediately. In interactive mode, variable is set to <literal>on</>, processing will instead stop
immediately. In interactive mode,
<application>psql</application> will return to the command prompt; <application>psql</application> will return to the command prompt;
otherwise, <application>psql</application> will exit, returning otherwise, <application>psql</application> will exit, returning
error code 3 to distinguish this case from fatal error error code 3 to distinguish this case from fatal error
...@@ -3107,8 +3108,8 @@ bar ...@@ -3107,8 +3108,8 @@ bar
<term><varname>QUIET</varname></term> <term><varname>QUIET</varname></term>
<listitem> <listitem>
<para> <para>
This variable is equivalent to the command line option Setting this variable to <literal>on</> is equivalent to the command
<option>-q</option>. It is probably not too useful in line option <option>-q</option>. It is probably not too useful in
interactive mode. interactive mode.
</para> </para>
</listitem> </listitem>
...@@ -3118,8 +3119,8 @@ bar ...@@ -3118,8 +3119,8 @@ bar
<term><varname>SINGLELINE</varname></term> <term><varname>SINGLELINE</varname></term>
<listitem> <listitem>
<para> <para>
This variable is equivalent to the command line option Setting this variable to <literal>on</> is equivalent to the command
<option>-S</option>. line option <option>-S</option>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -3128,8 +3129,8 @@ bar ...@@ -3128,8 +3129,8 @@ bar
<term><varname>SINGLESTEP</varname></term> <term><varname>SINGLESTEP</varname></term>
<listitem> <listitem>
<para> <para>
This variable is equivalent to the command line option Setting this variable to <literal>on</> is equivalent to the command
<option>-s</option>. line option <option>-s</option>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
...@@ -1362,7 +1362,7 @@ exec_command(const char *cmd, ...@@ -1362,7 +1362,7 @@ exec_command(const char *cmd,
OT_NORMAL, NULL, false); OT_NORMAL, NULL, false);
if (opt) if (opt)
pset.timing = ParseVariableBool(opt); pset.timing = ParseVariableBool(opt, "\\timing");
else else
pset.timing = !pset.timing; pset.timing = !pset.timing;
if (!pset.quiet) if (!pset.quiet)
...@@ -2412,12 +2412,14 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) ...@@ -2412,12 +2412,14 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
} }
/* set expanded/vertical mode */ /* set expanded/vertical mode */
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0) else if (strcmp(param, "x") == 0 ||
strcmp(param, "expanded") == 0 ||
strcmp(param, "vertical") == 0)
{ {
if (value && pg_strcasecmp(value, "auto") == 0) if (value && pg_strcasecmp(value, "auto") == 0)
popt->topt.expanded = 2; popt->topt.expanded = 2;
else if (value) else if (value)
popt->topt.expanded = ParseVariableBool(value); popt->topt.expanded = ParseVariableBool(value, param);
else else
popt->topt.expanded = !popt->topt.expanded; popt->topt.expanded = !popt->topt.expanded;
} }
...@@ -2426,7 +2428,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) ...@@ -2426,7 +2428,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
else if (strcmp(param, "numericlocale") == 0) else if (strcmp(param, "numericlocale") == 0)
{ {
if (value) if (value)
popt->topt.numericLocale = ParseVariableBool(value); popt->topt.numericLocale = ParseVariableBool(value, param);
else else
popt->topt.numericLocale = !popt->topt.numericLocale; popt->topt.numericLocale = !popt->topt.numericLocale;
} }
...@@ -2481,7 +2483,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) ...@@ -2481,7 +2483,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0) else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
{ {
if (value) if (value)
popt->topt.tuples_only = ParseVariableBool(value); popt->topt.tuples_only = ParseVariableBool(value, param);
else else
popt->topt.tuples_only = !popt->topt.tuples_only; popt->topt.tuples_only = !popt->topt.tuples_only;
} }
...@@ -2512,10 +2514,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) ...@@ -2512,10 +2514,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
if (value && pg_strcasecmp(value, "always") == 0) if (value && pg_strcasecmp(value, "always") == 0)
popt->topt.pager = 2; popt->topt.pager = 2;
else if (value) else if (value)
if (ParseVariableBool(value)) {
if (ParseVariableBool(value, param))
popt->topt.pager = 1; popt->topt.pager = 1;
else else
popt->topt.pager = 0; popt->topt.pager = 0;
}
else if (popt->topt.pager == 1) else if (popt->topt.pager == 1)
popt->topt.pager = 0; popt->topt.pager = 0;
else else
...@@ -2526,7 +2530,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) ...@@ -2526,7 +2530,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
else if (strcmp(param, "footer") == 0) else if (strcmp(param, "footer") == 0)
{ {
if (value) if (value)
popt->topt.default_footer = ParseVariableBool(value); popt->topt.default_footer = ParseVariableBool(value, param);
else else
popt->topt.default_footer = !popt->topt.default_footer; popt->topt.default_footer = !popt->topt.default_footer;
} }
......
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
#define DEFAULT_PROMPT2 "%/%R%# " #define DEFAULT_PROMPT2 "%/%R%# "
#define DEFAULT_PROMPT3 ">> " #define DEFAULT_PROMPT3 ">> "
/*
* Note: these enums should generally be chosen so that zero corresponds
* to the default behavior.
*/
typedef enum typedef enum
{ {
PSQL_ECHO_NONE, PSQL_ECHO_NONE,
...@@ -49,6 +54,14 @@ typedef enum ...@@ -49,6 +54,14 @@ typedef enum
PSQL_ERROR_ROLLBACK_ON PSQL_ERROR_ROLLBACK_ON
} PSQL_ERROR_ROLLBACK; } PSQL_ERROR_ROLLBACK;
typedef enum
{
PSQL_COMP_CASE_PRESERVE_UPPER,
PSQL_COMP_CASE_PRESERVE_LOWER,
PSQL_COMP_CASE_UPPER,
PSQL_COMP_CASE_LOWER
} PSQL_COMP_CASE;
typedef enum typedef enum
{ {
hctl_none = 0, hctl_none = 0,
...@@ -110,6 +123,7 @@ typedef struct _psqlSettings ...@@ -110,6 +123,7 @@ typedef struct _psqlSettings
PSQL_ECHO echo; PSQL_ECHO echo;
PSQL_ECHO_HIDDEN echo_hidden; PSQL_ECHO_HIDDEN echo_hidden;
PSQL_ERROR_ROLLBACK on_error_rollback; PSQL_ERROR_ROLLBACK on_error_rollback;
PSQL_COMP_CASE comp_case;
HistControl histcontrol; HistControl histcontrol;
const char *prompt1; const char *prompt1;
const char *prompt2; const char *prompt2;
......
...@@ -705,31 +705,31 @@ showVersion(void) ...@@ -705,31 +705,31 @@ showVersion(void)
static void static void
autocommit_hook(const char *newval) autocommit_hook(const char *newval)
{ {
pset.autocommit = ParseVariableBool(newval); pset.autocommit = ParseVariableBool(newval, "AUTOCOMMIT");
} }
static void static void
on_error_stop_hook(const char *newval) on_error_stop_hook(const char *newval)
{ {
pset.on_error_stop = ParseVariableBool(newval); pset.on_error_stop = ParseVariableBool(newval, "ON_ERROR_STOP");
} }
static void static void
quiet_hook(const char *newval) quiet_hook(const char *newval)
{ {
pset.quiet = ParseVariableBool(newval); pset.quiet = ParseVariableBool(newval, "QUIET");
} }
static void static void
singleline_hook(const char *newval) singleline_hook(const char *newval)
{ {
pset.singleline = ParseVariableBool(newval); pset.singleline = ParseVariableBool(newval, "SINGLELINE");
} }
static void static void
singlestep_hook(const char *newval) singlestep_hook(const char *newval)
{ {
pset.singlestep = ParseVariableBool(newval); pset.singlestep = ParseVariableBool(newval, "SINGLESTEP");
} }
static void static void
...@@ -743,14 +743,20 @@ echo_hook(const char *newval) ...@@ -743,14 +743,20 @@ echo_hook(const char *newval)
{ {
if (newval == NULL) if (newval == NULL)
pset.echo = PSQL_ECHO_NONE; pset.echo = PSQL_ECHO_NONE;
else if (strcmp(newval, "queries") == 0) else if (pg_strcasecmp(newval, "queries") == 0)
pset.echo = PSQL_ECHO_QUERIES; pset.echo = PSQL_ECHO_QUERIES;
else if (strcmp(newval, "errors") == 0) else if (pg_strcasecmp(newval, "errors") == 0)
pset.echo = PSQL_ECHO_ERRORS; pset.echo = PSQL_ECHO_ERRORS;
else if (strcmp(newval, "all") == 0) else if (pg_strcasecmp(newval, "all") == 0)
pset.echo = PSQL_ECHO_ALL; pset.echo = PSQL_ECHO_ALL;
else if (pg_strcasecmp(newval, "none") == 0)
pset.echo = PSQL_ECHO_NONE;
else else
{
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
newval, "ECHO", "none");
pset.echo = PSQL_ECHO_NONE; pset.echo = PSQL_ECHO_NONE;
}
} }
static void static void
...@@ -758,12 +764,12 @@ echo_hidden_hook(const char *newval) ...@@ -758,12 +764,12 @@ echo_hidden_hook(const char *newval)
{ {
if (newval == NULL) if (newval == NULL)
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF; pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
else if (strcmp(newval, "noexec") == 0) else if (pg_strcasecmp(newval, "noexec") == 0)
pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC; pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC;
else if (pg_strcasecmp(newval, "off") == 0) else if (ParseVariableBool(newval, "ECHO_HIDDEN"))
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
else
pset.echo_hidden = PSQL_ECHO_HIDDEN_ON; pset.echo_hidden = PSQL_ECHO_HIDDEN_ON;
else /* ParseVariableBool printed msg if needed */
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
} }
static void static void
...@@ -773,10 +779,31 @@ on_error_rollback_hook(const char *newval) ...@@ -773,10 +779,31 @@ on_error_rollback_hook(const char *newval)
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF; pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
else if (pg_strcasecmp(newval, "interactive") == 0) else if (pg_strcasecmp(newval, "interactive") == 0)
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE; pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
else if (pg_strcasecmp(newval, "off") == 0) else if (ParseVariableBool(newval, "ON_ERROR_ROLLBACK"))
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON;
else /* ParseVariableBool printed msg if needed */
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF; pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
}
static void
comp_keyword_case_hook(const char *newval)
{
if (newval == NULL)
pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER;
else if (pg_strcasecmp(newval, "preserve-upper") == 0)
pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER;
else if (pg_strcasecmp(newval, "preserve-lower") == 0)
pset.comp_case = PSQL_COMP_CASE_PRESERVE_LOWER;
else if (pg_strcasecmp(newval, "upper") == 0)
pset.comp_case = PSQL_COMP_CASE_UPPER;
else if (pg_strcasecmp(newval, "lower") == 0)
pset.comp_case = PSQL_COMP_CASE_LOWER;
else else
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON; {
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
newval, "COMP_KEYWORD_CASE", "preserve-upper");
pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER;
}
} }
static void static void
...@@ -784,14 +811,20 @@ histcontrol_hook(const char *newval) ...@@ -784,14 +811,20 @@ histcontrol_hook(const char *newval)
{ {
if (newval == NULL) if (newval == NULL)
pset.histcontrol = hctl_none; pset.histcontrol = hctl_none;
else if (strcmp(newval, "ignorespace") == 0) else if (pg_strcasecmp(newval, "ignorespace") == 0)
pset.histcontrol = hctl_ignorespace; pset.histcontrol = hctl_ignorespace;
else if (strcmp(newval, "ignoredups") == 0) else if (pg_strcasecmp(newval, "ignoredups") == 0)
pset.histcontrol = hctl_ignoredups; pset.histcontrol = hctl_ignoredups;
else if (strcmp(newval, "ignoreboth") == 0) else if (pg_strcasecmp(newval, "ignoreboth") == 0)
pset.histcontrol = hctl_ignoreboth; pset.histcontrol = hctl_ignoreboth;
else if (pg_strcasecmp(newval, "none") == 0)
pset.histcontrol = hctl_none;
else else
{
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
newval, "HISTCONTROL", "none");
pset.histcontrol = hctl_none; pset.histcontrol = hctl_none;
}
} }
static void static void
...@@ -817,14 +850,18 @@ verbosity_hook(const char *newval) ...@@ -817,14 +850,18 @@ verbosity_hook(const char *newval)
{ {
if (newval == NULL) if (newval == NULL)
pset.verbosity = PQERRORS_DEFAULT; pset.verbosity = PQERRORS_DEFAULT;
else if (strcmp(newval, "default") == 0) else if (pg_strcasecmp(newval, "default") == 0)
pset.verbosity = PQERRORS_DEFAULT; pset.verbosity = PQERRORS_DEFAULT;
else if (strcmp(newval, "terse") == 0) else if (pg_strcasecmp(newval, "terse") == 0)
pset.verbosity = PQERRORS_TERSE; pset.verbosity = PQERRORS_TERSE;
else if (strcmp(newval, "verbose") == 0) else if (pg_strcasecmp(newval, "verbose") == 0)
pset.verbosity = PQERRORS_VERBOSE; pset.verbosity = PQERRORS_VERBOSE;
else else
{
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
newval, "VERBOSITY", "default");
pset.verbosity = PQERRORS_DEFAULT; pset.verbosity = PQERRORS_DEFAULT;
}
if (pset.db) if (pset.db)
PQsetErrorVerbosity(pset.db, pset.verbosity); PQsetErrorVerbosity(pset.db, pset.verbosity);
...@@ -845,6 +882,7 @@ EstablishVariableSpace(void) ...@@ -845,6 +882,7 @@ EstablishVariableSpace(void)
SetVariableAssignHook(pset.vars, "ECHO", echo_hook); SetVariableAssignHook(pset.vars, "ECHO", echo_hook);
SetVariableAssignHook(pset.vars, "ECHO_HIDDEN", echo_hidden_hook); SetVariableAssignHook(pset.vars, "ECHO_HIDDEN", echo_hidden_hook);
SetVariableAssignHook(pset.vars, "ON_ERROR_ROLLBACK", on_error_rollback_hook); SetVariableAssignHook(pset.vars, "ON_ERROR_ROLLBACK", on_error_rollback_hook);
SetVariableAssignHook(pset.vars, "COMP_KEYWORD_CASE", comp_keyword_case_hook);
SetVariableAssignHook(pset.vars, "HISTCONTROL", histcontrol_hook); SetVariableAssignHook(pset.vars, "HISTCONTROL", histcontrol_hook);
SetVariableAssignHook(pset.vars, "PROMPT1", prompt1_hook); SetVariableAssignHook(pset.vars, "PROMPT1", prompt1_hook);
SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook); SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook);
......
...@@ -4453,7 +4453,7 @@ complete_from_files(const char *text, int state) ...@@ -4453,7 +4453,7 @@ complete_from_files(const char *text, int state)
/* /*
* Make a pg_strdup copy of s and convert the case according to * Make a pg_strdup copy of s and convert the case according to
* COMP_KEYWORD_CASE variable, using ref as the text that was already entered. * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
*/ */
static char * static char *
pg_strdup_keyword_case(const char *s, const char *ref) pg_strdup_keyword_case(const char *s, const char *ref)
...@@ -4461,38 +4461,22 @@ pg_strdup_keyword_case(const char *s, const char *ref) ...@@ -4461,38 +4461,22 @@ pg_strdup_keyword_case(const char *s, const char *ref)
char *ret, char *ret,
*p; *p;
unsigned char first = ref[0]; unsigned char first = ref[0];
int tocase;
const char *varval;
varval = GetVariable(pset.vars, "COMP_KEYWORD_CASE");
if (!varval)
tocase = 0;
else if (strcmp(varval, "lower") == 0)
tocase = -2;
else if (strcmp(varval, "preserve-lower") == 0)
tocase = -1;
else if (strcmp(varval, "preserve-upper") == 0)
tocase = +1;
else if (strcmp(varval, "upper") == 0)
tocase = +2;
else
tocase = 0;
/* default */
if (tocase == 0)
tocase = +1;
ret = pg_strdup(s); ret = pg_strdup(s);
if (tocase == -2 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
|| ((tocase == -1 || tocase == +1) && islower(first)) ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
|| (tocase == -1 && !isalpha(first)) pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
) (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
{
for (p = ret; *p; p++) for (p = ret; *p; p++)
*p = pg_tolower((unsigned char) *p); *p = pg_tolower((unsigned char) *p);
}
else else
{
for (p = ret; *p; p++) for (p = ret; *p; p++)
*p = pg_toupper((unsigned char) *p); *p = pg_toupper((unsigned char) *p);
}
return ret; return ret;
} }
......
...@@ -79,11 +79,16 @@ GetVariable(VariableSpace space, const char *name) ...@@ -79,11 +79,16 @@ GetVariable(VariableSpace space, const char *name)
} }
/* /*
* Try to interpret value as boolean value. Valid values are: true, * Try to interpret "value" as boolean value.
* false, yes, no, on, off, 1, 0; as well as unique prefixes thereof. *
* Valid values are: true, false, yes, no, on, off, 1, 0; as well as unique
* prefixes thereof.
*
* "name" is the name of the variable we're assigning to, to use in error
* report if any. Pass name == NULL to suppress the error report.
*/ */
bool bool
ParseVariableBool(const char *value) ParseVariableBool(const char *value, const char *name)
{ {
size_t len; size_t len;
...@@ -112,7 +117,9 @@ ParseVariableBool(const char *value) ...@@ -112,7 +117,9 @@ ParseVariableBool(const char *value)
else else
{ {
/* NULL is treated as false, so a non-matching value is 'true' */ /* NULL is treated as false, so a non-matching value is 'true' */
psql_error("unrecognized Boolean value; assuming \"on\"\n"); if (name)
psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
value, name, "on");
return true; return true;
} }
} }
......
...@@ -35,7 +35,7 @@ typedef struct _variable *VariableSpace; ...@@ -35,7 +35,7 @@ typedef struct _variable *VariableSpace;
VariableSpace CreateVariableSpace(void); VariableSpace CreateVariableSpace(void);
const char *GetVariable(VariableSpace space, const char *name); const char *GetVariable(VariableSpace space, const char *name);
bool ParseVariableBool(const char *val); bool ParseVariableBool(const char *value, const char *name);
int ParseVariableNum(const char *val, int ParseVariableNum(const char *val,
int defaultval, int defaultval,
int faultval, int faultval,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment