diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index 5d2e3b0487..91d4b56e89 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.39 2006/08/11 20:08:28 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.40 2006/08/11 20:15:16 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,58 @@ 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; + /* set correctly source */ + 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 falls back 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 8770fbca70..42de724514 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.334 2006/08/11 20:08:28 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.335 2006/08/11 20:15:16 momjian Exp $ * *-------------------------------------------------------------------- */ @@ -2694,39 +2694,39 @@ InitializeGUCOptions(void) struct config_bool *conf = (struct config_bool *) gconf; if (conf->assign_hook) - if (!(*conf->assign_hook) (conf->reset_val, true, + if (!(*conf->assign_hook) (conf->boot_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; + 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); + Assert(conf->boot_val >= conf->min); + Assert(conf->boot_val <= conf->max); if (conf->assign_hook) - if (!(*conf->assign_hook) (conf->reset_val, true, + if (!(*conf->assign_hook) (conf->boot_val, true, PGC_S_DEFAULT)) elog(FATAL, "failed to initialize %s to %d", - conf->gen.name, conf->reset_val); - *conf->variable = conf->reset_val; + 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); + Assert(conf->boot_val >= conf->min); + Assert(conf->boot_val <= conf->max); if (conf->assign_hook) - if (!(*conf->assign_hook) (conf->reset_val, true, + if (!(*conf->assign_hook) (conf->boot_val, true, PGC_S_DEFAULT)) elog(FATAL, "failed to initialize %s to %g", - conf->gen.name, conf->reset_val); - *conf->variable = conf->reset_val; + conf->gen.name, conf->boot_val); + *conf->variable = conf->reset_val = conf->boot_val; break; } case PGC_STRING: @@ -3179,7 +3179,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; @@ -3726,8 +3726,19 @@ 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) @@ -3770,8 +3781,19 @@ 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) @@ -3814,8 +3836,19 @@ 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) @@ -3849,6 +3882,20 @@ 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) { /* @@ -4053,6 +4100,11 @@ verify_config_option(const char *name, const char *value, if( parse_value(elevel, record, value, &source, false, &newval) ) { + /* 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) @@ -4115,7 +4167,7 @@ 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 ecb49cb22a..524cb82989 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.24 2006/07/27 08:30:41 petere Exp $ + * $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.25 2006/08/11 20:15:16 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