Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitff4597a

Browse files
committed
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_INPUTparameter to be an empty list. A locution such asSET search_path = '';doesn't mean that; it means setting the GUC to contain a single itemthat is an empty string. (For search_path the net effect is much thesame, because search_path ignores invalid schema names and '' must beinvalid.) This is confusing, not least because configuration-fileentries and the set_config() function can easily produce empty-listvalues.We considered making the empty-string syntax do this, but that wouldforeclose ever allowing empty-string items to be valid in list GUCs.While there isn't any obvious use-case for that today, it feels likethe kind of restriction that might hurt someday. Instead, let'saccept the forbidden-up-to-now value NULL and treat that as meaning anempty list. (An objection to this could be "what if we someday wantto allow NULL as a GUC value?". That seems unlikely though, and evenif we did allow it for scalar GUCs, we could continue to treat it asmeaning 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
1 parent93b7ab5 commitff4597a

File tree

12 files changed

+135
-17
lines changed

12 files changed

+135
-17
lines changed

‎doc/src/sgml/ref/alter_system.sgml‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ ALTER SYSTEM RESET ALL
8484
constants, identifiers, numbers, or comma-separated lists of
8585
these, as appropriate for the particular parameter.
8686
Values that are neither numbers nor valid identifiers must be quoted.
87+
If the parameter accepts a list of values, <literal>NULL</literal>
88+
can be written to specify an empty list.
8789
<literal>DEFAULT</literal> can be written to specify removing the
8890
parameter and its value from <filename>postgresql.auto.conf</filename>.
8991
</para>
@@ -136,7 +138,15 @@ ALTER SYSTEM SET wal_level = replica;
136138
in <filename>postgresql.conf</filename>:
137139
<programlisting>
138140
ALTER SYSTEM RESET wal_level;
139-
</programlisting></para>
141+
</programlisting>
142+
</para>
143+
144+
<para>
145+
Set the list of preloaded extension modules to be empty:
146+
<programlisting>
147+
ALTER SYSTEM SET shared_preload_libraries TO NULL;
148+
</programlisting>
149+
</para>
140150
</refsect1>
141151

142152
<refsect1>

‎doc/src/sgml/ref/set.sgml‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ PostgreSQL documentation
2121

2222
<refsynopsisdiv>
2323
<synopsis>
24-
SET [ SESSION | LOCAL ] <replaceable class="parameter">configuration_parameter</replaceable> { TO | = } { <replaceable class="parameter">value</replaceable>| '<replaceable class="parameter">value</replaceable>' | DEFAULT }
25-
SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="parameter">value</replaceable> |'<replaceable class="parameter">value</replaceable>' |LOCAL | DEFAULT }
24+
SET [ SESSION | LOCAL ] <replaceable class="parameter">configuration_parameter</replaceable> { TO | = } { <replaceable class="parameter">value</replaceable>[, ...] | DEFAULT }
25+
SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="parameter">value</replaceable> | LOCAL | DEFAULT }
2626
</synopsis>
2727
</refsynopsisdiv>
2828

@@ -123,7 +123,7 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="parameter">value</replac
123123
<term><replaceable class="parameter">configuration_parameter</replaceable></term>
124124
<listitem>
125125
<para>
126-
Name of a settablerun-time parameter. Available parameters are
126+
Name of a settableconfiguration parameter. Available parameters are
127127
documented in <xref linkend="runtime-config"/> and below.
128128
</para>
129129
</listitem>
@@ -133,9 +133,12 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="parameter">value</replac
133133
<term><replaceable class="parameter">value</replaceable></term>
134134
<listitem>
135135
<para>
136-
New value of parameter. Values can be specified as string
136+
New value oftheparameter. Values can be specified as string
137137
constants, identifiers, numbers, or comma-separated lists of
138138
these, as appropriate for the particular parameter.
139+
Values that are neither numbers nor valid identifiers must be quoted.
140+
If the parameter accepts a list of values, <literal>NULL</literal>
141+
can be written to specify an empty list.
139142
<literal>DEFAULT</literal> can be written to specify
140143
resetting the parameter to its default value (that is, whatever
141144
value it would have had if no <command>SET</command> had been executed
@@ -283,6 +286,19 @@ SELECT setseed(<replaceable>value</replaceable>);
283286
Set the schema search path:
284287
<programlisting>
285288
SET search_path TO my_schema, public;
289+
</programlisting>
290+
Note that this is not the same as
291+
<programlisting>
292+
SET search_path TO 'my_schema, public';
293+
</programlisting>
294+
which would have the effect of setting <varname>search_path</varname>
295+
to contain a single, probably-nonexistent schema name.
296+
</para>
297+
298+
<para>
299+
Set the list of temporary tablespace names to be empty:
300+
<programlisting>
301+
SET temp_tablespaces TO NULL;
286302
</programlisting>
287303
</para>
288304

‎src/backend/parser/gram.y‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,6 +1716,26 @@ generic_set:
17161716
n->location = @3;
17171717
$$ = n;
17181718
}
1719+
| var_name TO NULL_P
1720+
{
1721+
VariableSetStmt *n = makeNode(VariableSetStmt);
1722+
1723+
n->kind = VAR_SET_VALUE;
1724+
n->name = $1;
1725+
n->args = list_make1(makeNullAConst(@3));
1726+
n->location = @3;
1727+
$$ = n;
1728+
}
1729+
| var_name '=' NULL_P
1730+
{
1731+
VariableSetStmt *n = makeNode(VariableSetStmt);
1732+
1733+
n->kind = VAR_SET_VALUE;
1734+
n->name = $1;
1735+
n->args = list_make1(makeNullAConst(@3));
1736+
n->location = @3;
1737+
$$ = n;
1738+
}
17191739
| var_name TO DEFAULT
17201740
{
17211741
VariableSetStmt *n = makeNode(VariableSetStmt);

‎src/backend/utils/adt/ruleutils.c‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3087,7 +3087,8 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
30873087
* string literals. (The elements may be double-quoted as-is,
30883088
* but we can't just feed them to the SQL parser; it would do
30893089
* the wrong thing with elements that are zero-length or
3090-
* longer than NAMEDATALEN.)
3090+
* longer than NAMEDATALEN.) Also, we need a special case for
3091+
* empty lists.
30913092
*
30923093
* Variables that are not so marked should just be emitted as
30933094
* simple string literals. If the variable is not known to
@@ -3105,6 +3106,9 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
31053106
/* this shouldn't fail really */
31063107
elog(ERROR,"invalid list syntax in proconfig item");
31073108
}
3109+
/* Special case: represent an empty list as NULL */
3110+
if (namelist==NIL)
3111+
appendStringInfoString(&buf,"NULL");
31083112
foreach(lc,namelist)
31093113
{
31103114
char*curname= (char*)lfirst(lc);

‎src/backend/utils/adt/varlena.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,7 +2753,7 @@ SplitIdentifierString(char *rawstring, char separator,
27532753
nextp++;/* skip leading whitespace */
27542754

27552755
if (*nextp=='\0')
2756-
return true;/*allowempty string */
2756+
return true;/* empty string represents empty list */
27572757

27582758
/* At the top of the loop, we are at start of a new identifier. */
27592759
do
@@ -2880,7 +2880,7 @@ SplitDirectoriesString(char *rawstring, char separator,
28802880
nextp++;/* skip leading whitespace */
28812881

28822882
if (*nextp=='\0')
2883-
return true;/*allowempty string */
2883+
return true;/* empty string represents empty list */
28842884

28852885
/* At the top of the loop, we are at start of a new directory. */
28862886
do
@@ -3001,7 +3001,7 @@ SplitGUCList(char *rawstring, char separator,
30013001
nextp++;/* skip leading whitespace */
30023002

30033003
if (*nextp=='\0')
3004-
return true;/*allowempty string */
3004+
return true;/* empty string represents empty list */
30053005

30063006
/* At the top of the loop, we are at start of a new identifier. */
30073007
do

‎src/backend/utils/misc/guc_funcs.c‎

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,29 @@ flatten_set_variable_args(const char *name, List *args)
210210
else
211211
flags=0;
212212

213-
/* Complain if list input and non-list variable */
214-
if ((flags&GUC_LIST_INPUT)==0&&
215-
list_length(args)!=1)
216-
ereport(ERROR,
217-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
218-
errmsg("SET %s takes only one argument",name)));
213+
/*
214+
* Handle special cases for list input.
215+
*/
216+
if (flags&GUC_LIST_INPUT)
217+
{
218+
/* NULL represents an empty list. */
219+
if (list_length(args)==1)
220+
{
221+
Node*arg= (Node*)linitial(args);
222+
223+
if (IsA(arg,A_Const)&&
224+
((A_Const*)arg)->isnull)
225+
returnpstrdup("");
226+
}
227+
}
228+
else
229+
{
230+
/* Complain if list input and non-list variable. */
231+
if (list_length(args)!=1)
232+
ereport(ERROR,
233+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
234+
errmsg("SET %s takes only one argument",name)));
235+
}
219236

220237
initStringInfo(&buf);
221238

@@ -246,6 +263,12 @@ flatten_set_variable_args(const char *name, List *args)
246263
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(arg));
247264
con= (A_Const*)arg;
248265

266+
/* Complain if NULL is used with a non-list variable. */
267+
if (con->isnull)
268+
ereport(ERROR,
269+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
270+
errmsg("NULL is an invalid value for %s",name)));
271+
249272
switch (nodeTag(&con->val))
250273
{
251274
caseT_Integer:
@@ -269,6 +292,9 @@ flatten_set_variable_args(const char *name, List *args)
269292
Datuminterval;
270293
char*intervalout;
271294

295+
/* gram.y ensures this is only reachable for TIME ZONE */
296+
Assert(!(flags&GUC_LIST_QUOTE));
297+
272298
typenameTypeIdAndMod(NULL,typeName,&typoid,&typmod);
273299
Assert(typoid==INTERVALOID);
274300

‎src/bin/pg_dump/dumputils.c‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ SplitGUCList(char *rawstring, char separator,
781781
nextp++;/* skip leading whitespace */
782782

783783
if (*nextp=='\0')
784-
return true;/*allowempty string */
784+
return true;/* empty string represents empty list */
785785

786786
/* At the top of the loop, we are at start of a new identifier. */
787787
do
@@ -893,6 +893,7 @@ makeAlterConfigCommand(PGconn *conn, const char *configitem,
893893
* elements as string literals. (The elements may be double-quoted as-is,
894894
* but we can't just feed them to the SQL parser; it would do the wrong
895895
* thing with elements that are zero-length or longer than NAMEDATALEN.)
896+
* Also, we need a special case for empty lists.
896897
*
897898
* Variables that are not so marked should just be emitted as simple
898899
* string literals. If the variable is not known to
@@ -908,6 +909,9 @@ makeAlterConfigCommand(PGconn *conn, const char *configitem,
908909
/* this shouldn't fail really */
909910
if (SplitGUCList(pos,',',&namelist))
910911
{
912+
/* Special case: represent an empty list as NULL */
913+
if (*namelist==NULL)
914+
appendPQExpBufferStr(buf,"NULL");
911915
for (nameptr=namelist;*nameptr;nameptr++)
912916
{
913917
if (nameptr!=namelist)

‎src/bin/pg_dump/pg_dump.c‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13764,7 +13764,8 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
1376413764
* and then quote the elements as string literals. (The elements may
1376513765
* be double-quoted as-is, but we can't just feed them to the SQL
1376613766
* parser; it would do the wrong thing with elements that are
13767-
* zero-length or longer than NAMEDATALEN.)
13767+
* zero-length or longer than NAMEDATALEN.) Also, we need a special
13768+
* case for empty lists.
1376813769
*
1376913770
* Variables that are not so marked should just be emitted as simple
1377013771
* string literals. If the variable is not known to
@@ -13780,6 +13781,9 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
1378013781
/* this shouldn't fail really */
1378113782
if (SplitGUCList(pos, ',', &namelist))
1378213783
{
13784+
/* Special case: represent an empty list as NULL */
13785+
if (*namelist == NULL)
13786+
appendPQExpBufferStr(q, "NULL");
1378313787
for (nameptr = namelist; *nameptr; nameptr++)
1378413788
{
1378513789
if (nameptr != namelist)

‎src/test/regress/expected/guc.out‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,28 @@ SELECT '2006-08-13 12:34:56'::timestamptz;
3131
2006-08-13 12:34:56-07
3232
(1 row)
3333

34+
-- Check handling of list GUCs
35+
SET search_path = 'pg_catalog', Foo, 'Bar', '';
36+
SHOW search_path;
37+
search_path
38+
----------------------------
39+
pg_catalog, foo, "Bar", ""
40+
(1 row)
41+
42+
SET search_path = null; -- means empty list
43+
SHOW search_path;
44+
search_path
45+
-------------
46+
47+
(1 row)
48+
49+
SET search_path = null, null; -- syntax error
50+
ERROR: syntax error at or near ","
51+
LINE 1: SET search_path = null, null;
52+
^
53+
SET enable_seqscan = null; -- error
54+
ERROR: NULL is an invalid value for enable_seqscan
55+
RESET search_path;
3456
-- SET LOCAL has no effect outside of a transaction
3557
SET LOCAL vacuum_cost_delay TO 50;
3658
WARNING: SET LOCAL can only be used in transaction blocks

‎src/test/regress/expected/rules.out‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3572,6 +3572,7 @@ CREATE FUNCTION func_with_set_params() RETURNS integer
35723572
SET extra_float_digits TO 2
35733573
SET work_mem TO '4MB'
35743574
SET datestyle to iso, mdy
3575+
SET temp_tablespaces to NULL
35753576
SET local_preload_libraries TO "Mixed/Case", 'c:/''a"/path', '', '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
35763577
IMMUTABLE STRICT;
35773578
SELECT pg_get_functiondef('func_with_set_params()'::regprocedure);
@@ -3585,6 +3586,7 @@ SELECT pg_get_functiondef('func_with_set_params()'::regprocedure);
35853586
SET extra_float_digits TO '2' +
35863587
SET work_mem TO '4MB' +
35873588
SET "DateStyle" TO 'iso, mdy' +
3589+
SET temp_tablespaces TO NULL +
35883590
SET local_preload_libraries TO 'Mixed/Case', 'c:/''a"/path', '', '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'+
35893591
AS $function$select 1;$function$ +
35903592

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp