aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/variables.h
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-02-01 11:02:40 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2017-02-01 11:02:40 -0500
commit86322dc7e013b4062393dcbb74043db003e23ec5 (patch)
treeb209a1ef6c679a3e53b92f146189b0a7cfe92343 /src/bin/psql/variables.h
parentdbd69118c05d73969a1bd52ead6702c6e40b0fee (diff)
downloadpostgresql-86322dc7e013b4062393dcbb74043db003e23ec5.tar.gz
postgresql-86322dc7e013b4062393dcbb74043db003e23ec5.zip
Improve psql's behavior for \set and \unset of its control variables.
This commit improves on the results of commit 511ae628f in two ways: 1. It restores the historical behavior that "\set FOO" is interpreted as setting FOO to "on", if FOO is a boolean control variable. We already found one test script that was expecting that behavior, and the psql documentation certainly does nothing to discourage people from assuming that would work, since it often says just "if FOO is set" when describing the effects of a boolean variable. However, now this case will result in actually setting FOO to "on", not an empty string. 2. It arranges for an "\unset" of a control variable to set the value back to its default value, rather than becoming apparently undefined. The control variables are also initialized that way at psql startup. In combination, these things guarantee that a control variable always has a displayable value that reflects what psql is actually doing. That is a pretty substantial usability improvement. The implementation involves adding a second type of variable hook function that is able to replace a proposed new value (including NULL) with another one. We could alternatively have complicated the API of the assign hook, but this way seems better since many variables can share the same substitution hook function. Also document the actual behavior of these variables more fully, including covering assorted behaviors that were there before but never documented. This patch also includes some minor cleanup that should have been in 511ae628f but was missed. Patch by me, but it owes a lot to discussions with Daniel Vérité. Discussion: https://postgr.es/m/9572.1485821620@sss.pgh.pa.us
Diffstat (limited to 'src/bin/psql/variables.h')
-rw-r--r--src/bin/psql/variables.h35
1 files changed, 31 insertions, 4 deletions
diff --git a/src/bin/psql/variables.h b/src/bin/psql/variables.h
index 274b4af5537..84be7805098 100644
--- a/src/bin/psql/variables.h
+++ b/src/bin/psql/variables.h
@@ -18,12 +18,12 @@
* prevent invalid values from being assigned, and can update internal C
* variables to keep them in sync with the variable's current value.
*
- * A hook function is called before any attempted assignment, with the
+ * An assign hook function is called before any attempted assignment, with the
* proposed new value of the variable (or with NULL, if an \unset is being
* attempted). If it returns false, the assignment doesn't occur --- it
* should print an error message with psql_error() to tell the user why.
*
- * When a hook function is installed with SetVariableAssignHook(), it is
+ * When an assign hook function is installed with SetVariableHooks(), it is
* called with the variable's current value (or with NULL, if it wasn't set
* yet). But its return value is ignored in this case. The hook should be
* set before any possibly-invalid value can be assigned.
@@ -31,15 +31,39 @@
typedef bool (*VariableAssignHook) (const char *newval);
/*
+ * Variables can also be given "substitute hook" functions. The substitute
+ * hook can replace values (including NULL) with other values, allowing
+ * normalization of variable contents. For example, for a boolean variable,
+ * we wish to interpret "\unset FOO" as "\set FOO off", and we can do that
+ * by installing a substitute hook. (We can use the same substitute hook
+ * for all bool or nearly-bool variables, which is why this responsibility
+ * isn't part of the assign hook.)
+ *
+ * The substitute hook is called before any attempted assignment, and before
+ * the assign hook if any, passing the proposed new value of the variable as a
+ * malloc'd string (or NULL, if an \unset is being attempted). It can return
+ * the same value, or a different malloc'd string, or modify the string
+ * in-place. It should free the passed-in value if it's not returning it.
+ * The substitute hook generally should not complain about erroneous values;
+ * that's a job for the assign hook.
+ *
+ * When a substitute hook is installed with SetVariableHooks(), it is applied
+ * to the variable's current value (typically NULL, if it wasn't set yet).
+ * That also happens before applying the assign hook.
+ */
+typedef char *(*VariableSubstituteHook) (char *newval);
+
+/*
* Data structure representing one variable.
*
* Note: if value == NULL then the variable is logically unset, but we are
- * keeping the struct around so as not to forget about its hook function.
+ * keeping the struct around so as not to forget about its hook function(s).
*/
struct _variable
{
char *name;
char *value;
+ VariableSubstituteHook substitute_hook;
VariableAssignHook assign_hook;
struct _variable *next;
};
@@ -65,10 +89,13 @@ int GetVariableNum(VariableSpace space,
void PrintVariables(VariableSpace space);
bool SetVariable(VariableSpace space, const char *name, const char *value);
-void SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook);
bool SetVariableBool(VariableSpace space, const char *name);
bool DeleteVariable(VariableSpace space, const char *name);
+void SetVariableHooks(VariableSpace space, const char *name,
+ VariableSubstituteHook shook,
+ VariableAssignHook ahook);
+
void PsqlVarEnumError(const char *name, const char *value, const char *suggestions);
#endif /* VARIABLES_H */