Skip to content

Commit 75d2206

Browse files
committed
Warning on SET of nonexisting setting with a prefix reserved by an extension
An extension can already de facto reserve a GUC prefix using EmitWarningsOnPlaceholders(). But this was only checked against settings that exist at the time the extension is loaded (or the extension chooses to call this). No diagnostic is given when a SET command later uses a nonexisting setting with a custom prefix. With this change, EmitWarningsOnPlaceholders() saves the prefixes it reserves in a list, and SET checks when it finds a "placeholder" setting whether it belongs to a reserved prefix and issues a warning in that case. Add a regression test that checks the patch using the "plpgsql" registered prefix. Author: Florin Irion <florin.irion@enterprisedb.com> Discussion: https://www.postgresql.org/message-id/flat/CA+HEvJDhWuuTpGTJT9Tgbdzm4QS4EzPAwDBScWK18H2Q=FVJFw@mail.gmail.com
1 parent c3b34a0 commit 75d2206

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

src/backend/utils/misc/guc.c

+47
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ static bool check_recovery_target_lsn(char **newval, void **extra, GucSource sou
235235
static void assign_recovery_target_lsn(const char *newval, void *extra);
236236
static bool check_primary_slot_name(char **newval, void **extra, GucSource source);
237237
static bool check_default_with_oids(bool *newval, void **extra, GucSource source);
238+
static void check_reserved_prefixes(const char *varName);
239+
static List *reserved_class_prefix = NIL;
238240

239241
/* Private functions in guc-file.l that need to be called from guc.c */
240242
static ConfigVariable *ProcessConfigFileInternal(GucContext context,
@@ -8755,6 +8757,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
87558757
(superuser() ? PGC_SUSET : PGC_USERSET),
87568758
PGC_S_SESSION,
87578759
action, true, 0, false);
8760+
check_reserved_prefixes(stmt->name);
87588761
break;
87598762
case VAR_SET_MULTI:
87608763

@@ -8840,6 +8843,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
88408843
(superuser() ? PGC_SUSET : PGC_USERSET),
88418844
PGC_S_SESSION,
88428845
action, true, 0, false);
8846+
8847+
check_reserved_prefixes(stmt->name);
88438848
break;
88448849
case VAR_RESET_ALL:
88458850
ResetAllOptions();
@@ -9326,6 +9331,7 @@ EmitWarningsOnPlaceholders(const char *className)
93269331
{
93279332
int classLen = strlen(className);
93289333
int i;
9334+
MemoryContext oldcontext;
93299335

93309336
for (i = 0; i < num_guc_variables; i++)
93319337
{
@@ -9341,8 +9347,49 @@ EmitWarningsOnPlaceholders(const char *className)
93419347
var->name)));
93429348
}
93439349
}
9350+
9351+
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
9352+
reserved_class_prefix = lappend(reserved_class_prefix, pstrdup(className));
9353+
MemoryContextSwitchTo(oldcontext);
93449354
}
93459355

9356+
/*
9357+
* Check a setting name against prefixes previously reserved by
9358+
* EmitWarningsOnPlaceholders() and throw a warning if matching.
9359+
*/
9360+
static void
9361+
check_reserved_prefixes(const char *varName)
9362+
{
9363+
char *sep = strchr(varName, GUC_QUALIFIER_SEPARATOR);
9364+
9365+
if (sep)
9366+
{
9367+
size_t classLen = sep - varName;
9368+
ListCell *lc;
9369+
9370+
foreach(lc, reserved_class_prefix)
9371+
{
9372+
char *rcprefix = lfirst(lc);
9373+
9374+
if (strncmp(varName, rcprefix, classLen) == 0)
9375+
{
9376+
for (int i = 0; i < num_guc_variables; i++)
9377+
{
9378+
struct config_generic *var = guc_variables[i];
9379+
9380+
if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
9381+
strcmp(varName, var->name) == 0)
9382+
{
9383+
ereport(WARNING,
9384+
(errcode(ERRCODE_UNDEFINED_OBJECT),
9385+
errmsg("unrecognized configuration parameter \"%s\"", var->name),
9386+
errdetail("\"%.*s\" is a reserved prefix.", (int) classLen, var->name)));
9387+
}
9388+
}
9389+
}
9390+
}
9391+
}
9392+
}
93469393

93479394
/*
93489395
* SHOW command

src/test/regress/expected/guc.out

+19
Original file line numberDiff line numberDiff line change
@@ -813,3 +813,22 @@ set default_with_oids to f;
813813
-- Should not allow to set it to true.
814814
set default_with_oids to t;
815815
ERROR: tables declared WITH OIDS are not supported
816+
-- test SET unrecognized parameter
817+
SET foo = false; -- no such setting
818+
ERROR: unrecognized configuration parameter "foo"
819+
-- test setting a parameter with a registered prefix (plpgsql)
820+
SET plpgsql.extra_foo_warnings = false; -- no such setting
821+
WARNING: unrecognized configuration parameter "plpgsql.extra_foo_warnings"
822+
DETAIL: "plpgsql" is a reserved prefix.
823+
SHOW plpgsql.extra_foo_warnings; -- but the parameter is set
824+
plpgsql.extra_foo_warnings
825+
----------------------------
826+
false
827+
(1 row)
828+
829+
-- cleanup
830+
RESET foo;
831+
ERROR: unrecognized configuration parameter "foo"
832+
RESET plpgsql.extra_foo_warnings;
833+
WARNING: unrecognized configuration parameter "plpgsql.extra_foo_warnings"
834+
DETAIL: "plpgsql" is a reserved prefix.

src/test/regress/sql/guc.sql

+11
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,14 @@ reset check_function_bodies;
311311
set default_with_oids to f;
312312
-- Should not allow to set it to true.
313313
set default_with_oids to t;
314+
315+
-- test SET unrecognized parameter
316+
SET foo = false; -- no such setting
317+
318+
-- test setting a parameter with a registered prefix (plpgsql)
319+
SET plpgsql.extra_foo_warnings = false; -- no such setting
320+
SHOW plpgsql.extra_foo_warnings; -- but the parameter is set
321+
322+
-- cleanup
323+
RESET foo;
324+
RESET plpgsql.extra_foo_warnings;

0 commit comments

Comments
 (0)