summaryrefslogtreecommitdiff
path: root/src/backend/utils/misc/guc_funcs.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2025-11-04 12:37:40 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2025-11-04 12:37:40 -0500
commitff4597acd4c3d957373335034e1ac16b6584c3e6 (patch)
tree4200936a64420820b780661b91d5111446c8b7fa /src/backend/utils/misc/guc_funcs.c
parent93b7ab5b4beee2f0cdef9d57d934e3a57638f5ca (diff)
Allow "SET list_guc TO NULL" to specify setting the GUC to empty.
We have never had a SET syntax that allows setting a GUC_LIST_INPUT parameter to be an empty list. A locution such as SET search_path = ''; doesn't mean that; it means setting the GUC to contain a single item that is an empty string. (For search_path the net effect is much the same, because search_path ignores invalid schema names and '' must be invalid.) This is confusing, not least because configuration-file entries and the set_config() function can easily produce empty-list values. We considered making the empty-string syntax do this, but that would foreclose ever allowing empty-string items to be valid in list GUCs. While there isn't any obvious use-case for that today, it feels like the kind of restriction that might hurt someday. Instead, let's accept the forbidden-up-to-now value NULL and treat that as meaning an empty list. (An objection to this could be "what if we someday want to allow NULL as a GUC value?". That seems unlikely though, and even if we did allow it for scalar GUCs, we could continue to treat it as meaning an empty list for list GUCs.) Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Andrei Klychkov <andrew.a.klychkov@gmail.com> Reviewed-by: Jim Jones <jim.jones@uni-muenster.de> Discussion: https://postgr.es/m/CA+mfrmwsBmYsJayWjc8bJmicxc3phZcHHY=yW5aYe=P-1d_4bg@mail.gmail.com
Diffstat (limited to 'src/backend/utils/misc/guc_funcs.c')
-rw-r--r--src/backend/utils/misc/guc_funcs.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/src/backend/utils/misc/guc_funcs.c b/src/backend/utils/misc/guc_funcs.c
index 4f58fa3d4e0..9dbc5d3aeb9 100644
--- a/src/backend/utils/misc/guc_funcs.c
+++ b/src/backend/utils/misc/guc_funcs.c
@@ -210,12 +210,29 @@ flatten_set_variable_args(const char *name, List *args)
else
flags = 0;
- /* Complain if list input and non-list variable */
- if ((flags & GUC_LIST_INPUT) == 0 &&
- list_length(args) != 1)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("SET %s takes only one argument", name)));
+ /*
+ * Handle special cases for list input.
+ */
+ if (flags & GUC_LIST_INPUT)
+ {
+ /* NULL represents an empty list. */
+ if (list_length(args) == 1)
+ {
+ Node *arg = (Node *) linitial(args);
+
+ if (IsA(arg, A_Const) &&
+ ((A_Const *) arg)->isnull)
+ return pstrdup("");
+ }
+ }
+ else
+ {
+ /* Complain if list input and non-list variable. */
+ if (list_length(args) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("SET %s takes only one argument", name)));
+ }
initStringInfo(&buf);
@@ -246,6 +263,12 @@ flatten_set_variable_args(const char *name, List *args)
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
con = (A_Const *) arg;
+ /* Complain if NULL is used with a non-list variable. */
+ if (con->isnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("NULL is an invalid value for %s", name)));
+
switch (nodeTag(&con->val))
{
case T_Integer:
@@ -269,6 +292,9 @@ flatten_set_variable_args(const char *name, List *args)
Datum interval;
char *intervalout;
+ /* gram.y ensures this is only reachable for TIME ZONE */
+ Assert(!(flags & GUC_LIST_QUOTE));
+
typenameTypeIdAndMod(NULL, typeName, &typoid, &typmod);
Assert(typoid == INTERVALOID);