From 9d522cb35d8b4f266abadd0d019f68eb8802ae05 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Fri, 8 Jul 2011 17:02:58 -0400 Subject: [PATCH] Fix another oversight in logging of changes in postgresql.conf settings. We were using GetConfigOption to collect the old value of each setting, overlooking the possibility that it didn't exist yet. This does happen in the case of adding a new entry within a custom variable class, as exhibited in bug #6097 from Maxim Boguk. To fix, add a missing_ok parameter to GetConfigOption, but only in 9.1 and HEAD --- it seems possible that some third-party code is using that function, so changing its API in a minor release would cause problems. In 9.0, create a near-duplicate function instead. --- src/backend/commands/extension.c | 6 +++--- src/backend/utils/misc/guc-file.l | 6 +++--- src/backend/utils/misc/guc.c | 16 ++++++++++++---- src/include/utils/guc.h | 3 ++- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index a0385eb0a18..9b9bb7dc8f0 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -814,14 +814,14 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, * error. */ save_client_min_messages = - pstrdup(GetConfigOption("client_min_messages", false)); + pstrdup(GetConfigOption("client_min_messages", false, false)); if (client_min_messages < WARNING) (void) set_config_option("client_min_messages", "warning", PGC_USERSET, PGC_S_SESSION, GUC_ACTION_LOCAL, true); save_log_min_messages = - pstrdup(GetConfigOption("log_min_messages", false)); + pstrdup(GetConfigOption("log_min_messages", false, false)); if (log_min_messages < WARNING) (void) set_config_option("log_min_messages", "warning", PGC_SUSET, PGC_S_SESSION, @@ -836,7 +836,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, * but we cannot do that. We have to actually set the search_path GUC in * case the extension script examines or changes it. */ - save_search_path = pstrdup(GetConfigOption("search_path", false)); + save_search_path = pstrdup(GetConfigOption("search_path", false, false)); initStringInfo(&pathbuf); appendStringInfoString(&pathbuf, quote_identifier(schemaName)); diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index 78907b939de..3e9b10328d4 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -306,9 +306,9 @@ ProcessConfigFile(GucContext context) /* In SIGHUP cases in the postmaster, report changes */ if (context == PGC_SIGHUP && !IsUnderPostmaster) { - const char *preval = GetConfigOption(item->name, false); + const char *preval = GetConfigOption(item->name, true, false); - /* string variables could be NULL; treat that as empty */ + /* If option doesn't exist yet or is NULL, treat as empty string */ if (!preval) preval = ""; /* must dup, else might have dangling pointer below */ @@ -323,7 +323,7 @@ ProcessConfigFile(GucContext context) if (pre_value) { - const char *post_value = GetConfigOption(item->name, false); + const char *post_value = GetConfigOption(item->name, true, false); if (!post_value) post_value = ""; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 5a0e94f8014..5841631e8c3 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5828,8 +5828,11 @@ SetConfigOption(const char *name, const char *value, /* - * Fetch the current value of the option `name'. If the option doesn't exist, - * throw an ereport and don't return. + * Fetch the current value of the option `name', as a string. + * + * If the option doesn't exist, return NULL if missing_ok is true (NOTE that + * this cannot be distinguished from a string variable with a NULL value!), + * otherwise throw an ereport and don't return. * * If restrict_superuser is true, we also enforce that only superusers can * see GUC_SUPERUSER_ONLY variables. This should only be passed as true @@ -5839,16 +5842,21 @@ SetConfigOption(const char *name, const char *value, * valid until the next call to configuration related functions. */ const char * -GetConfigOption(const char *name, bool restrict_superuser) +GetConfigOption(const char *name, bool missing_ok, bool restrict_superuser) { struct config_generic *record; static char buffer[256]; record = find_option(name, false, ERROR); if (record == NULL) + { + if (missing_ok) + return NULL; ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("unrecognized configuration parameter \"%s\"", name))); + errmsg("unrecognized configuration parameter \"%s\"", + name))); + } if (restrict_superuser && (record->flags & GUC_SUPERUSER_ONLY) && !superuser()) diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index ee52cd735e3..011f6b7f001 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -296,7 +296,8 @@ extern void DefineCustomEnumVariable( extern void EmitWarningsOnPlaceholders(const char *className); -extern const char *GetConfigOption(const char *name, bool restrict_superuser); +extern const char *GetConfigOption(const char *name, bool missing_ok, + bool restrict_superuser); extern const char *GetConfigOptionResetString(const char *name); extern void ProcessConfigFile(GucContext context); extern void InitializeGUCOptions(void); -- GitLab