* See src/backend/utils/misc/README for more information.
*
*
- * Copyright (c) 2000-2007, PostgreSQL Global Development Group
+ * Copyright (c) 2000-2008, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.418 2007/09/10 01:39:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.436 2008/03/10 12:39:23 tgl Exp $
*
*--------------------------------------------------------------------
*/
extern int CommitSiblings;
extern char *default_tablespace;
extern char *temp_tablespaces;
+extern bool synchronize_seqscans;
extern bool fullPageWrites;
#ifdef TRACE_SORT
static const char *assign_defaultxactisolevel(const char *newval, bool doit,
GucSource source);
static const char *assign_session_replication_role(const char *newval, bool doit,
- GucSource source);
+ GucSource source);
static const char *assign_log_min_messages(const char *newval, bool doit,
GucSource source);
static const char *assign_client_min_messages(const char *newval,
static const char *assign_timezone_abbreviations(const char *newval, bool doit, GucSource source);
static const char *assign_xmlbinary(const char *newval, bool doit, GucSource source);
static const char *assign_xmloption(const char *newval, bool doit, GucSource source);
-
+static const char *show_archive_command(void);
static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_count(int newval, bool doit, GucSource source);
bool Password_encryption = true;
int log_min_error_statement = ERROR;
-int log_min_messages = NOTICE;
+int log_min_messages = WARNING;
int client_min_messages = NOTICE;
int log_min_duration_statement = -1;
int log_temp_files = -1;
* 4. Add a record below.
*
* 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
- * appropriate
+ * appropriate.
*
- * 6. Don't forget to document the option.
+ * 6. Don't forget to document the option (at least in config.sgml).
*
* 7. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure
* it is not single quoted at dump time.
NULL
},
&XactSyncCommit,
- /* XXX TEMPORARY FOR TESTING: sync commit should default to TRUE! */
- false, NULL, NULL
+ true, NULL, NULL
},
{
{"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
&Explain_pretty_print,
true, NULL, NULL
},
+
{
- {"stats_start_collector", PGC_POSTMASTER, STATS_COLLECTOR,
- gettext_noop("Starts the server statistics-collection subprocess."),
- NULL
+ {"track_activities", PGC_SUSET, STATS_COLLECTOR,
+ gettext_noop("Collects information about executing commands."),
+ gettext_noop("Enables the collection of information on the currently "
+ "executing command of each session, along with "
+ "the time at which that command began execution.")
},
- &pgstat_collect_startcollector,
+ &pgstat_track_activities,
true, NULL, NULL
},
{
- {"stats_reset_on_server_start", PGC_POSTMASTER, STATS_COLLECTOR,
- gettext_noop("Zeroes collected statistics on server restart."),
- NULL
- },
- &pgstat_collect_resetonpmstart,
- false, NULL, NULL
- },
- {
- {"stats_row_level", PGC_SUSET, STATS_COLLECTOR,
- gettext_noop("Collects row-level statistics on database activity."),
+ {"track_counts", PGC_SUSET, STATS_COLLECTOR,
+ gettext_noop("Collects statistics on database activity."),
NULL
},
- &pgstat_collect_tuplelevel,
- true, NULL, NULL
- },
- {
- {"stats_block_level", PGC_SUSET, STATS_COLLECTOR,
- gettext_noop("Collects block-level statistics on database activity."),
- NULL
- },
- &pgstat_collect_blocklevel,
- false, NULL, NULL
- },
-
- {
- {"stats_command_string", PGC_SUSET, STATS_COLLECTOR,
- gettext_noop("Collects information about executing commands."),
- gettext_noop("Enables the collection of information on the currently "
- "executing command of each session, along with the time "
- "at which that command began execution.")
- },
- &pgstat_collect_querystring,
+ &pgstat_track_counts,
true, NULL, NULL
},
false, NULL, NULL
},
+ {
+ {"synchronize_seqscans", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
+ gettext_noop("Enable synchronized sequential scans."),
+ NULL
+ },
+ &synchronize_seqscans,
+ true, NULL, NULL
+ },
+
+ {
+ {"archive_mode", PGC_POSTMASTER, WAL_SETTINGS,
+ gettext_noop("Allows archiving of WAL files using archive_command."),
+ NULL
+ },
+ &XLogArchiveMode,
+ false, NULL, NULL
+ },
+
{
{"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS,
gettext_noop("Allows modifications of the structure of system tables."),
GUC_UNIT_MS
},
&DeadlockTimeout,
- 1000, 1, INT_MAX/1000, NULL, NULL
+ 1000, 1, INT_MAX / 1000, NULL, NULL
},
/*
- * Note: There is some postprocessing done in PostmasterMain() to make
- * sure the buffers are at least twice the number of backends, so the
- * constraints here are partially unused. Similarly, the superuser
- * reserved number is checked to ensure it is less than the max backends
- * number.
- *
- * MaxBackends is limited to INT_MAX/4 because some places compute
- * 4*MaxBackends without any overflow check. This check is made on
- * assign_maxconnections, since MaxBackends is computed as MaxConnections +
- * autovacuum_max_workers.
+ * Note: MaxBackends is limited to INT_MAX/4 because some places compute
+ * 4*MaxBackends without any overflow check. This check is made in
+ * assign_maxconnections, since MaxBackends is computed as MaxConnections
+ * plus autovacuum_max_workers.
*
* Likewise we have to limit NBuffers to INT_MAX/2.
*/
{
{"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN,
- gettext_noop("Sets the minimum execution time above which statements will "
- "be logged."),
- gettext_noop("Zero prints all queries. The default is -1 (turning this feature off)."),
+ gettext_noop("Sets the minimum execution time above which "
+ "statements will be logged."),
+ gettext_noop("Zero prints all queries. -1 turns this feature off."),
GUC_UNIT_MS
},
&log_min_duration_statement,
},
{
- {"log_autovacuum", PGC_SIGHUP, LOGGING_WHAT,
- gettext_noop("Sets the minimum execution time above which autovacuum actions "
- "will be logged."),
- gettext_noop("Zero prints all actions. The default is -1 (disabling autovacuum logging)."),
+ {"log_autovacuum_min_duration", PGC_SIGHUP, LOGGING_WHAT,
+ gettext_noop("Sets the minimum execution time above which "
+ "autovacuum actions will be logged."),
+ gettext_noop("Zero prints all actions. -1 turns autovacuum logging off."),
GUC_UNIT_MS
},
- &Log_autovacuum,
+ &Log_autovacuum_min_duration,
-1, -1, INT_MAX / 1000, NULL, NULL
},
NULL
},
&bgwriter_lru_maxpages,
- 5, 0, 1000, NULL, NULL
+ 100, 0, 1000, NULL, NULL
},
{
},
{
- {"bgwriter_lru_percent", PGC_SIGHUP, RESOURCES,
- gettext_noop("Background writer percentage of LRU buffers to flush per round."),
+ {"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES,
+ gettext_noop("Multiple of the average buffer usage to free per round."),
NULL
},
- &bgwriter_lru_percent,
- 1.0, 0.0, 100.0, NULL, NULL
+ &bgwriter_lru_multiplier,
+ 2.0, 0.0, 10.0, NULL, NULL
},
{
GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&phony_random_seed,
- 0.5, 0.0, 1.0, assign_random_seed, show_random_seed
+ 0.0, -1.0, 1.0, assign_random_seed, show_random_seed
},
{
NULL
},
&XLogArchiveCommand,
- "", NULL, NULL
+ "", NULL, show_archive_command
},
{
"includes all the levels that follow it.")
},
&log_min_messages_str,
- "notice", assign_log_min_messages, NULL
+ "warning", assign_log_min_messages, NULL
},
{
{
{"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
- gettext_noop("Sets the sessions behavior for triggers and rewrite rules."),
+ gettext_noop("Sets the session's behavior for triggers and rewrite rules."),
gettext_noop("Each session can be either"
- " \"origin\", \"replica\" or \"local\".")
+ " \"origin\", \"replica\", or \"local\".")
},
&session_replication_role_string,
"origin", assign_session_replication_role, NULL
"$libdir", NULL, NULL
},
+ {
+ {"krb_realm", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+ gettext_noop("Sets realm to match Kerberos and GSSAPI users against."),
+ NULL,
+ GUC_SUPERUSER_ONLY
+ },
+ &pg_krb_realm,
+ NULL, NULL, NULL
+ },
+
{
{"krb_server_keyfile", PGC_POSTMASTER, CONN_AUTH_SECURITY,
gettext_noop("Sets the location of the Kerberos server key file."),
&SSLCipherSuites,
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH", NULL, NULL
},
-#endif /* USE_SSL */
+#endif /* USE_SSL */
/* End-of-list marker */
{
static int guc_var_compare(const void *a, const void *b);
static int guc_name_compare(const char *namea, const char *nameb);
-static void push_old_value(struct config_generic * gconf);
+static void push_old_value(struct config_generic * gconf, GucAction action);
static void ReportGUCOption(struct config_generic * record);
static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
static void ShowAllGUCConfig(DestReceiver *dest);
static char *_ShowOption(struct config_generic * record, bool use_units);
-static bool is_newvalue_equal(struct config_generic *record, const char *newvalue);
+static bool is_newvalue_equal(struct config_generic * record, const char *newvalue);
/*
if (oldval == NULL ||
oldval == *(conf->variable) ||
oldval == conf->reset_val ||
- oldval == conf->tentative_val ||
oldval == conf->boot_val)
return;
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
- if (oldval == stack->tentative_val.stringval ||
- oldval == stack->value.stringval)
+ if (oldval == stack->prior.stringval ||
+ oldval == stack->masked.stringval)
return;
}
if (strval == *(conf->variable) ||
strval == conf->reset_val ||
- strval == conf->tentative_val ||
strval == conf->boot_val)
return true;
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
- if (strval == stack->tentative_val.stringval ||
- strval == stack->value.stringval)
+ if (strval == stack->prior.stringval ||
+ strval == stack->masked.stringval)
return true;
}
return false;
}
+/*
+ * Support for copying a variable's active value into a stack entry
+ */
+static void
+set_stack_value(struct config_generic * gconf, union config_var_value * val)
+{
+ switch (gconf->vartype)
+ {
+ case PGC_BOOL:
+ val->boolval =
+ *((struct config_bool *) gconf)->variable;
+ break;
+ case PGC_INT:
+ val->intval =
+ *((struct config_int *) gconf)->variable;
+ break;
+ case PGC_REAL:
+ val->realval =
+ *((struct config_real *) gconf)->variable;
+ break;
+ case PGC_STRING:
+ /* we assume stringval is NULL if not valid */
+ set_string_field((struct config_string *) gconf,
+ &(val->stringval),
+ *((struct config_string *) gconf)->variable);
+ break;
+ }
+}
+/*
+ * Support for discarding a no-longer-needed value in a stack entry
+ */
+static void
+discard_stack_value(struct config_generic * gconf, union config_var_value * val)
+{
+ switch (gconf->vartype)
+ {
+ case PGC_BOOL:
+ case PGC_INT:
+ case PGC_REAL:
+ /* no need to do anything */
+ break;
+ case PGC_STRING:
+ set_string_field((struct config_string *) gconf,
+ &(val->stringval),
+ NULL);
+ break;
+ }
+}
+
+
+/*
+ * Fetch the sorted array pointer (exported for help_config.c's use ONLY)
+ */
struct config_generic **
get_guc_variables(void)
{
/*
* The char* is allocated at the end of the struct since we have no
- * 'static' place to point to. Note that the current value, as well
- * as the boot and reset values, start out NULL.
+ * 'static' place to point to. Note that the current value, as well as
+ * the boot and reset values, start out NULL.
*/
var->variable = (char **) (var + 1);
return guc_name_compare(confa->name, confb->name);
}
-
+/*
+ * the bare comparison function for GUC names
+ */
static int
guc_name_compare(const char *namea, const char *nameb)
{
long stack_rlimit;
/*
- * Before log_line_prefix could possibly receive a nonempty setting,
- * make sure that timezone processing is minimally alive (see elog.c).
+ * Before log_line_prefix could possibly receive a nonempty setting, make
+ * sure that timezone processing is minimally alive (see elog.c).
*/
pg_timezone_pre_initialize();
gconf->status = 0;
gconf->reset_source = PGC_S_DEFAULT;
- gconf->tentative_source = PGC_S_DEFAULT;
gconf->source = PGC_S_DEFAULT;
gconf->stack = NULL;
*conf->variable = NULL;
conf->reset_val = NULL;
- conf->tentative_val = NULL;
if (conf->boot_val == NULL)
{
/*
* For historical reasons, some GUC parameters can receive defaults from
- * environment variables. Process those settings. NB: if you add or
+ * environment variables. Process those settings. NB: if you add or
* remove anything here, see also ProcessConfigFile().
*/
stack_rlimit = get_stack_depth_rlimit();
if (stack_rlimit > 0)
{
- int new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;
+ int new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;
if (new_limit > 100)
{
- char limbuf[16];
+ char limbuf[16];
new_limit = Min(new_limit, 2048);
sprintf(limbuf, "%d", new_limit);
continue;
/* Save old value to support transaction abort */
- push_old_value(gconf);
+ push_old_value(gconf, GUC_ACTION_SET);
switch (gconf->vartype)
{
PGC_S_SESSION))
elog(ERROR, "failed to reset %s", conf->gen.name);
*conf->variable = conf->reset_val;
- conf->tentative_val = conf->reset_val;
conf->gen.source = conf->gen.reset_source;
- conf->gen.tentative_source = conf->gen.reset_source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- guc_dirty = true;
break;
}
case PGC_INT:
PGC_S_SESSION))
elog(ERROR, "failed to reset %s", conf->gen.name);
*conf->variable = conf->reset_val;
- conf->tentative_val = conf->reset_val;
conf->gen.source = conf->gen.reset_source;
- conf->gen.tentative_source = conf->gen.reset_source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- guc_dirty = true;
break;
}
case PGC_REAL:
PGC_S_SESSION))
elog(ERROR, "failed to reset %s", conf->gen.name);
*conf->variable = conf->reset_val;
- conf->tentative_val = conf->reset_val;
conf->gen.source = conf->gen.reset_source;
- conf->gen.tentative_source = conf->gen.reset_source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- guc_dirty = true;
break;
}
case PGC_STRING:
}
set_string_field(conf, conf->variable, str);
- set_string_field(conf, &conf->tentative_val, str);
conf->gen.source = conf->gen.reset_source;
- conf->gen.tentative_source = conf->gen.reset_source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- guc_dirty = true;
break;
}
}
/*
* push_old_value
- * Push previous state during first assignment to a GUC variable
- * within a particular transaction.
- *
- * We have to be willing to "back-fill" the state stack if the first
- * assignment occurs within a subtransaction nested several levels deep.
- * This ensures that if an intermediate transaction aborts, it will have
- * the proper value available to restore the setting to.
+ * Push previous state during transactional assignment to a GUC variable.
*/
static void
-push_old_value(struct config_generic * gconf)
+push_old_value(struct config_generic * gconf, GucAction action)
{
GucStack *stack;
- /* If we're not inside a transaction, do nothing */
+ /* If we're not inside a nest level, do nothing */
if (GUCNestLevel == 0)
return;
- for (;;)
+ /* Do we already have a stack entry of the current nest level? */
+ stack = gconf->stack;
+ if (stack && stack->nest_level >= GUCNestLevel)
{
- /* Done if we already pushed it at this nesting depth */
- if (gconf->stack && gconf->stack->nest_level >= GUCNestLevel)
- return;
-
- /*
- * We keep all the stack entries in TopTransactionContext so as to
- * avoid allocation problems when a subtransaction back-fills stack
- * entries for upper transaction levels.
- */
- stack = (GucStack *) MemoryContextAlloc(TopTransactionContext,
- sizeof(GucStack));
-
- stack->prev = gconf->stack;
- stack->nest_level = stack->prev ? stack->prev->nest_level + 1 : 1;
- stack->status = gconf->status;
- stack->tentative_source = gconf->tentative_source;
- stack->source = gconf->source;
-
- switch (gconf->vartype)
+ /* Yes, so adjust its state if necessary */
+ Assert(stack->nest_level == GUCNestLevel);
+ switch (action)
{
- case PGC_BOOL:
- stack->tentative_val.boolval =
- ((struct config_bool *) gconf)->tentative_val;
- stack->value.boolval =
- *((struct config_bool *) gconf)->variable;
- break;
-
- case PGC_INT:
- stack->tentative_val.intval =
- ((struct config_int *) gconf)->tentative_val;
- stack->value.intval =
- *((struct config_int *) gconf)->variable;
+ case GUC_ACTION_SET:
+ /* SET overrides any prior action at same nest level */
+ if (stack->state == GUC_SET_LOCAL)
+ {
+ /* must discard old masked value */
+ discard_stack_value(gconf, &stack->masked);
+ }
+ stack->state = GUC_SET;
break;
-
- case PGC_REAL:
- stack->tentative_val.realval =
- ((struct config_real *) gconf)->tentative_val;
- stack->value.realval =
- *((struct config_real *) gconf)->variable;
+ case GUC_ACTION_LOCAL:
+ if (stack->state == GUC_SET)
+ {
+ /* SET followed by SET LOCAL, remember SET's value */
+ set_stack_value(gconf, &stack->masked);
+ stack->state = GUC_SET_LOCAL;
+ }
+ /* in all other cases, no change to stack entry */
break;
-
- case PGC_STRING:
- stack->tentative_val.stringval =
- ((struct config_string *) gconf)->tentative_val;
- stack->value.stringval =
- *((struct config_string *) gconf)->variable;
+ case GUC_ACTION_SAVE:
+ /* Could only have a prior SAVE of same variable */
+ Assert(stack->state == GUC_SAVE);
break;
}
+ Assert(guc_dirty); /* must be set already */
+ return;
+ }
- gconf->stack = stack;
-
- /* Set state to indicate nothing happened yet within this level */
- gconf->status = GUC_HAVE_STACK;
+ /*
+ * Push a new stack entry
+ *
+ * We keep all the stack entries in TopTransactionContext for simplicity.
+ */
+ stack = (GucStack *) MemoryContextAllocZero(TopTransactionContext,
+ sizeof(GucStack));
- /* Ensure we remember to pop at end of xact */
- guc_dirty = true;
+ stack->prev = gconf->stack;
+ stack->nest_level = GUCNestLevel;
+ switch (action)
+ {
+ case GUC_ACTION_SET:
+ stack->state = GUC_SET;
+ break;
+ case GUC_ACTION_LOCAL:
+ stack->state = GUC_LOCAL;
+ break;
+ case GUC_ACTION_SAVE:
+ stack->state = GUC_SAVE;
+ break;
}
+ stack->source = gconf->source;
+ set_stack_value(gconf, &stack->prior);
+
+ gconf->stack = stack;
+
+ /* Ensure we remember to pop at end of xact */
+ guc_dirty = true;
}
+
/*
* Do GUC processing at main transaction start.
*/
AtStart_GUC(void)
{
/*
- * The nest level should be 0 between transactions; if it isn't,
- * somebody didn't call AtEOXact_GUC, or called it with the wrong
- * nestLevel. We throw a warning but make no other effort to clean up.
+ * The nest level should be 0 between transactions; if it isn't, somebody
+ * didn't call AtEOXact_GUC, or called it with the wrong nestLevel. We
+ * throw a warning but make no other effort to clean up.
*/
if (GUCNestLevel != 0)
elog(WARNING, "GUC nest level = %d at transaction start",
/*
* Enter a new nesting level for GUC values. This is called at subtransaction
- * start and when entering a function that has proconfig settings. NOTE that
+ * start and when entering a function that has proconfig settings. NOTE that
* we must not risk error here, else subtransaction start will be unhappy.
*/
int
void
AtEOXact_GUC(bool isCommit, int nestLevel)
{
+ bool still_dirty;
int i;
Assert(nestLevel > 0 && nestLevel <= GUCNestLevel);
return;
}
+ still_dirty = false;
for (i = 0; i < num_guc_variables; i++)
{
struct config_generic *gconf = guc_variables[i];
- int my_status = gconf->status;
- GucStack *stack = gconf->stack;
- bool useTentative;
- bool changed;
+ GucStack *stack;
/*
- * Skip if nothing's happened to this var in this transaction
+ * Process and pop each stack entry within the nest level. To
+ * simplify fmgr_security_definer(), we allow failure exit from a
+ * function-with-SET-options to be recovered at the surrounding
+ * transaction or subtransaction abort; so there could be more than
+ * one stack entry to pop.
*/
- if ((my_status & (GUC_HAVE_TENTATIVE |
- GUC_HAVE_LOCAL |
- GUC_HAVE_STACK)) == 0)
+ while ((stack = gconf->stack) != NULL &&
+ stack->nest_level >= nestLevel)
{
- Assert(stack == NULL);
- continue;
- }
- /* Assert that we stacked old value before changing it */
- Assert(stack != NULL && (my_status & GUC_HAVE_STACK));
- /* However, the last change may have been at an outer xact level */
- if (stack->nest_level < nestLevel)
- continue;
- Assert(stack->nest_level == nestLevel);
-
- /*
- * We will pop the stack entry. Start by restoring outer xact status
- * (since we may want to modify it below). Be careful to use
- * my_status to reference the inner xact status below this point...
- */
- gconf->status = stack->status;
+ GucStack *prev = stack->prev;
+ bool restorePrior = false;
+ bool restoreMasked = false;
+ bool changed;
- /*
- * We have two cases:
- *
- * If commit and HAVE_TENTATIVE, set actual value to tentative (this
- * is to override a SET LOCAL if one occurred later than SET). We keep
- * the tentative value and propagate HAVE_TENTATIVE to the parent
- * status, allowing the SET's effect to percolate up. (But if we're
- * exiting the outermost transaction, we'll drop the HAVE_TENTATIVE
- * bit below.)
- *
- * Otherwise, we have a transaction that aborted or executed only SET
- * LOCAL (or no SET at all). In either case it should have no further
- * effect, so restore both tentative and actual values from the stack
- * entry.
- */
-
- useTentative = isCommit && (my_status & GUC_HAVE_TENTATIVE) != 0;
- changed = false;
-
- switch (gconf->vartype)
- {
- case PGC_BOOL:
+ /*
+ * In this next bit, if we don't set either restorePrior or
+ * restoreMasked, we must "discard" any unwanted fields of the
+ * stack entries to avoid leaking memory. If we do set one of
+ * those flags, unused fields will be cleaned up after restoring.
+ */
+ if (!isCommit) /* if abort, always restore prior value */
+ restorePrior = true;
+ else if (stack->state == GUC_SAVE)
+ restorePrior = true;
+ else if (stack->nest_level == 1)
+ {
+ /* transaction commit */
+ if (stack->state == GUC_SET_LOCAL)
+ restoreMasked = true;
+ else if (stack->state == GUC_SET)
{
- struct config_bool *conf = (struct config_bool *) gconf;
- bool newval;
- GucSource newsource;
-
- if (useTentative)
- {
- newval = conf->tentative_val;
- newsource = conf->gen.tentative_source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- }
- else
- {
- newval = stack->value.boolval;
- newsource = stack->source;
- conf->tentative_val = stack->tentative_val.boolval;
- conf->gen.tentative_source = stack->tentative_source;
- }
-
- if (*conf->variable != newval)
- {
- if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval,
- true, PGC_S_OVERRIDE))
- elog(LOG, "failed to commit %s",
- conf->gen.name);
- *conf->variable = newval;
- changed = true;
- }
- conf->gen.source = newsource;
- break;
+ /* we keep the current active value */
+ discard_stack_value(gconf, &stack->prior);
}
- case PGC_INT:
+ else /* must be GUC_LOCAL */
+ restorePrior = true;
+ }
+ else if (prev == NULL ||
+ prev->nest_level < stack->nest_level - 1)
+ {
+ /* decrement entry's level and do not pop it */
+ stack->nest_level--;
+ continue;
+ }
+ else
+ {
+ /*
+ * We have to merge this stack entry into prev. See README for
+ * discussion of this bit.
+ */
+ switch (stack->state)
{
- struct config_int *conf = (struct config_int *) gconf;
- int newval;
- GucSource newsource;
+ case GUC_SAVE:
+ Assert(false); /* can't get here */
+
+ case GUC_SET:
+ /* next level always becomes SET */
+ discard_stack_value(gconf, &stack->prior);
+ if (prev->state == GUC_SET_LOCAL)
+ discard_stack_value(gconf, &prev->masked);
+ prev->state = GUC_SET;
+ break;
- if (useTentative)
- {
- newval = conf->tentative_val;
- newsource = conf->gen.tentative_source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- }
- else
- {
- newval = stack->value.intval;
- newsource = stack->source;
- conf->tentative_val = stack->tentative_val.intval;
- conf->gen.tentative_source = stack->tentative_source;
- }
+ case GUC_LOCAL:
+ if (prev->state == GUC_SET)
+ {
+ /* LOCAL migrates down */
+ prev->masked = stack->prior;
+ prev->state = GUC_SET_LOCAL;
+ }
+ else
+ {
+ /* else just forget this stack level */
+ discard_stack_value(gconf, &stack->prior);
+ }
+ break;
- if (*conf->variable != newval)
- {
- if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval,
- true, PGC_S_OVERRIDE))
- elog(LOG, "failed to commit %s",
- conf->gen.name);
- *conf->variable = newval;
- changed = true;
- }
- conf->gen.source = newsource;
- break;
+ case GUC_SET_LOCAL:
+ /* prior state at this level no longer wanted */
+ discard_stack_value(gconf, &stack->prior);
+ /* copy down the masked state */
+ if (prev->state == GUC_SET_LOCAL)
+ discard_stack_value(gconf, &prev->masked);
+ prev->masked = stack->masked;
+ prev->state = GUC_SET_LOCAL;
+ break;
}
- case PGC_REAL:
- {
- struct config_real *conf = (struct config_real *) gconf;
- double newval;
- GucSource newsource;
+ }
- if (useTentative)
- {
- newval = conf->tentative_val;
- newsource = conf->gen.tentative_source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- }
- else
- {
- newval = stack->value.realval;
- newsource = stack->source;
- conf->tentative_val = stack->tentative_val.realval;
- conf->gen.tentative_source = stack->tentative_source;
- }
+ changed = false;
- if (*conf->variable != newval)
- {
- if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval,
- true, PGC_S_OVERRIDE))
- elog(LOG, "failed to commit %s",
- conf->gen.name);
- *conf->variable = newval;
- changed = true;
- }
- conf->gen.source = newsource;
- break;
+ if (restorePrior || restoreMasked)
+ {
+ /* Perform appropriate restoration of the stacked value */
+ union config_var_value newvalue;
+ GucSource newsource;
+
+ if (restoreMasked)
+ {
+ newvalue = stack->masked;
+ newsource = PGC_S_SESSION;
}
- case PGC_STRING:
+ else
{
- struct config_string *conf = (struct config_string *) gconf;
- char *newval;
- GucSource newsource;
+ newvalue = stack->prior;
+ newsource = stack->source;
+ }
- if (useTentative)
- {
- newval = conf->tentative_val;
- newsource = conf->gen.tentative_source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- }
- else
- {
- newval = stack->value.stringval;
- newsource = stack->source;
- set_string_field(conf, &conf->tentative_val,
- stack->tentative_val.stringval);
- conf->gen.tentative_source = stack->tentative_source;
- }
+ switch (gconf->vartype)
+ {
+ case PGC_BOOL:
+ {
+ struct config_bool *conf = (struct config_bool *) gconf;
+ bool newval = newvalue.boolval;
- if (*conf->variable != newval)
- {
- if (conf->assign_hook && newval)
+ if (*conf->variable != newval)
+ {
+ if (conf->assign_hook)
+ if (!(*conf->assign_hook) (newval,
+ true, PGC_S_OVERRIDE))
+ elog(LOG, "failed to commit %s",
+ conf->gen.name);
+ *conf->variable = newval;
+ changed = true;
+ }
+ break;
+ }
+ case PGC_INT:
{
- const char *newstr;
-
- newstr = (*conf->assign_hook) (newval, true,
- PGC_S_OVERRIDE);
- if (newstr == NULL)
- elog(LOG, "failed to commit %s",
- conf->gen.name);
- else if (newstr != newval)
+ struct config_int *conf = (struct config_int *) gconf;
+ int newval = newvalue.intval;
+
+ if (*conf->variable != newval)
{
- /*
- * If newval should now be freed, it'll be
- * taken care of below.
- *
- * See notes in set_config_option about
- * casting
- */
- newval = (char *) newstr;
+ if (conf->assign_hook)
+ if (!(*conf->assign_hook) (newval,
+ true, PGC_S_OVERRIDE))
+ elog(LOG, "failed to commit %s",
+ conf->gen.name);
+ *conf->variable = newval;
+ changed = true;
}
+ break;
}
+ case PGC_REAL:
+ {
+ struct config_real *conf = (struct config_real *) gconf;
+ double newval = newvalue.realval;
- set_string_field(conf, conf->variable, newval);
- changed = true;
- }
- conf->gen.source = newsource;
- /* Release stacked values if not used anymore */
- set_string_field(conf, &stack->value.stringval,
- NULL);
- set_string_field(conf, &stack->tentative_val.stringval,
- NULL);
- /* Don't store tentative value separately after commit */
- if (nestLevel == 1)
- set_string_field(conf, &conf->tentative_val, NULL);
- break;
+ if (*conf->variable != newval)
+ {
+ if (conf->assign_hook)
+ if (!(*conf->assign_hook) (newval,
+ true, PGC_S_OVERRIDE))
+ elog(LOG, "failed to commit %s",
+ conf->gen.name);
+ *conf->variable = newval;
+ changed = true;
+ }
+ break;
+ }
+ case PGC_STRING:
+ {
+ struct config_string *conf = (struct config_string *) gconf;
+ char *newval = newvalue.stringval;
+
+ if (*conf->variable != newval)
+ {
+ if (conf->assign_hook && newval)
+ {
+ const char *newstr;
+
+ newstr = (*conf->assign_hook) (newval, true,
+ PGC_S_OVERRIDE);
+ if (newstr == NULL)
+ elog(LOG, "failed to commit %s",
+ conf->gen.name);
+ else if (newstr != newval)
+ {
+ /*
+ * If newval should now be freed,
+ * it'll be taken care of below.
+ *
+ * See notes in set_config_option
+ * about casting
+ */
+ newval = (char *) newstr;
+ }
+ }
+
+ set_string_field(conf, conf->variable, newval);
+ changed = true;
+ }
+
+ /*
+ * Release stacked values if not used anymore. We
+ * could use discard_stack_value() here, but since
+ * we have type-specific code anyway, might as
+ * well inline it.
+ */
+ set_string_field(conf, &stack->prior.stringval, NULL);
+ set_string_field(conf, &stack->masked.stringval, NULL);
+ break;
+ }
}
- }
- /* Finish popping the state stack */
- gconf->stack = stack->prev;
- pfree(stack);
+ gconf->source = newsource;
+ }
- /*
- * If we're now out of all xact levels, forget TENTATIVE status bit;
- * there's nothing tentative about the value anymore.
- */
- if (nestLevel == 1)
- {
- Assert(gconf->stack == NULL);
- gconf->status = 0;
- }
+ /* Finish popping the state stack */
+ gconf->stack = prev;
+ pfree(stack);
- /* Report new value if we changed it */
- if (changed && (gconf->flags & GUC_REPORT))
- ReportGUCOption(gconf);
+ /* Report new value if we changed it */
+ if (changed && (gconf->flags & GUC_REPORT))
+ ReportGUCOption(gconf);
+ } /* end of stack-popping loop */
+
+ if (stack != NULL)
+ still_dirty = true;
}
- /*
- * If we're now out of all xact levels, we can clear guc_dirty. (Note: we
- * cannot reset guc_dirty when exiting a subtransaction, because we know
- * that all outer transaction levels will have stacked values to deal
- * with.)
- */
- if (nestLevel == 1)
- guc_dirty = false;
+ /* If there are no remaining stack entries, we can reset guc_dirty */
+ guc_dirty = still_dirty;
/* Update nesting level */
GUCNestLevel = nestLevel - 1;
* function is being called so it can apply the access restrictions
* properly.
*
- * If value is NULL, set the option to its default value. If the
- * parameter changeVal is false then don't really set the option but do all
+ * If value is NULL, set the option to its default value (normally the
+ * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
+ *
+ * action indicates whether to set the value globally in the session, locally
+ * to the current top transaction, or just for the duration of a function call.
+ *
+ * If changeVal is false then don't really set the option but do all
* the checks to see if it would work.
*
* If there is an error (non-existing option, invalid value) then an
* ereport(ERROR) is thrown *unless* this is called in a context where we
* don't want to ereport (currently, startup or SIGHUP config file reread).
- * In that case we write a suitable error message via ereport(DEBUG) and
+ * In that case we write a suitable error message via ereport(LOG) and
* return false. This is working around the deficiencies in the ereport
* mechanism, so don't blame me. In all other cases, the function
* returns true, including cases where the input is valid but we chose
bool
set_config_option(const char *name, const char *value,
GucContext context, GucSource source,
- bool isLocal, bool changeVal)
+ GucAction action, bool changeVal)
{
struct config_generic *record;
int elevel;
* To avoid cluttering the log, only the postmaster bleats loudly
* about problems with the config file.
*/
- elevel = IsUnderPostmaster ? DEBUG2 : LOG;
+ elevel = IsUnderPostmaster ? DEBUG3 : LOG;
}
else if (source == PGC_S_DATABASE || source == PGC_S_USER)
elevel = INFO;
}
/*
- * If source is postgresql.conf, mark the found record with GUC_IS_IN_FILE.
- * This is for the convenience of ProcessConfigFile. Note that we do it
- * even if changeVal is false, since ProcessConfigFile wants the marking
- * to occur during its testing pass.
+ * If source is postgresql.conf, mark the found record with
+ * GUC_IS_IN_FILE. This is for the convenience of ProcessConfigFile. Note
+ * that we do it even if changeVal is false, since ProcessConfigFile wants
+ * the marking to occur during its testing pass.
*/
if (source == PGC_S_FILE)
record->status |= GUC_IS_IN_FILE;
/*
* We are reading a PGC_POSTMASTER var from postgresql.conf.
* We can't change the setting, so give a warning if the DBA
- * tries to change it. (Throwing an error would be more
+ * tries to change it. (Throwing an error would be more
* consistent, but seems overly rigid.)
*/
if (changeVal && !is_newvalue_equal(record, 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.) 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.
*/
makeDefault = changeVal && (source <= PGC_S_OVERRIDE) &&
((value != NULL) || source == PGC_S_DEFAULT);
/*
* Evaluate value and set variable.
- *
- * Note: if value == NULL then we are supposed to set to the reset_val,
- * except when source == PGC_S_DEFAULT; then we set to the boot_val.
*/
switch (record->vartype)
{
{
/* Save old value to support transaction abort */
if (!makeDefault)
- push_old_value(&conf->gen);
+ push_old_value(&conf->gen, action);
if (changeVal)
{
*conf->variable = newval;
{
if (stack->source <= source)
{
- stack->value.boolval = newval;
+ stack->prior.boolval = newval;
stack->source = source;
}
}
}
- else if (isLocal)
- {
- conf->gen.status |= GUC_HAVE_LOCAL;
- guc_dirty = true;
- }
- else
- {
- conf->tentative_val = newval;
- conf->gen.tentative_source = source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- guc_dirty = true;
- }
}
break;
}
{
ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for parameter \"%s\": \"%s\"",
- name, value),
+ errmsg("invalid value for parameter \"%s\": \"%s\"",
+ name, value),
hintmsg ? errhint(hintmsg) : 0));
return false;
}
{
/* Save old value to support transaction abort */
if (!makeDefault)
- push_old_value(&conf->gen);
+ push_old_value(&conf->gen, action);
if (changeVal)
{
*conf->variable = newval;
{
if (stack->source <= source)
{
- stack->value.intval = newval;
+ stack->prior.intval = newval;
stack->source = source;
}
}
}
- else if (isLocal)
- {
- conf->gen.status |= GUC_HAVE_LOCAL;
- guc_dirty = true;
- }
- else
- {
- conf->tentative_val = newval;
- conf->gen.tentative_source = source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- guc_dirty = true;
- }
}
break;
}
{
/* Save old value to support transaction abort */
if (!makeDefault)
- push_old_value(&conf->gen);
+ push_old_value(&conf->gen, action);
if (changeVal)
{
*conf->variable = newval;
{
if (stack->source <= source)
{
- stack->value.realval = newval;
+ stack->prior.realval = newval;
stack->source = source;
}
}
}
- else if (isLocal)
- {
- conf->gen.status |= GUC_HAVE_LOCAL;
- guc_dirty = true;
- }
- else
- {
- conf->tentative_val = newval;
- conf->gen.tentative_source = source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- guc_dirty = true;
- }
}
break;
}
{
/* Save old value to support transaction abort */
if (!makeDefault)
- push_old_value(&conf->gen);
+ push_old_value(&conf->gen, action);
if (changeVal)
{
set_string_field(conf, conf->variable, newval);
{
if (stack->source <= source)
{
- set_string_field(conf, &stack->value.stringval,
+ set_string_field(conf, &stack->prior.stringval,
newval);
stack->source = source;
}
if (newval && !string_field_used(conf, newval))
free(newval);
}
- else if (isLocal)
- {
- conf->gen.status |= GUC_HAVE_LOCAL;
- guc_dirty = true;
- }
- else
- {
- set_string_field(conf, &conf->tentative_val, newval);
- conf->gen.tentative_source = source;
- conf->gen.status |= GUC_HAVE_TENTATIVE;
- guc_dirty = true;
- }
}
else if (newval)
free(newval);
SetConfigOption(const char *name, const char *value,
GucContext context, GucSource source)
{
- (void) set_config_option(name, value, context, source, false, true);
+ (void) set_config_option(name, value, context, source,
+ GUC_ACTION_SET, true);
}
}
+/*
+ * GUC_complaint_elevel
+ * Get the ereport error level to use in an assign_hook's error report.
+ *
+ * This should be used by assign hooks that want to emit a custom error
+ * report (in addition to the generic "invalid value for option FOO" that
+ * guc.c will provide). Note that the result might be ERROR or a lower
+ * level, so the caller must be prepared for control to return from ereport,
+ * or not. If control does return, return false/NULL from the hook function.
+ *
+ * At some point it'd be nice to replace this with a mechanism that allows
+ * the custom message to become the DETAIL line of guc.c's generic message.
+ */
+int
+GUC_complaint_elevel(GucSource source)
+{
+ int elevel;
+
+ if (source == PGC_S_FILE)
+ {
+ /*
+ * To avoid cluttering the log, only the postmaster bleats loudly
+ * about problems with the config file.
+ */
+ elevel = IsUnderPostmaster ? DEBUG3 : LOG;
+ }
+ else if (source == PGC_S_OVERRIDE)
+ {
+ /*
+ * If we're a postmaster child, this is probably "undo" during
+ * transaction abort, so we don't want to clutter the log. There's
+ * a small chance of a real problem with an OVERRIDE setting,
+ * though, so suppressing the message entirely wouldn't be desirable.
+ */
+ elevel = IsUnderPostmaster ? DEBUG5 : LOG;
+ }
+ else if (source < PGC_S_INTERACTIVE)
+ elevel = LOG;
+ else
+ elevel = ERROR;
+
+ return elevel;
+}
+
+
/*
* flatten_set_variable_args
* Given a parsenode List as emitted by the grammar for SET,
* to interval and back to normalize the value and account
* for any typmod.
*/
+ Oid typoid;
int32 typmod;
Datum interval;
char *intervalout;
- typmod = typenameTypeMod(NULL, arg->typename, INTERVALOID);
+ typoid = typenameTypeId(NULL, arg->typename, &typmod);
+ Assert(typoid == INTERVALOID);
interval =
DirectFunctionCall3(interval_in,
void
ExecSetVariableStmt(VariableSetStmt *stmt)
{
+ GucAction action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
+
switch (stmt->kind)
{
case VAR_SET_VALUE:
ExtractSetVariableArgs(stmt),
(superuser() ? PGC_SUSET : PGC_USERSET),
PGC_S_SESSION,
- stmt->is_local,
+ action,
true);
break;
case VAR_SET_MULTI:
+
/*
- * Special case for special SQL syntax that effectively sets
- * more than one variable per statement.
+ * Special case for special SQL syntax that effectively sets more
+ * than one variable per statement.
*/
if (strcmp(stmt->name, "TRANSACTION") == 0)
{
NULL,
(superuser() ? PGC_SUSET : PGC_USERSET),
PGC_S_SESSION,
- stmt->is_local,
+ action,
true);
break;
case VAR_RESET_ALL:
argstring,
(superuser() ? PGC_SUSET : PGC_USERSET),
PGC_S_SESSION,
- is_local,
+ is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
true);
}
value,
(superuser() ? PGC_SUSET : PGC_USERSET),
PGC_S_SESSION,
- is_local,
+ is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
true);
/* get the new current value */
* variable into the GUC variable array, replacing any placeholder.
*/
static void
-define_custom_variable(struct config_generic *variable)
+define_custom_variable(struct config_generic * variable)
{
const char *name = variable->name;
const char **nameAddr = &name;
pHolder = (struct config_string *) (*res);
/*
- * Replace the placeholder.
- * We aren't changing the name, so no re-sorting is necessary
+ * Replace the placeholder. We aren't changing the name, so no re-sorting
+ * is necessary
*/
*res = variable;
if (value)
set_config_option(name, value,
pHolder->gen.context, pHolder->gen.source,
- false, true);
+ GUC_ACTION_SET, true);
/*
* Free up as much as we conveniently can of the placeholder structure
*/
set_string_field(pHolder, pHolder->variable, NULL);
set_string_field(pHolder, &pHolder->reset_val, NULL);
- set_string_field(pHolder, &pHolder->tentative_val, NULL);
free(pHolder);
}
* effects of canonicalization of string values by assign_hooks.
*/
static bool
-is_newvalue_equal(struct config_generic *record, const char *newvalue)
+is_newvalue_equal(struct config_generic * record, const char *newvalue)
{
/* newvalue == NULL isn't supported */
Assert(newvalue != NULL);
elog(FATAL, "invalid format of exec config params file");
(void) set_config_option(varname, varvalue, record->context,
- varsource, false, true);
+ varsource, GUC_ACTION_SET, true);
free(varname);
free(varvalue);
}
/*
* Handle options fetched from pg_database.datconfig, pg_authid.rolconfig,
- * pg_proc.proconfig, etc. Caller must specify proper context/source/local.
+ * pg_proc.proconfig, etc. Caller must specify proper context/source/action.
*
* The array parameter must be an array of TEXT (it must not be NULL).
*/
void
ProcessGUCArray(ArrayType *array,
- GucContext context, GucSource source, bool isLocal)
+ GucContext context, GucSource source, GucAction action)
{
int i;
continue;
}
- (void) set_config_option(name, value, context, source, isLocal, true);
+ (void) set_config_option(name, value, context, source, action, true);
free(name);
if (value)
/* test if the option is valid */
set_config_option(name, value,
superuser() ? PGC_SUSET : PGC_USERSET,
- PGC_S_TEST, false, false);
+ PGC_S_TEST, GUC_ACTION_SET, false);
/* convert name to canonical spelling, so we can use plain strcmp */
(void) GetConfigOptionByName(name, &varname);
/* test if the option is valid */
set_config_option(name, NULL,
superuser() ? PGC_SUSET : PGC_USERSET,
- PGC_S_TEST, false, false);
+ PGC_S_TEST, GUC_ACTION_SET, false);
/* convert name to canonical spelling, so we can use plain strcmp */
(void) GetConfigOptionByName(name, &varname);
/*
- * assign_hook subroutines
+ * assign_hook and show_hook subroutines
*/
static const char *
/* syntax error in list */
pfree(rawstring);
list_free(elemlist);
- if (source >= PGC_S_INTERACTIVE)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ ereport(GUC_complaint_elevel(source),
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid list syntax for parameter \"log_destination\"")));
return NULL;
}
if (pg_strcasecmp(tok, "stderr") == 0)
newlogdest |= LOG_DESTINATION_STDERR;
else if (pg_strcasecmp(tok, "csvlog") == 0)
- newlogdest |= LOG_DESTINATION_CSVLOG;
+ newlogdest |= LOG_DESTINATION_CSVLOG;
#ifdef HAVE_SYSLOG
else if (pg_strcasecmp(tok, "syslog") == 0)
newlogdest |= LOG_DESTINATION_SYSLOG;
#endif
else
{
- if (source >= PGC_S_INTERACTIVE)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ ereport(GUC_complaint_elevel(source),
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized \"log_destination\" key word: \"%s\"",
tok)));
pfree(rawstring);
static const char *
assign_session_replication_role(const char *newval, bool doit, GucSource source)
{
- int newrole;
+ int newrole;
if (pg_strcasecmp(newval, "origin") == 0)
newrole = SESSION_REPLICATION_ROLE_ORIGIN;
{
if (!newval)
{
- if (doit && source >= PGC_S_INTERACTIVE)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("SET AUTOCOMMIT TO OFF is no longer supported")));
+ ereport(GUC_complaint_elevel(source),
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("SET AUTOCOMMIT TO OFF is no longer supported")));
return false;
}
return true;
{
#ifndef USE_ASSERT_CHECKING
if (newval)
- ereport(ERROR,
+ {
+ ereport(GUC_complaint_elevel(source),
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("assertion checking is not supported by this build")));
+ return false;
+ }
#endif
return true;
}
{
#ifndef USE_SSL
if (newval)
- ereport(ERROR,
+ {
+ ereport(GUC_complaint_elevel(source),
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("SSL is not supported by this build")));
+ return false;
+ }
#endif
return true;
}
{
if (newval && log_statement_stats)
{
- if (source >= PGC_S_INTERACTIVE)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot enable parameter when \"log_statement_stats\" is true")));
+ ereport(GUC_complaint_elevel(source),
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("cannot enable parameter when \"log_statement_stats\" is true")));
/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
- else if (source != PGC_S_OVERRIDE)
+ if (source != PGC_S_OVERRIDE)
return false;
}
return true;
if (newval &&
(log_parser_stats || log_planner_stats || log_executor_stats))
{
- if (source >= PGC_S_INTERACTIVE)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot enable \"log_statement_stats\" when "
- "\"log_parser_stats\", \"log_planner_stats\", "
- "or \"log_executor_stats\" is true")));
+ ereport(GUC_complaint_elevel(source),
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("cannot enable \"log_statement_stats\" when "
+ "\"log_parser_stats\", \"log_planner_stats\", "
+ "or \"log_executor_stats\" is true")));
/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
- else if (source != PGC_S_OVERRIDE)
+ if (source != PGC_S_OVERRIDE)
return false;
}
return true;
/* Can't go to r/w mode inside a r/o transaction */
if (newval == false && XactReadOnly && IsSubTransaction())
{
- if (source >= PGC_S_INTERACTIVE)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot set transaction read-write mode inside a read-only transaction")));
+ ereport(GUC_complaint_elevel(source),
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("cannot set transaction read-write mode inside a read-only transaction")));
/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
- else if (source != PGC_S_OVERRIDE)
+ if (source != PGC_S_OVERRIDE)
return false;
}
return true;
* and we use WARNING message level.
*/
if (source == PGC_S_FILE)
- elevel = IsUnderPostmaster ? DEBUG2 : LOG;
+ elevel = IsUnderPostmaster ? DEBUG3 : LOG;
else
elevel = WARNING;
if (!load_tzoffsets(newval, doit, elevel))
return newval;
}
+static const char *
+show_archive_command(void)
+{
+ if (XLogArchiveMode)
+ return XLogArchiveCommand;
+ else
+ return "(disabled)";
+}
+
static bool
assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
{