From f09fb71af96f92491cbfc2e65ef27311cff9af51 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sun, 13 Aug 2006 02:22:24 +0000 Subject: [PATCH] Recommit patch to allow commented GUC variables to return to their default values. --- src/backend/utils/misc/guc-file.l | 56 ++++++++++++- src/backend/utils/misc/guc.c | 132 ++++++++++++++++++++---------- src/include/utils/guc_tables.h | 14 ++-- 3 files changed, 151 insertions(+), 51 deletions(-) diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index 64f9304de56..a0044abc860 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -4,7 +4,7 @@ * * Copyright (c) 2000-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.43 2006/08/13 01:30:17 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.44 2006/08/13 02:22:24 momjian Exp $ */ %{ @@ -117,6 +117,7 @@ ProcessConfigFile(GucContext context) { int elevel, i; struct name_value_pair *item, *head, *tail; + char *env; bool *apply_list = NULL; int varcount = 0; @@ -183,6 +184,59 @@ ProcessConfigFile(GucContext context) set_config_option(item->name, item->value, context, PGC_S_FILE, false, true); + if (context == PGC_SIGHUP) + { + /* + * Revert all "untouched" options with reset source PGC_S_FILE to + * default/boot value. + */ + for (i = 0; i < num_guc_variables; i++) + { + struct config_generic *gconf = guc_variables[i]; + + if (gconf->reset_source == PGC_S_FILE && + !(gconf->status & GUC_IN_CONFFILE)) + { + if (gconf->context == PGC_BACKEND && IsUnderPostmaster) + ; /* Be silent. Does any body want message from each session? */ + else if (gconf->context == PGC_POSTMASTER) + ereport(elevel, + (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), + errmsg("parameter \"%s\" cannot be changed (commented) after server start; configuration file change ignored", + gconf->name))); + else if (set_config_option(gconf->name, NULL, context, + PGC_S_FILE, false, true)) + { + GucStack *stack; + + gconf->reset_source = PGC_S_DEFAULT; + + for (stack = gconf->stack; stack; stack = stack->prev) + if (stack->source == PGC_S_FILE) + stack->source = PGC_S_DEFAULT; + + ereport(elevel, + (errcode(ERRCODE_SUCCESSFUL_COMPLETION), + errmsg("configuration option %s returned to default value", gconf->name))); + } + } + gconf->status &= ~GUC_IN_CONFFILE; + } + + /* + * Revert to environment variable. PGPORT is ignored, because it cannot be + * set in running state. + */ + env = getenv("PGDATESTYLE"); + if (env != NULL) + set_config_option("datestyle", env, context, + PGC_S_ENV_VAR, false, true); + + env = getenv("PGCLIENTENCODING"); + if (env != NULL) + set_config_option("client_encoding", env, context, + PGC_S_ENV_VAR, false, true); + } cleanup_list: if (apply_list) diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 11b1fe1e6cd..caa4fc67a59 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.338 2006/08/13 01:30:17 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.339 2006/08/13 02:22:24 momjian Exp $ * *-------------------------------------------------------------------- */ @@ -2692,40 +2692,40 @@ InitializeGUCOptions(void) { struct config_bool *conf = (struct config_bool *) gconf; - if (conf->assign_hook) - if (!(*conf->assign_hook) (conf->reset_val, true, - PGC_S_DEFAULT)) - elog(FATAL, "failed to initialize %s to %d", - conf->gen.name, (int) conf->reset_val); - *conf->variable = conf->reset_val; + if (conf->assign_hook && + !(*conf->assign_hook) (conf->boot_val, true, + PGC_S_DEFAULT)) + elog(FATAL, "failed to initialize %s to %d", + conf->gen.name, (int) conf->boot_val); + *conf->variable = conf->reset_val = conf->boot_val; break; } case PGC_INT: { struct config_int *conf = (struct config_int *) gconf; - Assert(conf->reset_val >= conf->min); - Assert(conf->reset_val <= conf->max); - if (conf->assign_hook) - if (!(*conf->assign_hook) (conf->reset_val, true, - PGC_S_DEFAULT)) - elog(FATAL, "failed to initialize %s to %d", - conf->gen.name, conf->reset_val); - *conf->variable = conf->reset_val; + Assert(conf->boot_val >= conf->min); + Assert(conf->boot_val <= conf->max); + if (conf->assign_hook && + !(*conf->assign_hook) (conf->boot_val, true, + PGC_S_DEFAULT)) + elog(FATAL, "failed to initialize %s to %d", + conf->gen.name, conf->boot_val); + *conf->variable = conf->reset_val = conf->boot_val; break; } case PGC_REAL: { struct config_real *conf = (struct config_real *) gconf; - Assert(conf->reset_val >= conf->min); - Assert(conf->reset_val <= conf->max); - if (conf->assign_hook) - if (!(*conf->assign_hook) (conf->reset_val, true, - PGC_S_DEFAULT)) - elog(FATAL, "failed to initialize %s to %g", - conf->gen.name, conf->reset_val); - *conf->variable = conf->reset_val; + Assert(conf->boot_val >= conf->min); + Assert(conf->boot_val <= conf->max); + if (conf->assign_hook && + !(*conf->assign_hook) (conf->boot_val, true, + PGC_S_DEFAULT)) + elog(FATAL, "failed to initialize %s to %g", + conf->gen.name, conf->boot_val); + *conf->variable = conf->reset_val = conf->boot_val; break; } case PGC_STRING: @@ -2738,10 +2738,8 @@ InitializeGUCOptions(void) conf->tentative_val = NULL; if (conf->boot_val == NULL) - { /* Cannot set value yet */ break; - } str = guc_strdup(FATAL, conf->boot_val); conf->reset_val = str; @@ -2753,10 +2751,8 @@ InitializeGUCOptions(void) newstr = (*conf->assign_hook) (str, true, PGC_S_DEFAULT); if (newstr == NULL) - { elog(FATAL, "failed to initialize %s to \"%s\"", conf->gen.name, str); - } else if (newstr != str) { free(str); @@ -2796,12 +2792,10 @@ InitializeGUCOptions(void) if (env != NULL) SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR); - env = getenv("PGDATESTYLE"); - if (env != NULL) + if ((env = getenv("PGDATESTYLE")) != NULL) SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR); - env = getenv("PGCLIENTENCODING"); - if (env != NULL) + if ((env = getenv("PGCLIENTENCODING")) != NULL) SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR); } @@ -3178,7 +3172,7 @@ AtEOXact_GUC(bool isCommit, bool isSubXact) for (i = 0; i < num_guc_variables; i++) { struct config_generic *gconf = guc_variables[i]; - int my_status = gconf->status; + int my_status = gconf->status & (~GUC_IN_CONFFILE); GucStack *stack = gconf->stack; bool useTentative; bool changed; @@ -3723,12 +3717,22 @@ parse_value(int elevel, const struct config_generic *record, } else { - newval = conf->reset_val; - *source = conf->gen.reset_source; + /* + * Revert value to default if source is configuration file. It is used when + * configuration parameter is removed/commented out in the config file. Else + * RESET or SET TO DEFAULT command is called and reset_val is used. + */ + if (*source == PGC_S_FILE) + newval = conf->boot_val; + else + { + newval = conf->reset_val; + *source = conf->gen.reset_source; + } } - if (conf->assign_hook) - if (!(*conf->assign_hook) (newval, changeVal, *source)) + if (conf->assign_hook && + !(*conf->assign_hook) (newval, changeVal, *source)) { ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -3767,8 +3771,18 @@ parse_value(int elevel, const struct config_generic *record, } else { - newval = conf->reset_val; - *source = conf->gen.reset_source; + /* + * Revert value to default if source is configuration file. It is used when + * configuration parameter is removed/commented out in the config file. Else + * RESET or SET TO DEFAULT command is called and reset_val is used. + */ + if (*source == PGC_S_FILE) + newval = conf->boot_val; + else + { + newval = conf->reset_val; + *source = conf->gen.reset_source; + } } if (conf->assign_hook) @@ -3811,12 +3825,22 @@ parse_value(int elevel, const struct config_generic *record, } else { - newval = conf->reset_val; - *source = conf->gen.reset_source; + /* + * Revert value to default if source is configuration file. It is used when + * configuration parameter is removed/commented out in the config file. Else + * RESET or SET TO DEFAULT command is called and reset_val is used. + */ + if (*source == PGC_S_FILE) + newval = conf->boot_val; + else + { + newval = conf->reset_val; + *source = conf->gen.reset_source; + } } - if (conf->assign_hook) - if (!(*conf->assign_hook) (newval, changeVal, *source)) + if (conf->assign_hook && + !(*conf->assign_hook) (newval, changeVal, *source)) { ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -3845,6 +3869,18 @@ parse_value(int elevel, const struct config_generic *record, if (conf->gen.flags & GUC_IS_NAME) truncate_identifier(newval, strlen(newval), true); } + else if (*source == PGC_S_FILE) + { + /* Revert value to default when item is removed from config file. */ + if (conf->boot_val != NULL) + { + newval = guc_strdup(elevel, conf->boot_val); + if (newval == NULL) + return false; + } + else + return false; + } else if (conf->reset_val) { /* @@ -3856,10 +3892,8 @@ parse_value(int elevel, const struct config_generic *record, *source = conf->gen.reset_source; } else - { /* Nothing to reset to, as yet; so do nothing */ break; - } if (conf->assign_hook) { @@ -4047,6 +4081,13 @@ verify_config_option(const char *name, const char *value, if (parse_value(elevel, record, value, &source, false, NULL)) { + /* + * Mark record like presented in the config file. Be carefull if + * you use this function for another purpose than config file + * verification. It causes confusion configfile parser. + */ + record->status |= GUC_IN_CONFFILE; + if (isNewEqual != NULL) *isNewEqual = is_newvalue_equal(record, value); if (isContextOK != NULL) @@ -4109,7 +4150,8 @@ set_config_option(const char *name, const char *value, * Should we set reset/stacked values? (If so, the behavior is not * transactional.) */ - makeDefault = changeVal && (source <= PGC_S_OVERRIDE) && (value != NULL); + makeDefault = changeVal && (source <= PGC_S_OVERRIDE) && + (value != NULL || source == PGC_S_FILE); /* * Ignore attempted set if overridden by previously processed setting. diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index 21b22eefa86..6345fb1abd7 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -7,7 +7,7 @@ * * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.26 2006/08/12 04:11:50 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.27 2006/08/13 02:22:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -143,7 +143,8 @@ struct config_generic #define GUC_HAVE_TENTATIVE 0x0001 /* tentative value is defined */ #define GUC_HAVE_LOCAL 0x0002 /* a SET LOCAL has been executed */ #define GUC_HAVE_STACK 0x0004 /* we have stacked prior value(s) */ - +#define GUC_IN_CONFFILE 0x0008 /* value shows up in the configuration + file (is not commented) */ /* GUC records for specific variable types */ @@ -153,11 +154,12 @@ struct config_bool /* these fields must be set correctly in initial value: */ /* (all but reset_val are constants) */ bool *variable; - bool reset_val; + bool boot_val; GucBoolAssignHook assign_hook; GucShowHook show_hook; /* variable fields, initialized at runtime: */ bool tentative_val; + bool reset_val; }; struct config_int @@ -166,13 +168,14 @@ struct config_int /* these fields must be set correctly in initial value: */ /* (all but reset_val are constants) */ int *variable; - int reset_val; + int boot_val; int min; int max; GucIntAssignHook assign_hook; GucShowHook show_hook; /* variable fields, initialized at runtime: */ int tentative_val; + int reset_val; }; struct config_real @@ -181,13 +184,14 @@ struct config_real /* these fields must be set correctly in initial value: */ /* (all but reset_val are constants) */ double *variable; - double reset_val; + double boot_val; double min; double max; GucRealAssignHook assign_hook; GucShowHook show_hook; /* variable fields, initialized at runtime: */ double tentative_val; + double reset_val; }; struct config_string