1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Reverted waiting for further fixes:

Make configuration parameters fall back to their default values when they
are removed from the configuration file.

Joachim Wieland
This commit is contained in:
Peter Eisentraut
2007-03-13 14:32:25 +00:00
parent f32515df77
commit f4ee82e3d3
4 changed files with 40 additions and 441 deletions

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.381 2007/03/13 09:11:05 mha Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.382 2007/03/13 14:32:25 petere Exp $
*
*--------------------------------------------------------------------
*/
@ -2439,8 +2439,7 @@ set_string_field(struct config_string * conf, char **field, char *newval)
if (oldval == NULL ||
oldval == *(conf->variable) ||
oldval == conf->reset_val ||
oldval == conf->tentative_val ||
oldval == conf->boot_val)
oldval == conf->tentative_val)
return;
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
@ -2463,8 +2462,7 @@ string_field_used(struct config_string * conf, char *strval)
if (strval == *(conf->variable) ||
strval == conf->reset_val ||
strval == conf->tentative_val ||
strval == conf->boot_val)
strval == conf->tentative_val)
return true;
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
@ -2633,105 +2631,6 @@ add_guc_variable(struct config_generic * var, int elevel)
return true;
}
static int
guc_get_index(const char *name)
{
int i;
for (i = 0; i < num_guc_variables; i++)
if (pg_strcasecmp(name, guc_variables[i]->name) == 0)
return i;
return -1;
}
static void
guc_delete_variable(const char *name)
{
struct config_generic *gen;
int idx;
GucStack *stack, *prev;
struct config_string *conf;
idx = guc_get_index(name);
Assert(idx >= 0);
gen = guc_variables[idx];
/*
* Even though this function could delete other types of variables as well,
* at the moment we only call it for custom variables that always have type
* string.
*/
Assert(gen->group == CUSTOM_OPTIONS);
Assert(gen->vartype == PGC_STRING);
conf = (struct config_string *) gen;
set_string_field(conf, &conf->reset_val, NULL);
set_string_field(conf, &conf->tentative_val, NULL);
for (stack = conf->gen.stack; stack; stack = prev)
{
set_string_field(conf, &stack->tentative_val.stringval, NULL);
set_string_field(conf, &stack->value.stringval, NULL);
prev = stack->prev;
pfree(stack);
}
/* no pfree() here, gen has been allocated via guc_malloc */
free(gen);
guc_variables[idx] = guc_variables[num_guc_variables - 1];
num_guc_variables--;
qsort((void *) guc_variables, num_guc_variables,
sizeof(struct config_generic *), guc_var_compare);
}
static void
guc_delete_custom_variable(const char *name)
{
struct config_generic *gen;
struct config_string *conf;
int idx;
idx = guc_get_index(name);
Assert(idx >= 0);
gen = guc_variables[idx];
Assert(gen->group == CUSTOM_OPTIONS);
Assert(gen->vartype == PGC_STRING);
conf = (struct config_string *) gen;
/*
* Here we check whether it is safe to really delete the variable
* or if we have to wait for the end of the transaction. We do
* not remove the physical entry of a custom variable if it has
* been SET to another value in the transaction but has been
* removed from the configuration file.
*/
if (gen->stack)
{
/*
* Make sure this custom variable (which has a definition in
* the configuration file) behaves as any other custom
* variable from now on. We have deleted its former
* definition; that's why "RESET foo.bar" should not fall back
* to this deleted definition from the configuration file.
* The analogy is that any other custom variable that gets
* introduced in a session has no reset value either. And a
* variable that has been SET within a transaction and has
* then been deleted from the configuration file should behave
* as if it had been introduced in the session.
*/
Assert(gen->vartype == PGC_STRING);
gen->reset_source = PGC_S_DEFAULT;
set_string_field(conf, &conf->reset_val, NULL);
}
else
guc_delete_variable(name);
}
/*
* Create and add a placeholder variable. It's presumed to belong
* to a valid custom variable class at this point.
@ -2910,39 +2809,39 @@ InitializeGUCOptions(void)
struct config_bool *conf = (struct config_bool *) gconf;
if (conf->assign_hook)
if (!(*conf->assign_hook) (conf->boot_val, true,
if (!(*conf->assign_hook) (conf->reset_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;
conf->gen.name, (int) conf->reset_val);
*conf->variable = conf->reset_val;
break;
}
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
Assert(conf->boot_val >= conf->min);
Assert(conf->boot_val <= conf->max);
Assert(conf->reset_val >= conf->min);
Assert(conf->reset_val <= conf->max);
if (conf->assign_hook)
if (!(*conf->assign_hook) (conf->boot_val, true,
if (!(*conf->assign_hook) (conf->reset_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;
conf->gen.name, conf->reset_val);
*conf->variable = conf->reset_val;
break;
}
case PGC_REAL:
{
struct config_real *conf = (struct config_real *) gconf;
Assert(conf->boot_val >= conf->min);
Assert(conf->boot_val <= conf->max);
Assert(conf->reset_val >= conf->min);
Assert(conf->reset_val <= conf->max);
if (conf->assign_hook)
if (!(*conf->assign_hook) (conf->boot_val, true,
if (!(*conf->assign_hook) (conf->reset_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;
conf->gen.name, conf->reset_val);
*conf->variable = conf->reset_val;
break;
}
case PGC_STRING:
@ -3397,25 +3296,8 @@ push_old_value(struct config_generic * gconf)
}
}
/*------
/*
* Do GUC processing at transaction or subtransaction commit or abort.
*
* GUC can abort the transaction in exactly one case, namely when you
* delete a custom variable class while a still-open transaction has
* SET a custom variable within this class.
*
* Consider the following example. In the configuration file we could
* have:
*
* custom_variable_classes = "foo"
*
* begin;
* set foo.bar to 1;
* <delete foo.bar from configuration file and send SIGHUP>
* commit;
*
* This will result in an error because foo.bar is no longer available
* but commit would have to guarantee that the value is preserved.
*/
void
AtEOXact_GUC(bool isCommit, bool isSubXact)
@ -3453,33 +3335,6 @@ AtEOXact_GUC(bool isCommit, bool isSubXact)
continue;
Assert(stack->nest_level == my_level);
if (!isSubXact && gconf->group == CUSTOM_OPTIONS)
{
char *dot = strchr(gconf->name, GUC_QUALIFIER_SEPARATOR);
Assert(dot != NULL);
if (!is_custom_class(gconf->name, dot - gconf->name))
{
if (!isCommit)
{
/* We do not commit the transaction. Delete the variable. */
guc_delete_variable(gconf->name);
/* Call the loop with the same i again, which is
* the next variable. */
i--;
continue;
}
else
{
/* We commit the transaction. Throw an error that
* the respective custom class does not exist. */
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("no valid custom variable class available for "
"parameter \"%s\"", gconf->name)));
}
}
}
/*
* We will pop the stack entry. Start by restoring outer xact status
* (since we may want to modify it below). Be careful to use
@ -4143,26 +3998,19 @@ set_config_option(const char *name, const char *value,
}
/*
* Should we set reset/stacked values? (If so, the behavior is not
* transactional.) This is done either when we get a default
* value from the database's/user's/client's default settings or
* when we reset a value to its default.
* Should we set reset/stacked values? (If so, the behavior is not
* transactional.)
*/
makeDefault = changeVal && (source <= PGC_S_OVERRIDE)
&& ((value != NULL) || source == PGC_S_DEFAULT);
makeDefault = changeVal && (source <= PGC_S_OVERRIDE) && (value != NULL);
/*
* Ignore attempted set if overridden by previously processed
* setting. However, if changeVal is false then plow ahead anyway
* since we are trying to find out if the value is potentially
* good, not actually use it. Also keep going if makeDefault is
* true, since we may want to set the reset/stacked values even if
* we can't set the variable itself. There's one exception to
* this rule: if we want to apply the default value to variables
* that were removed from the configuration file. This is
* indicated by source == PGC_S_DEFAULT.
* Ignore attempted set if overridden by previously processed setting.
* However, if changeVal is false then plow ahead anyway since we are
* trying to find out if the value is potentially good, not actually use
* it. Also keep going if makeDefault is true, since we may want to set
* the reset/stacked values even if we can't set the variable itself.
*/
if (record->source > source && source != PGC_S_DEFAULT)
if (record->source > source)
{
if (changeVal && !makeDefault)
{
@ -4194,14 +4042,6 @@ set_config_option(const char *name, const char *value,
return false;
}
}
/*
* If value == NULL and source == PGC_S_DEFAULT then
* we reset some value to its default (removed from
* configuration file).
*/
else if (source == PGC_S_DEFAULT)
newval = conf->boot_val;
/* else we handle a "RESET varname" command */
else
{
newval = conf->reset_val;
@ -4286,14 +4126,6 @@ set_config_option(const char *name, const char *value,
return false;
}
}
/*
* If value == NULL and source == PGC_S_DEFAULT then
* we reset some value to its default (removed from
* configuration file).
*/
else if (source == PGC_S_DEFAULT)
newval = conf->boot_val;
/* else we handle a "RESET varname" command */
else
{
newval = conf->reset_val;
@ -4378,14 +4210,6 @@ set_config_option(const char *name, const char *value,
return false;
}
}
/*
* If value == NULL and source == PGC_S_DEFAULT then
* we reset some value to its default (removed from
* configuration file).
*/
else if (source == PGC_S_DEFAULT)
newval = conf->boot_val;
/* else we handle a "RESET varname" command */
else
{
newval = conf->reset_val;
@ -4464,23 +4288,6 @@ set_config_option(const char *name, const char *value,
if (conf->gen.flags & GUC_IS_NAME)
truncate_identifier(newval, strlen(newval), true);
}
/*
* If value == NULL and source == PGC_S_DEFAULT then
* we reset some value to its default (removed from
* configuration file).
*/
else if (source == PGC_S_DEFAULT)
{
if (conf->boot_val == NULL)
newval = NULL;
else
{
newval = guc_strdup(elevel, conf->boot_val);
if (newval == NULL)
return false;
}
}
/* else we handle a "RESET varname" command */
else if (conf->reset_val)
{
/*
@ -6497,13 +6304,6 @@ assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
int c;
StringInfoData buf;
/*
* Resetting custom_variable_classes by removing it from the
* configuration file will lead to newval = NULL
*/
if (newval == NULL)
return guc_strdup(ERROR, "");
initStringInfo(&buf);
while ((c = *cp++) != 0)
{
@ -6548,7 +6348,7 @@ assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
if (buf.len == 0)
newval = NULL;
else if (doit)
newval = guc_strdup(ERROR, buf.data);
newval = strdup(buf.data);
pfree(buf.data);
return newval;