postgres.git / summary / log / commit / refs
commit 2600e44364cbbf418bcff39ce1d45025e9844386
Author: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed Dec 31 17:17:12 2014 +0000
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.
doc/src/sgml/ref/psql-ref.sgml | 43 ++++++++++++++++----------------
src/bin/psql/command.c | 18 ++++++++------
src/bin/psql/startup.c | 56 +++++++++++++++++++++++++++---------------
src/bin/psql/variables.c | 15 ++++++++---
src/bin/psql/variables.h | 2 +-
5 files changed, 81 insertions(+), 53 deletions(-)
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index c90947bba90..f382034c313 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -157,8 +157,7 @@ EOF
Echo the actual queries generated by <command>\d</command> and other backslash
commands. You can use this to study <application>psql</application>'s
internal operations. This is equivalent to
- setting the variable <varname>ECHO_HIDDEN</varname> from within
- <application>psql</application>.
+ setting the variable <varname>ECHO_HIDDEN</varname> to <literal>on</>.
</para>
</listitem>
</varlistentry>
@@ -317,8 +316,8 @@ EOF
quietly. By default, it prints welcome messages and various
informational output. If this option is used, none of this
happens. This is useful with the <option>-c</option> option.
- Within <application>psql</application> you can also set the
- <varname>QUIET</varname> variable to achieve the same effect.
+ This is equivalent to setting the variable <varname>QUIET</varname>
+ to <literal>on</>.
</para>
</listitem>
</varlistentry>
@@ -2455,8 +2454,9 @@ bar
<term><varname>ECHO_HIDDEN</varname></term>
<listitem>
<para>
- When this variable is set and a backslash command queries the
- database, the query is first shown. This way you can study the
+ When this variable is set to <literal>on</> and a backslash command
+ queries the database, the query is first shown.
+ This feature helps you to study
<productname>PostgreSQL</productname> internals and provide
similar functionality in your own programs. (To select this behavior
on program start-up, use the switch <option>-E</option>.) If you set
@@ -2614,16 +2614,16 @@ bar
<term><varname>ON_ERROR_ROLLBACK</varname></term>
<listitem>
<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
- 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
- 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. 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
- that is in a transaction block, and rolls back to the savepoint
- on error.
+ that is in a transaction block, and then rolling back to the
+ savepoint if the command fails.
</para>
</listitem>
</varlistentry>
@@ -2636,9 +2636,10 @@ bar
as a malformed <acronym>SQL</acronym> command or internal
meta-command, processing continues. This has been the
traditional behavior of <application>psql</application> but it
- is sometimes not desirable. If this variable is set, script
- processing will immediately terminate. If the script was called
- from another script it will terminate in the same fashion. If
+ is sometimes not desirable. If this variable is set to <literal>on</>,
+ script processing will immediately terminate after an error.
+ If the script was called
+ from another script, that one will terminate in the same fashion. If
the outermost script was not called from an interactive
<application>psql</application> session but rather using the
<option>-f</option> option, <application>psql</application> will
@@ -2677,8 +2678,8 @@ bar
<term><varname>QUIET</varname></term>
<listitem>
<para>
- This variable is equivalent to the command line option
- <option>-q</option>. It is probably not too useful in
+ Setting this variable to <literal>on</> is equivalent to the command
+ line option <option>-q</option>. It is probably not too useful in
interactive mode.
</para>
</listitem>
@@ -2688,8 +2689,8 @@ bar
<term><varname>SINGLELINE</varname></term>
<listitem>
<para>
- This variable is equivalent to the command line option
- <option>-S</option>.
+ Setting this variable to <literal>on</> is equivalent to the command
+ line option <option>-S</option>.
</para>
</listitem>
</varlistentry>
@@ -2698,8 +2699,8 @@ bar
<term><varname>SINGLESTEP</varname></term>
<listitem>
<para>
- This variable is equivalent to the command line option
- <option>-s</option>.
+ Setting this variable to <literal>on</> is equivalent to the command
+ line option <option>-s</option>.
</para>
</listitem>
</varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 35c757ec415..d2967edaa0a 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1025,7 +1025,7 @@ exec_command(const char *cmd,
OT_NORMAL, NULL, false);
if (opt)
- pset.timing = ParseVariableBool(opt);
+ pset.timing = ParseVariableBool(opt, "\\timing");
else
pset.timing = !pset.timing;
if (!pset.quiet)
@@ -1882,10 +1882,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
}
/* 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)
- popt->topt.expanded = ParseVariableBool(value);
+ popt->topt.expanded = ParseVariableBool(value, param);
else
popt->topt.expanded = !popt->topt.expanded;
if (!quiet)
@@ -1898,7 +1900,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
else if (strcmp(param, "numericlocale") == 0)
{
if (value)
- popt->topt.numericLocale = ParseVariableBool(value);
+ popt->topt.numericLocale = ParseVariableBool(value, param);
else
popt->topt.numericLocale = !popt->topt.numericLocale;
if (!quiet)
@@ -1955,7 +1957,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
{
if (value)
- popt->topt.tuples_only = ParseVariableBool(value);
+ popt->topt.tuples_only = ParseVariableBool(value, param);
else
popt->topt.tuples_only = !popt->topt.tuples_only;
if (!quiet)
@@ -2009,10 +2011,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
if (value && pg_strcasecmp(value, "always") == 0)
popt->topt.pager = 2;
else if (value)
- if (ParseVariableBool(value))
+ {
+ if (ParseVariableBool(value, param))
popt->topt.pager = 1;
else
popt->topt.pager = 0;
+ }
else if (popt->topt.pager == 1)
popt->topt.pager = 0;
else
@@ -2032,7 +2036,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
else if (strcmp(param, "footer") == 0)
{
if (value)
- popt->default_footer = ParseVariableBool(value);
+ popt->default_footer = ParseVariableBool(value, param);
else
popt->default_footer = !popt->default_footer;
if (!quiet)
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 805909ea254..15a0965865f 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -631,31 +631,31 @@ showVersion(void)
static void
autocommit_hook(const char *newval)
{
- pset.autocommit = ParseVariableBool(newval);
+ pset.autocommit = ParseVariableBool(newval, "AUTOCOMMIT");
}
static void
on_error_stop_hook(const char *newval)
{
- pset.on_error_stop = ParseVariableBool(newval);
+ pset.on_error_stop = ParseVariableBool(newval, "ON_ERROR_STOP");
}
static void
quiet_hook(const char *newval)
{
- pset.quiet = ParseVariableBool(newval);
+ pset.quiet = ParseVariableBool(newval, "QUIET");
}
static void
singleline_hook(const char *newval)
{
- pset.singleline = ParseVariableBool(newval);
+ pset.singleline = ParseVariableBool(newval, "SINGLELINE");
}
static void
singlestep_hook(const char *newval)
{
- pset.singlestep = ParseVariableBool(newval);
+ pset.singlestep = ParseVariableBool(newval, "SINGLESTEP");
}
static void
@@ -669,12 +669,18 @@ echo_hook(const char *newval)
{
if (newval == NULL)
pset.echo = PSQL_ECHO_NONE;
- else if (strcmp(newval, "queries") == 0)
+ else if (pg_strcasecmp(newval, "queries") == 0)
pset.echo = PSQL_ECHO_QUERIES;
- else if (strcmp(newval, "all") == 0)
+ else if (pg_strcasecmp(newval, "all") == 0)
pset.echo = PSQL_ECHO_ALL;
+ else if (pg_strcasecmp(newval, "none") == 0)
+ pset.echo = PSQL_ECHO_NONE;
else
+ {
+ psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
+ newval, "ECHO", "none");
pset.echo = PSQL_ECHO_NONE;
+ }
}
static void
@@ -682,12 +688,12 @@ echo_hidden_hook(const char *newval)
{
if (newval == NULL)
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;
- else if (pg_strcasecmp(newval, "off") == 0)
- pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
- else
+ else if (ParseVariableBool(newval, "ECHO_HIDDEN"))
pset.echo_hidden = PSQL_ECHO_HIDDEN_ON;
+ else /* ParseVariableBool printed msg if needed */
+ pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
}
static void
@@ -697,10 +703,10 @@ on_error_rollback_hook(const char *newval)
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
else if (pg_strcasecmp(newval, "interactive") == 0)
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
- else if (pg_strcasecmp(newval, "off") == 0)
- pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
- else
+ 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;
}
static void
@@ -708,14 +714,20 @@ histcontrol_hook(const char *newval)
{
if (newval == NULL)
pset.histcontrol = hctl_none;
- else if (strcmp(newval, "ignorespace") == 0)
+ else if (pg_strcasecmp(newval, "ignorespace") == 0)
pset.histcontrol = hctl_ignorespace;
- else if (strcmp(newval, "ignoredups") == 0)
+ else if (pg_strcasecmp(newval, "ignoredups") == 0)
pset.histcontrol = hctl_ignoredups;
- else if (strcmp(newval, "ignoreboth") == 0)
+ else if (pg_strcasecmp(newval, "ignoreboth") == 0)
pset.histcontrol = hctl_ignoreboth;
+ else if (pg_strcasecmp(newval, "none") == 0)
+ pset.histcontrol = hctl_none;
else
+ {
+ psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
+ newval, "HISTCONTROL", "none");
pset.histcontrol = hctl_none;
+ }
}
static void
@@ -741,14 +753,18 @@ verbosity_hook(const char *newval)
{
if (newval == NULL)
pset.verbosity = PQERRORS_DEFAULT;
- else if (strcmp(newval, "default") == 0)
+ else if (pg_strcasecmp(newval, "default") == 0)
pset.verbosity = PQERRORS_DEFAULT;
- else if (strcmp(newval, "terse") == 0)
+ else if (pg_strcasecmp(newval, "terse") == 0)
pset.verbosity = PQERRORS_TERSE;
- else if (strcmp(newval, "verbose") == 0)
+ else if (pg_strcasecmp(newval, "verbose") == 0)
pset.verbosity = PQERRORS_VERBOSE;
else
+ {
+ psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
+ newval, "VERBOSITY", "default");
pset.verbosity = PQERRORS_DEFAULT;
+ }
if (pset.db)
PQsetErrorVerbosity(pset.db, pset.verbosity);
diff --git a/src/bin/psql/variables.c b/src/bin/psql/variables.c
index 7a479a50604..ce0d983f52c 100644
--- a/src/bin/psql/variables.c
+++ b/src/bin/psql/variables.c
@@ -49,11 +49,16 @@ GetVariable(VariableSpace space, const char *name)
}
/*
- * Try to interpret value as boolean value. Valid values are: true,
- * false, yes, no, on, off, 1, 0; as well as unique prefixes thereof.
+ * Try to interpret "value" as boolean value.
+ *
+ * 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
-ParseVariableBool(const char *value)
+ParseVariableBool(const char *value, const char *name)
{
size_t len;
@@ -82,7 +87,9 @@ ParseVariableBool(const char *value)
else
{
/* 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;
}
/* suppress compiler warning */
diff --git a/src/bin/psql/variables.h b/src/bin/psql/variables.h
index eb73ebdc062..2c49137e4dc 100644
--- a/src/bin/psql/variables.h
+++ b/src/bin/psql/variables.h
@@ -39,7 +39,7 @@ typedef struct _variable *VariableSpace;
VariableSpace CreateVariableSpace(void);
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 defaultval,
int faultval,
[parent: 9b74f35744b6]