aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/misc
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-04-07 00:11:01 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-04-07 00:12:02 -0400
commit2594cf0e8c04406ffff19b1651c5a406d376657c (patch)
tree8ced737d26b54f4499a8029d8cad0ab42fc83ba3 /src/backend/utils/misc
parent5d0e462366f4521e37744fdb42fed3c6819a3374 (diff)
downloadpostgresql-2594cf0e8c04406ffff19b1651c5a406d376657c.tar.gz
postgresql-2594cf0e8c04406ffff19b1651c5a406d376657c.zip
Revise the API for GUC variable assign hooks.
The previous functions of assign hooks are now split between check hooks and assign hooks, where the former can fail but the latter shouldn't. Aside from being conceptually clearer, this approach exposes the "canonicalized" form of the variable value to guc.c without having to do an actual assignment. And that lets us fix the problem recently noted by Bernd Helmle that the auto-tune patch for wal_buffers resulted in bogus log messages about "parameter "wal_buffers" cannot be changed without restarting the server". There may be some speed advantage too, because this design lets hook functions avoid re-parsing variable values when restoring a previous state after a rollback (they can store a pre-parsed representation of the value instead). This patch also resolves a longstanding annoyance about custom error messages from variable assign hooks: they should modify, not appear separately from, guc.c's own message about "invalid parameter value".
Diffstat (limited to 'src/backend/utils/misc')
-rw-r--r--src/backend/utils/misc/README203
-rw-r--r--src/backend/utils/misc/guc-file.l22
-rw-r--r--src/backend/utils/misc/guc.c2276
-rw-r--r--src/backend/utils/misc/tzparser.c152
4 files changed, 1564 insertions, 1089 deletions
diff --git a/src/backend/utils/misc/README b/src/backend/utils/misc/README
index 881862a30b1..70244ced18d 100644
--- a/src/backend/utils/misc/README
+++ b/src/backend/utils/misc/README
@@ -1,10 +1,10 @@
src/backend/utils/misc/README
-Guc Implementation Notes
+GUC Implementation Notes
========================
The GUC (Grand Unified Configuration) module implements configuration
-variables of multiple types (currently boolean, enum, int, float, and string).
+variables of multiple types (currently boolean, enum, int, real, and string).
Variable settings can come from various places, with a priority ordering
determining which setting is used.
@@ -12,65 +12,112 @@ determining which setting is used.
Per-Variable Hooks
------------------
-Each variable known to GUC can optionally have an assign_hook and/or
-a show_hook to provide customized behavior. Assign hooks are used to
-perform validity checking on variable values (above and beyond what
-GUC can do). They are also used to update any derived state that needs
-to change when a GUC variable is set. Show hooks are used to modify
-the default SHOW display for a variable.
+Each variable known to GUC can optionally have a check_hook, an
+assign_hook, and/or a show_hook to provide customized behavior.
+Check hooks are used to perform validity checking on variable values
+(above and beyond what GUC can do), to compute derived settings when
+nontrivial work is needed to do that, and optionally to "canonicalize"
+user-supplied values. Assign hooks are used to update any derived state
+that needs to change when a GUC variable is set. Show hooks are used to
+modify the default SHOW display for a variable.
+
+
+If a check_hook is provided, it points to a function of the signature
+ bool check_hook(datatype *newvalue, void **extra, GucSource source)
+The "newvalue" argument is of type bool *, int *, double *, or char **
+for bool, int/enum, real, or string variables respectively. The check
+function should validate the proposed new value, and return true if it is
+OK or false if not. The function can optionally do a few other things:
+
+* When rejecting a bad proposed value, it may be useful to append some
+additional information to the generic "invalid value for parameter FOO"
+complaint that guc.c will emit. To do that, call
+ void GUC_check_errdetail(const char *format, ...)
+where the format string and additional arguments follow the rules for
+errdetail() arguments. The resulting string will be emitted as the
+DETAIL line of guc.c's error report, so it should follow the message style
+guidelines for DETAIL messages. There is also
+ void GUC_check_errhint(const char *format, ...)
+which can be used in the same way to append a HINT message.
+Occasionally it may even be appropriate to override guc.c's generic primary
+message or error code, which can be done with
+ void GUC_check_errcode(int sqlerrcode)
+ void GUC_check_errmsg(const char *format, ...)
+In general, check_hooks should avoid throwing errors directly if possible,
+though this may be impractical to avoid for some corner cases such as
+out-of-memory.
+
+* Since the newvalue is pass-by-reference, the function can modify it.
+This might be used for example to canonicalize the spelling of a string
+value, round off a buffer size to the nearest supported value, or replace
+a special value such as "-1" with a computed default value. If the
+function wishes to replace a string value, it must malloc (not palloc)
+the replacement value, and be sure to free() the previous value.
+
+* Derived information, such as the role OID represented by a user name,
+can be stored for use by the assign hook. To do this, malloc (not palloc)
+storage space for the information, and return its address at *extra.
+guc.c will automatically free() this space when the associated GUC setting
+is no longer of interest. *extra is initialized to NULL before call, so
+it can be ignored if not needed.
+
+The "source" argument indicates the source of the proposed new value,
+If it is >= PGC_S_INTERACTIVE, then we are performing an interactive
+assignment (e.g., a SET command). But when source < PGC_S_INTERACTIVE,
+we are reading a non-interactive option source, such as postgresql.conf.
+This is sometimes needed to determine whether a setting should be
+allowed. The check_hook might also look at the current actual value of
+the variable to determine what is allowed.
+
+Note that check hooks are sometimes called just to validate a value,
+without any intention of actually changing the setting. Therefore the
+check hook must *not* take any action based on the assumption that an
+assignment will occur.
+
If an assign_hook is provided, it points to a function of the signature
- bool assign_hook(newvalue, bool doit, GucSource source)
-where the type of "newvalue" matches the kind of variable. This function
-is called immediately before actually setting the variable's value (so it
-can look at the actual variable to determine the old value). If the
-function returns "true" then the assignment is completed; if it returns
-"false" then newvalue is considered invalid and the assignment is not
-performed. If "doit" is false then the function should simply check
-validity of newvalue and not change any derived state. The "source" parameter
-indicates where the new value came from. If it is >= PGC_S_INTERACTIVE,
-then we are performing an interactive assignment (e.g., a SET command), and
-ereport(ERROR) is safe to do. But when source < PGC_S_INTERACTIVE, we are
-reading a non-interactive option source, such as postgresql.conf. In this
-case the assign_hook should *not* ereport but should just return false if it
-doesn't like the newvalue.
-
-If an assign_hook returns false then guc.c will report a generic "invalid
-value for option FOO" error message. If you feel the need to provide a more
-specific error message, ereport() it using "GUC_complaint_elevel(source)"
-as the error level. Note that this might return either ERROR or a lower level
-such as LOG, so the ereport call might or might not return. If it does
-return, return false out of the assign_hook.
-
-For string variables, the signature for assign hooks is a bit different:
- const char *assign_hook(const char *newvalue,
- bool doit,
- GucSource source)
-The meanings of the parameters are the same as for the other types of GUC
-variables, but the return value is handled differently:
- NULL --- assignment fails (like returning false for other datatypes)
- newvalue --- assignment succeeds, assign the newvalue as-is
- malloc'd (not palloc'd!!!) string --- assign that value instead
-The third choice is allowed in case the assign_hook wants to return a
-"canonical" version of the new value. For example, the assign_hook for
-datestyle always returns a string that includes both output and input
-datestyle options, although the input might have specified only one.
-
-Note that a string variable's assign_hook will NEVER be called with a NULL
-value for newvalue, since there would be no way to distinguish success
-and failure returns. If the boot_val or reset_val for a string variable
-is NULL, it will just be assigned without calling the assign_hook.
-Therefore, a NULL boot_val should never be used in combination with an
-assign_hook that has side-effects, as the side-effects wouldn't happen
-during a RESET that re-institutes the boot-time setting.
+ void assign_hook(datatype newvalue, void *extra)
+where the type of "newvalue" matches the kind of variable, and "extra"
+is the derived-information pointer returned by the check_hook (always
+NULL if there is no check_hook). This function is called immediately
+before actually setting the variable's value (so it can look at the actual
+variable to determine the old value, for example to avoid doing work when
+the value isn't really changing).
+
+Note that there is no provision for a failure result code. assign_hooks
+should never fail except under the most dire circumstances, since a failure
+may for example result in GUC settings not being rolled back properly during
+transaction abort. In general, try to do anything that could conceivably
+fail in a check_hook instead, and pass along the results in an "extra"
+struct, so that the assign hook has little to do beyond copying the data to
+someplace. This applies particularly to catalog lookups: any required
+lookups must be done in the check_hook, since the assign_hook may be
+executed during transaction rollback when lookups will be unsafe.
+
+Note that check_hooks are sometimes called outside any transaction, too.
+This happens when processing the wired-in "bootstrap" value, values coming
+from the postmaster command line or environment, or values coming from
+postgresql.conf. Therefore, any catalog lookups done in a check_hook
+should be guarded with an IsTransactionState() test, and there must be a
+fallback path to allow derived values to be computed during the first
+subsequent use of the GUC setting within a transaction. A typical
+arrangement is for the catalog values computed by the check_hook and
+installed by the assign_hook to be used only for the remainder of the
+transaction in which the new setting is made. Each subsequent transaction
+looks up the values afresh on first use. This arrangement is useful to
+prevent use of stale catalog values, independently of the problem of
+needing to check GUC values outside a transaction.
+
If a show_hook is provided, it points to a function of the signature
const char *show_hook(void)
This hook allows variable-specific computation of the value displayed
-by SHOW.
+by SHOW (and other SQL features for showing GUC variable values).
+The return value can point to a static buffer, since show functions are
+not used re-entrantly.
-Saving/Restoring Guc Variable Values
+Saving/Restoring GUC Variable Values
------------------------------------
Prior values of configuration variables must be remembered in order to deal
@@ -200,27 +247,49 @@ these has a current source priority <= PGC_S_FILE. (It is thus possible
for reset_val to track the config-file setting even if there is
currently a different interactive value of the actual variable.)
-The assign_hook and show_hook routines work only with the actual variable,
-and are not directly aware of the additional values maintained by GUC.
-This is not a problem for normal usage, since we can assign first to the
-actual variable and then (if that succeeds) to the additional values as
-needed. However, for SIGHUP rereads we may not want to assign to the
-actual variable. Our procedure in that case is to call the assign_hook
-with doit = false so that the value is validated, but no derived state is
-changed.
+The check_hook, assign_hook and show_hook routines work only with the
+actual variable, and are not directly aware of the additional values
+maintained by GUC.
-String Memory Handling
-----------------------
+GUC Memory Handling
+-------------------
-String option values are allocated with strdup, not with the
-pstrdup/palloc mechanisms. We would need to keep them in a permanent
-context anyway, and strdup gives us more control over handling
+String variable values are allocated with malloc/strdup, not with the
+palloc/pstrdup mechanisms. We would need to keep them in a permanent
+context anyway, and malloc gives us more control over handling
out-of-memory failures.
We allow a string variable's actual value, reset_val, boot_val, and stacked
values to point at the same storage. This makes it slightly harder to free
space (we must test whether a value to be freed isn't equal to any of the
other pointers in the GUC entry or associated stack items). The main
-advantage is that we never need to strdup during transaction commit/abort,
+advantage is that we never need to malloc during transaction commit/abort,
so cannot cause an out-of-memory failure there.
+
+"Extra" structs returned by check_hook routines are managed in the same
+way as string values. Note that we support "extra" structs for all types
+of GUC variables, although they are mainly useful with strings.
+
+
+GUC and Null String Variables
+-----------------------------
+
+A GUC string variable can have a boot_val of NULL. guc.c handles this
+unsurprisingly, assigning the NULL to the underlying C variable. Any code
+using such a variable, as well as any hook functions for it, must then be
+prepared to deal with a NULL value.
+
+However, it is not possible to assign a NULL value to a GUC string
+variable in any other way: values coming from SET, postgresql.conf, etc,
+might be empty strings, but they'll never be NULL. And SHOW displays
+a NULL the same as an empty string. It is therefore not appropriate to
+treat a NULL value as a distinct user-visible setting. A typical use
+for a NULL boot_val is to denote that a value hasn't yet been set for
+a variable that will receive a real value later in startup.
+
+If it's undesirable for code using the underlying C variable to have to
+worry about NULL values ever, the variable can be given a non-null static
+initializer as well as a non-null boot_val. guc.c will overwrite the
+static initializer pointer with a copy of the boot_val during
+InitializeGUCOptions, but the variable will never contain a NULL.
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index e6603958982..10ef12eb24b 100644
--- a/src/backend/utils/misc/guc-file.l
+++ b/src/backend/utils/misc/guc-file.l
@@ -141,7 +141,8 @@ ProcessConfigFile(GucContext context)
*/
cvc_struct = (struct config_string *)
find_option("custom_variable_classes", false, elevel);
- if (cvc_struct && cvc_struct->gen.reset_source > PGC_S_FILE)
+ Assert(cvc_struct);
+ if (cvc_struct->gen.reset_source > PGC_S_FILE)
{
cvc = guc_strdup(elevel, cvc_struct->reset_val);
if (cvc == NULL)
@@ -151,19 +152,18 @@ ProcessConfigFile(GucContext context)
guc_name_compare(head->name, "custom_variable_classes") == 0)
{
/*
- * Need to canonicalize the value via the assign hook. Casting away
- * const is a bit ugly, but we know the result is malloc'd.
+ * Need to canonicalize the value by calling the check hook.
*/
- cvc = (char *) assign_custom_variable_classes(head->value,
- false, PGC_S_FILE);
+ void *extra = NULL;
+
+ cvc = guc_strdup(elevel, head->value);
if (cvc == NULL)
- {
- ereport(elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for parameter \"%s\": \"%s\"",
- head->name, head->value)));
goto cleanup_list;
- }
+ if (!call_string_check_hook(cvc_struct, &cvc, &extra,
+ PGC_S_FILE, elevel))
+ goto cleanup_list;
+ if (extra)
+ free(extra);
}
/*
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 2151fde3618..5e4904aeb7f 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -104,7 +104,7 @@
* backend ID as a 3-byte signed integer. Even if that limitation were
* removed, we still could not exceed INT_MAX/4 because some places compute
* 4*MaxBackends without any overflow check. This is rechecked in
- * assign_maxconnections, since MaxBackends is computed as MaxConnections
+ * check_maxconnections, since MaxBackends is computed as MaxConnections
* plus autovacuum_max_workers plus one (for the autovacuum launcher).
*/
#define MAX_BACKENDS 0x7fffff
@@ -143,11 +143,29 @@ extern bool trace_syncscan;
extern bool optimize_bounded_sort;
#endif
+static int GUC_check_errcode_value;
+
+/* global variables for check hook support */
+char *GUC_check_errmsg_string;
+char *GUC_check_errdetail_string;
+char *GUC_check_errhint_string;
+
+
static void set_config_sourcefile(const char *name, char *sourcefile,
int sourceline);
-
-static const char *assign_log_destination(const char *value,
- bool doit, GucSource source);
+static bool call_bool_check_hook(struct config_bool *conf, bool *newval,
+ void **extra, GucSource source, int elevel);
+static bool call_int_check_hook(struct config_int *conf, int *newval,
+ void **extra, GucSource source, int elevel);
+static bool call_real_check_hook(struct config_real *conf, double *newval,
+ void **extra, GucSource source, int elevel);
+static bool call_string_check_hook(struct config_string *conf, char **newval,
+ void **extra, GucSource source, int elevel);
+static bool call_enum_check_hook(struct config_enum *conf, int *newval,
+ void **extra, GucSource source, int elevel);
+
+static bool check_log_destination(char **newval, void **extra, GucSource source);
+static void assign_log_destination(const char *newval, void *extra);
#ifdef HAVE_SYSLOG
static int syslog_facility = LOG_LOCAL0;
@@ -155,36 +173,36 @@ static int syslog_facility = LOG_LOCAL0;
static int syslog_facility = 0;
#endif
-static bool assign_syslog_facility(int newval,
- bool doit, GucSource source);
-static const char *assign_syslog_ident(const char *ident,
- bool doit, GucSource source);
-
-static bool assign_session_replication_role(int newval, bool doit,
- GucSource source);
-static const char *show_num_temp_buffers(void);
-static bool assign_phony_autocommit(bool newval, bool doit, GucSource source);
-static const char *assign_custom_variable_classes(const char *newval, bool doit,
- GucSource source);
-static bool assign_debug_assertions(bool newval, bool doit, GucSource source);
-static bool assign_bonjour(bool newval, bool doit, GucSource source);
-static bool assign_ssl(bool newval, bool doit, GucSource source);
-static bool assign_stage_log_stats(bool newval, bool doit, GucSource source);
-static bool assign_log_stats(bool newval, bool doit, GucSource source);
-static const char *assign_canonical_path(const char *newval, bool doit, GucSource source);
-static const char *assign_timezone_abbreviations(const char *newval, bool doit, GucSource source);
+static void assign_syslog_facility(int newval, void *extra);
+static void assign_syslog_ident(const char *newval, void *extra);
+static void assign_session_replication_role(int newval, void *extra);
+static bool check_temp_buffers(int *newval, void **extra, GucSource source);
+static bool check_phony_autocommit(bool *newval, void **extra, GucSource source);
+static bool check_custom_variable_classes(char **newval, void **extra, GucSource source);
+static bool check_debug_assertions(bool *newval, void **extra, GucSource source);
+static bool check_bonjour(bool *newval, void **extra, GucSource source);
+static bool check_ssl(bool *newval, void **extra, GucSource source);
+static bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
+static bool check_log_stats(bool *newval, void **extra, GucSource source);
+static bool check_canonical_path(char **newval, void **extra, GucSource source);
+static bool check_timezone_abbreviations(char **newval, void **extra, GucSource source);
+static void assign_timezone_abbreviations(const char *newval, void *extra);
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);
+static void assign_tcp_keepalives_idle(int newval, void *extra);
+static void assign_tcp_keepalives_interval(int newval, void *extra);
+static void assign_tcp_keepalives_count(int newval, void *extra);
static const char *show_tcp_keepalives_idle(void);
static const char *show_tcp_keepalives_interval(void);
static const char *show_tcp_keepalives_count(void);
-static bool assign_maxconnections(int newval, bool doit, GucSource source);
-static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source);
-static bool assign_effective_io_concurrency(int newval, bool doit, GucSource source);
-static const char *assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source);
-static const char *assign_application_name(const char *newval, bool doit, GucSource source);
+static bool check_maxconnections(int *newval, void **extra, GucSource source);
+static void assign_maxconnections(int newval, void *extra);
+static bool check_autovacuum_max_workers(int *newval, void **extra, GucSource source);
+static void assign_autovacuum_max_workers(int newval, void *extra);
+static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
+static void assign_effective_io_concurrency(int newval, void *extra);
+static void assign_pgstat_temp_directory(const char *newval, void *extra);
+static bool check_application_name(char **newval, void **extra, GucSource source);
+static void assign_application_name(const char *newval, void *extra);
static const char *show_unix_socket_permissions(void);
static const char *show_log_file_mode(void);
@@ -407,7 +425,7 @@ int log_min_duration_statement = -1;
int log_temp_files = -1;
int trace_recovery_messages = LOG;
-int num_temp_buffers = 1000;
+int num_temp_buffers = 1024;
char *data_directory;
char *ConfigFileName;
@@ -444,6 +462,8 @@ static int server_version_num;
static char *timezone_string;
static char *log_timezone_string;
static char *timezone_abbreviations_string;
+static char *XactIsoLevel_string;
+static char *session_authorization_string;
static char *custom_variable_classes;
static int max_function_args;
static int max_index_keys;
@@ -455,10 +475,8 @@ static int wal_segment_size;
static bool integer_datetimes;
static int effective_io_concurrency;
-/* should be static, but commands/variable.c needs to get at these */
+/* should be static, but commands/variable.c needs to get at this */
char *role_string;
-char *session_authorization_string;
-char *XactIsoLevel_string;
/*
@@ -643,7 +661,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_seqscan,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -651,7 +670,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_indexscan,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -659,7 +679,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_bitmapscan,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -667,7 +688,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_tidscan,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -675,7 +697,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_sort,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -683,7 +706,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_hashagg,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_material", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -691,7 +715,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_material,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -699,7 +724,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_nestloop,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -707,7 +733,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_mergejoin,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -715,7 +742,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_hashjoin,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
@@ -724,7 +752,8 @@ static struct config_bool ConfigureNamesBool[] =
"exhaustive searching.")
},
&enable_geqo,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
/* Not for general use --- used by SET SESSION AUTHORIZATION */
@@ -734,7 +763,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&session_auth_is_superuser,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
@@ -742,7 +772,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&enable_bonjour,
- false, assign_bonjour, NULL
+ false,
+ check_bonjour, NULL, NULL
},
{
{"ssl", PGC_POSTMASTER, CONN_AUTH_SECURITY,
@@ -750,7 +781,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&EnableSSL,
- false, assign_ssl, NULL
+ false,
+ check_ssl, NULL, NULL
},
{
{"fsync", PGC_SIGHUP, WAL_SETTINGS,
@@ -761,7 +793,8 @@ static struct config_bool ConfigureNamesBool[] =
"an operating system or hardware crash.")
},
&enableFsync,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
@@ -774,7 +807,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&zero_damaged_pages,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
@@ -786,7 +820,8 @@ static struct config_bool ConfigureNamesBool[] =
"is possible.")
},
&fullPageWrites,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"silent_mode", PGC_POSTMASTER, LOGGING_WHERE,
@@ -795,7 +830,8 @@ static struct config_bool ConfigureNamesBool[] =
"background and any controlling terminals are dissociated.")
},
&SilentMode,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
@@ -803,7 +839,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&log_checkpoints,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"log_connections", PGC_BACKEND, LOGGING_WHAT,
@@ -811,7 +848,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Log_connections,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"log_disconnections", PGC_BACKEND, LOGGING_WHAT,
@@ -819,7 +857,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Log_disconnections,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"debug_assertions", PGC_USERSET, DEVELOPER_OPTIONS,
@@ -833,7 +872,7 @@ static struct config_bool ConfigureNamesBool[] =
#else
false,
#endif
- assign_debug_assertions, NULL
+ check_debug_assertions, NULL, NULL
},
{
@@ -842,7 +881,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&ExitOnAnyError,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"restart_after_crash", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
@@ -850,7 +890,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&restart_after_crash,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
@@ -859,7 +900,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&log_duration,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
@@ -867,7 +909,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Debug_print_parse,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
@@ -875,7 +918,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Debug_print_rewritten,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
@@ -883,7 +927,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Debug_print_plan,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
@@ -891,7 +936,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Debug_pretty_print,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"log_parser_stats", PGC_SUSET, STATS_MONITORING,
@@ -899,7 +945,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&log_parser_stats,
- false, assign_stage_log_stats, NULL
+ false,
+ check_stage_log_stats, NULL, NULL
},
{
{"log_planner_stats", PGC_SUSET, STATS_MONITORING,
@@ -907,7 +954,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&log_planner_stats,
- false, assign_stage_log_stats, NULL
+ false,
+ check_stage_log_stats, NULL, NULL
},
{
{"log_executor_stats", PGC_SUSET, STATS_MONITORING,
@@ -915,7 +963,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&log_executor_stats,
- false, assign_stage_log_stats, NULL
+ false,
+ check_stage_log_stats, NULL, NULL
},
{
{"log_statement_stats", PGC_SUSET, STATS_MONITORING,
@@ -923,7 +972,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&log_statement_stats,
- false, assign_log_stats, NULL
+ false,
+ check_log_stats, NULL, NULL
},
#ifdef BTREE_BUILD_STATS
{
@@ -933,7 +983,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&log_btree_build_stats,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
#endif
@@ -945,7 +996,8 @@ static struct config_bool ConfigureNamesBool[] =
"the time at which that command began execution.")
},
&pgstat_track_activities,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"track_counts", PGC_SUSET, STATS_COLLECTOR,
@@ -953,7 +1005,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&pgstat_track_counts,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
@@ -962,7 +1015,8 @@ static struct config_bool ConfigureNamesBool[] =
gettext_noop("Enables updating of the process title every time a new SQL command is received by the server.")
},
&update_process_title,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
@@ -971,7 +1025,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&autovacuum_start_daemon,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
@@ -981,7 +1036,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&Trace_notify,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
#ifdef LOCK_DEBUG
@@ -992,7 +1048,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&Trace_locks,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
@@ -1001,7 +1058,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&Trace_userlocks,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
@@ -1010,7 +1068,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&Trace_lwlocks,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
@@ -1019,7 +1078,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&Debug_deadlocks,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
#endif
@@ -1029,7 +1089,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&log_lock_waits,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
@@ -1041,7 +1102,8 @@ static struct config_bool ConfigureNamesBool[] =
"setup it might impose a non-negligible performance penalty.")
},
&log_hostname,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"sql_inheritance", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
@@ -1049,7 +1111,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&SQL_inheritance,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
@@ -1059,7 +1122,8 @@ static struct config_bool ConfigureNamesBool[] =
"this parameter determines whether the password is to be encrypted.")
},
&Password_encryption,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
@@ -1071,7 +1135,8 @@ static struct config_bool ConfigureNamesBool[] =
"return null (unknown).")
},
&Transform_null_equals,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"db_user_namespace", PGC_SIGHUP, CONN_AUTH_SECURITY,
@@ -1079,7 +1144,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Db_user_namespace,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
/* only here for backwards compatibility */
@@ -1089,7 +1155,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
},
&phony_autocommit,
- true, assign_phony_autocommit, NULL
+ true,
+ check_phony_autocommit, NULL, NULL
},
{
{"default_transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
@@ -1097,7 +1164,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&DefaultXactReadOnly,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
@@ -1106,7 +1174,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&XactReadOnly,
- false, assign_transaction_read_only, NULL
+ false,
+ check_transaction_read_only, NULL, NULL
},
{
{"default_transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
@@ -1114,7 +1183,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&DefaultXactDeferrable,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
@@ -1123,7 +1193,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&XactDeferrable,
- false, assign_transaction_deferrable, NULL
+ false,
+ check_transaction_deferrable, NULL, NULL
},
{
{"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
@@ -1131,7 +1202,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&check_function_bodies,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
@@ -1141,7 +1213,8 @@ static struct config_bool ConfigureNamesBool[] =
"otherwise it is taken literally.")
},
&Array_nulls,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
{"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
@@ -1149,7 +1222,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&default_with_oids,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"logging_collector", PGC_POSTMASTER, LOGGING_WHERE,
@@ -1157,7 +1231,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Logging_collector,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
{"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
@@ -1165,7 +1240,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&Log_truncate_on_rotation,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
#ifdef TRACE_SORT
@@ -1176,7 +1252,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&trace_sort,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
#endif
@@ -1189,7 +1266,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&trace_syncscan,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
#endif
@@ -1203,7 +1281,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&optimize_bounded_sort,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
#endif
@@ -1215,7 +1294,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&XLOG_DEBUG,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
#endif
@@ -1227,10 +1307,11 @@ static struct config_bool ConfigureNamesBool[] =
},
&integer_datetimes,
#ifdef HAVE_INT64_TIMESTAMP
- true, NULL, NULL
+ true,
#else
- false, NULL, NULL
+ false,
#endif
+ NULL, NULL, NULL
},
{
@@ -1239,7 +1320,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&pg_krb_caseins_users,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
@@ -1248,7 +1330,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&escape_string_warning,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
@@ -1258,7 +1341,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_REPORT
},
&standard_conforming_strings,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
@@ -1267,7 +1351,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&synchronize_seqscans,
- true, NULL, NULL
+ true,
+ NULL, NULL, NULL
},
{
@@ -1276,7 +1361,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&XLogArchiveMode,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
@@ -1285,7 +1371,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&EnableHotStandby,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
@@ -1294,7 +1381,8 @@ static struct config_bool ConfigureNamesBool[] =
NULL
},
&hot_standby_feedback,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
@@ -1304,7 +1392,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&allowSystemTableMods,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
@@ -1315,7 +1404,8 @@ static struct config_bool ConfigureNamesBool[] =
GUC_NOT_IN_SAMPLE
},
&IgnoreSystemIndexes,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
@@ -1325,7 +1415,8 @@ static struct config_bool ConfigureNamesBool[] =
"for compatibility with PostgreSQL releases prior to 9.0.")
},
&lo_compat_privileges,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
{
@@ -1334,12 +1425,13 @@ static struct config_bool ConfigureNamesBool[] =
NULL,
},
&quote_all_identifiers,
- false, NULL, NULL
+ false,
+ NULL, NULL, NULL
},
/* End-of-list marker */
{
- {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL
+ {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
}
};
@@ -1354,7 +1446,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_S
},
&XLogArchiveTimeout,
- 0, 0, INT_MAX, NULL, NULL
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
{"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
@@ -1363,7 +1456,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE | GUC_UNIT_S
},
&PostAuthDelay,
- 0, 0, INT_MAX, NULL, NULL
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
{"default_statistics_target", PGC_USERSET, QUERY_TUNING_OTHER,
@@ -1372,7 +1466,8 @@ static struct config_int ConfigureNamesInt[] =
"column-specific target set via ALTER TABLE SET STATISTICS.")
},
&default_statistics_target,
- 100, 1, 10000, NULL, NULL
+ 100, 1, 10000,
+ NULL, NULL, NULL
},
{
{"from_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
@@ -1383,7 +1478,8 @@ static struct config_int ConfigureNamesInt[] =
"this many items.")
},
&from_collapse_limit,
- 8, 1, INT_MAX, NULL, NULL
+ 8, 1, INT_MAX,
+ NULL, NULL, NULL
},
{
{"join_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
@@ -1394,7 +1490,8 @@ static struct config_int ConfigureNamesInt[] =
"list of no more than this many items would result.")
},
&join_collapse_limit,
- 8, 1, INT_MAX, NULL, NULL
+ 8, 1, INT_MAX,
+ NULL, NULL, NULL
},
{
{"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
@@ -1402,7 +1499,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&geqo_threshold,
- 12, 2, INT_MAX, NULL, NULL
+ 12, 2, INT_MAX,
+ NULL, NULL, NULL
},
{
{"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
@@ -1410,7 +1508,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&Geqo_effort,
- DEFAULT_GEQO_EFFORT, MIN_GEQO_EFFORT, MAX_GEQO_EFFORT, NULL, NULL
+ DEFAULT_GEQO_EFFORT, MIN_GEQO_EFFORT, MAX_GEQO_EFFORT,
+ NULL, NULL, NULL
},
{
{"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
@@ -1418,7 +1517,8 @@ static struct config_int ConfigureNamesInt[] =
gettext_noop("Zero selects a suitable default value.")
},
&Geqo_pool_size,
- 0, 0, INT_MAX, NULL, NULL
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
{"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
@@ -1426,7 +1526,8 @@ static struct config_int ConfigureNamesInt[] =
gettext_noop("Zero selects a suitable default value.")
},
&Geqo_generations,
- 0, 0, INT_MAX, NULL, NULL
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1437,7 +1538,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&DeadlockTimeout,
- 1000, 1, INT_MAX, NULL, NULL
+ 1000, 1, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1447,7 +1549,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&max_standby_archive_delay,
- 30 * 1000, -1, INT_MAX, NULL, NULL
+ 30 * 1000, -1, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1457,7 +1560,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&max_standby_streaming_delay,
- 30 * 1000, -1, INT_MAX, NULL, NULL
+ 30 * 1000, -1, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1467,7 +1571,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_S
},
&wal_receiver_status_interval,
- 10, 0, INT_MAX/1000, NULL, NULL
+ 10, 0, INT_MAX/1000,
+ NULL, NULL, NULL
},
{
@@ -1476,7 +1581,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&MaxConnections,
- 100, 1, MAX_BACKENDS, assign_maxconnections, NULL
+ 100, 1, MAX_BACKENDS,
+ check_maxconnections, assign_maxconnections, NULL
},
{
@@ -1485,7 +1591,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&ReservedBackends,
- 3, 0, MAX_BACKENDS, NULL, NULL
+ 3, 0, MAX_BACKENDS,
+ NULL, NULL, NULL
},
/*
@@ -1499,7 +1606,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_BLOCKS
},
&NBuffers,
- 1024, 16, INT_MAX / 2, NULL, NULL
+ 1024, 16, INT_MAX / 2,
+ NULL, NULL, NULL
},
{
@@ -1509,7 +1617,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_BLOCKS
},
&num_temp_buffers,
- 1024, 100, INT_MAX / 2, NULL, show_num_temp_buffers
+ 1024, 100, INT_MAX / 2,
+ check_temp_buffers, NULL, NULL
},
{
@@ -1518,7 +1627,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&PostPortNumber,
- DEF_PGPORT, 1, 65535, NULL, NULL
+ DEF_PGPORT, 1, 65535,
+ NULL, NULL, NULL
},
{
@@ -1532,7 +1642,8 @@ static struct config_int ConfigureNamesInt[] =
"start with a 0 (zero).)")
},
&Unix_socket_permissions,
- 0777, 0000, 0777, NULL, show_unix_socket_permissions
+ 0777, 0000, 0777,
+ NULL, NULL, show_unix_socket_permissions
},
{
@@ -1545,7 +1656,8 @@ static struct config_int ConfigureNamesInt[] =
"start with a 0 (zero).)")
},
&Log_file_mode,
- 0600, 0000, 0777, NULL, show_log_file_mode
+ 0600, 0000, 0777,
+ NULL, NULL, show_log_file_mode
},
{
@@ -1557,7 +1669,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_KB
},
&work_mem,
- 1024, 64, MAX_KILOBYTES, NULL, NULL
+ 1024, 64, MAX_KILOBYTES,
+ NULL, NULL, NULL
},
{
@@ -1567,7 +1680,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_KB
},
&maintenance_work_mem,
- 16384, 1024, MAX_KILOBYTES, NULL, NULL
+ 16384, 1024, MAX_KILOBYTES,
+ NULL, NULL, NULL
},
/*
@@ -1582,7 +1696,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_KB
},
&max_stack_depth,
- 100, 100, MAX_KILOBYTES, assign_max_stack_depth, NULL
+ 100, 100, MAX_KILOBYTES,
+ check_max_stack_depth, assign_max_stack_depth, NULL
},
{
@@ -1591,7 +1706,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&VacuumCostPageHit,
- 1, 0, 10000, NULL, NULL
+ 1, 0, 10000,
+ NULL, NULL, NULL
},
{
@@ -1600,7 +1716,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&VacuumCostPageMiss,
- 10, 0, 10000, NULL, NULL
+ 10, 0, 10000,
+ NULL, NULL, NULL
},
{
@@ -1609,7 +1726,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&VacuumCostPageDirty,
- 20, 0, 10000, NULL, NULL
+ 20, 0, 10000,
+ NULL, NULL, NULL
},
{
@@ -1618,7 +1736,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&VacuumCostLimit,
- 200, 1, 10000, NULL, NULL
+ 200, 1, 10000,
+ NULL, NULL, NULL
},
{
@@ -1628,7 +1747,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&VacuumCostDelay,
- 0, 0, 100, NULL, NULL
+ 0, 0, 100,
+ NULL, NULL, NULL
},
{
@@ -1638,7 +1758,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&autovacuum_vac_cost_delay,
- 20, -1, 100, NULL, NULL
+ 20, -1, 100,
+ NULL, NULL, NULL
},
{
@@ -1647,7 +1768,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&autovacuum_vac_cost_limit,
- -1, -1, 10000, NULL, NULL
+ -1, -1, 10000,
+ NULL, NULL, NULL
},
{
@@ -1656,7 +1778,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&max_files_per_process,
- 1000, 25, INT_MAX, NULL, NULL
+ 1000, 25, INT_MAX,
+ NULL, NULL, NULL
},
/*
@@ -1668,7 +1791,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&max_prepared_xacts,
- 0, 0, MAX_BACKENDS, NULL, NULL
+ 0, 0, MAX_BACKENDS,
+ NULL, NULL, NULL
},
#ifdef LOCK_DEBUG
@@ -1679,7 +1803,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE
},
&Trace_lock_oidmin,
- FirstNormalObjectId, 0, INT_MAX, NULL, NULL
+ FirstNormalObjectId, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
{"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
@@ -1688,7 +1813,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE
},
&Trace_lock_table,
- 0, 0, INT_MAX, NULL, NULL
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
},
#endif
@@ -1699,7 +1825,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&StatementTimeout,
- 0, 0, INT_MAX, NULL, NULL
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1708,7 +1835,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&vacuum_freeze_min_age,
- 50000000, 0, 1000000000, NULL, NULL
+ 50000000, 0, 1000000000,
+ NULL, NULL, NULL
},
{
@@ -1717,7 +1845,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&vacuum_freeze_table_age,
- 150000000, 0, 2000000000, NULL, NULL
+ 150000000, 0, 2000000000,
+ NULL, NULL, NULL
},
{
@@ -1726,7 +1855,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&vacuum_defer_cleanup_age,
- 0, 0, 1000000, NULL, NULL
+ 0, 0, 1000000,
+ NULL, NULL, NULL
},
/*
@@ -1740,7 +1870,8 @@ static struct config_int ConfigureNamesInt[] =
"objects will need to be locked at any one time.")
},
&max_locks_per_xact,
- 64, 10, INT_MAX, NULL, NULL
+ 64, 10, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1751,7 +1882,8 @@ static struct config_int ConfigureNamesInt[] =
"objects will need to be locked at any one time.")
},
&max_predicate_locks_per_xact,
- 64, 10, INT_MAX, NULL, NULL
+ 64, 10, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1761,7 +1893,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_S
},
&AuthenticationTimeout,
- 60, 1, 600, NULL, NULL
+ 60, 1, 600,
+ NULL, NULL, NULL
},
{
@@ -1772,7 +1905,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE | GUC_UNIT_S
},
&PreAuthDelay,
- 0, 0, 60, NULL, NULL
+ 0, 0, 60,
+ NULL, NULL, NULL
},
{
@@ -1781,7 +1915,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&wal_keep_segments,
- 0, 0, INT_MAX, NULL, NULL
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1790,7 +1925,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&CheckPointSegments,
- 3, 1, INT_MAX, NULL, NULL
+ 3, 1, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1800,7 +1936,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_S
},
&CheckPointTimeout,
- 300, 30, 3600, NULL, NULL
+ 300, 30, 3600,
+ NULL, NULL, NULL
},
{
@@ -1813,7 +1950,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_S
},
&CheckPointWarning,
- 30, 0, INT_MAX, NULL, NULL
+ 30, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1823,7 +1961,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_XBLOCKS
},
&XLOGbuffers,
- -1, -1, INT_MAX, NULL, NULL
+ -1, -1, INT_MAX,
+ check_wal_buffers, NULL, NULL
},
{
@@ -1833,7 +1972,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&WalWriterDelay,
- 200, 1, 10000, NULL, NULL
+ 200, 1, 10000,
+ NULL, NULL, NULL
},
{
@@ -1843,7 +1983,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&max_wal_senders,
- 0, 0, MAX_BACKENDS, NULL, NULL
+ 0, 0, MAX_BACKENDS,
+ NULL, NULL, NULL
},
{
@@ -1853,7 +1994,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&WalSndDelay,
- 1000, 1, 10000, NULL, NULL
+ 1000, 1, 10000,
+ NULL, NULL, NULL
},
{
@@ -1863,7 +2005,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&replication_timeout,
- 60 * 1000, 0, INT_MAX, NULL, NULL
+ 60 * 1000, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1873,7 +2016,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&CommitDelay,
- 0, 0, 100000, NULL, NULL
+ 0, 0, 100000,
+ NULL, NULL, NULL
},
{
@@ -1883,7 +2027,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&CommitSiblings,
- 5, 0, 1000, NULL, NULL
+ 5, 0, 1000,
+ NULL, NULL, NULL
},
{
@@ -1894,7 +2039,8 @@ static struct config_int ConfigureNamesInt[] =
"(FLT_DIG or DBL_DIG as appropriate).")
},
&extra_float_digits,
- 0, -15, 3, NULL, NULL
+ 0, -15, 3,
+ NULL, NULL, NULL
},
{
@@ -1905,7 +2051,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&log_min_duration_statement,
- -1, -1, INT_MAX, NULL, NULL
+ -1, -1, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1916,7 +2063,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&Log_autovacuum_min_duration,
- -1, -1, INT_MAX, NULL, NULL
+ -1, -1, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -1926,7 +2074,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MS
},
&BgWriterDelay,
- 200, 10, 10000, NULL, NULL
+ 200, 10, 10000,
+ NULL, NULL, NULL
},
{
@@ -1935,7 +2084,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&bgwriter_lru_maxpages,
- 100, 0, 1000, NULL, NULL
+ 100, 0, 1000,
+ NULL, NULL, NULL
},
{
@@ -1955,7 +2105,7 @@ static struct config_int ConfigureNamesInt[] =
#else
0, 0, 0,
#endif
- assign_effective_io_concurrency, NULL
+ check_effective_io_concurrency, assign_effective_io_concurrency, NULL
},
{
@@ -1965,7 +2115,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_MIN
},
&Log_RotationAge,
- HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / MINS_PER_HOUR, NULL, NULL
+ HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / MINS_PER_HOUR,
+ NULL, NULL, NULL
},
{
@@ -1975,7 +2126,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_KB
},
&Log_RotationSize,
- 10 * 1024, 0, INT_MAX / 1024, NULL, NULL
+ 10 * 1024, 0, INT_MAX / 1024,
+ NULL, NULL, NULL
},
{
@@ -1985,7 +2137,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&max_function_args,
- FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS, NULL, NULL
+ FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS,
+ NULL, NULL, NULL
},
{
@@ -1995,7 +2148,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&max_index_keys,
- INDEX_MAX_KEYS, INDEX_MAX_KEYS, INDEX_MAX_KEYS, NULL, NULL
+ INDEX_MAX_KEYS, INDEX_MAX_KEYS, INDEX_MAX_KEYS,
+ NULL, NULL, NULL
},
{
@@ -2005,7 +2159,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&max_identifier_length,
- NAMEDATALEN - 1, NAMEDATALEN - 1, NAMEDATALEN - 1, NULL, NULL
+ NAMEDATALEN - 1, NAMEDATALEN - 1, NAMEDATALEN - 1,
+ NULL, NULL, NULL
},
{
@@ -2015,7 +2170,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&block_size,
- BLCKSZ, BLCKSZ, BLCKSZ, NULL, NULL
+ BLCKSZ, BLCKSZ, BLCKSZ,
+ NULL, NULL, NULL
},
{
@@ -2025,7 +2181,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_BLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&segment_size,
- RELSEG_SIZE, RELSEG_SIZE, RELSEG_SIZE, NULL, NULL
+ RELSEG_SIZE, RELSEG_SIZE, RELSEG_SIZE,
+ NULL, NULL, NULL
},
{
@@ -2035,7 +2192,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&wal_block_size,
- XLOG_BLCKSZ, XLOG_BLCKSZ, XLOG_BLCKSZ, NULL, NULL
+ XLOG_BLCKSZ, XLOG_BLCKSZ, XLOG_BLCKSZ,
+ NULL, NULL, NULL
},
{
@@ -2048,7 +2206,7 @@ static struct config_int ConfigureNamesInt[] =
(XLOG_SEG_SIZE / XLOG_BLCKSZ),
(XLOG_SEG_SIZE / XLOG_BLCKSZ),
(XLOG_SEG_SIZE / XLOG_BLCKSZ),
- NULL, NULL
+ NULL, NULL, NULL
},
{
@@ -2058,7 +2216,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_S
},
&autovacuum_naptime,
- 60, 1, INT_MAX / 1000, NULL, NULL
+ 60, 1, INT_MAX / 1000,
+ NULL, NULL, NULL
},
{
{"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
@@ -2066,7 +2225,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&autovacuum_vac_thresh,
- 50, 0, INT_MAX, NULL, NULL
+ 50, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
{"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
@@ -2074,7 +2234,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&autovacuum_anl_thresh,
- 50, 0, INT_MAX, NULL, NULL
+ 50, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
/* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
@@ -2084,7 +2245,8 @@ static struct config_int ConfigureNamesInt[] =
},
&autovacuum_freeze_max_age,
/* see pg_resetxlog if you change the upper-limit value */
- 200000000, 100000000, 2000000000, NULL, NULL
+ 200000000, 100000000, 2000000000,
+ NULL, NULL, NULL
},
{
/* see max_connections */
@@ -2093,7 +2255,8 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&autovacuum_max_workers,
- 3, 1, MAX_BACKENDS, assign_autovacuum_max_workers, NULL
+ 3, 1, MAX_BACKENDS,
+ check_autovacuum_max_workers, assign_autovacuum_max_workers, NULL
},
{
@@ -2103,7 +2266,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_S
},
&tcp_keepalives_idle,
- 0, 0, INT_MAX, assign_tcp_keepalives_idle, show_tcp_keepalives_idle
+ 0, 0, INT_MAX,
+ NULL, assign_tcp_keepalives_idle, show_tcp_keepalives_idle
},
{
@@ -2113,7 +2277,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_S
},
&tcp_keepalives_interval,
- 0, 0, INT_MAX, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
+ 0, 0, INT_MAX,
+ NULL, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
},
{
@@ -2123,7 +2288,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_KB,
},
&ssl_renegotiation_limit,
- 512 * 1024, 0, MAX_KILOBYTES, NULL, NULL
+ 512 * 1024, 0, MAX_KILOBYTES,
+ NULL, NULL, NULL
},
{
@@ -2134,7 +2300,8 @@ static struct config_int ConfigureNamesInt[] =
"system default."),
},
&tcp_keepalives_count,
- 0, 0, INT_MAX, assign_tcp_keepalives_count, show_tcp_keepalives_count
+ 0, 0, INT_MAX,
+ NULL, assign_tcp_keepalives_count, show_tcp_keepalives_count
},
{
@@ -2144,7 +2311,8 @@ static struct config_int ConfigureNamesInt[] =
0
},
&GinFuzzySearchLimit,
- 0, 0, INT_MAX, NULL, NULL
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -2156,7 +2324,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_BLOCKS,
},
&effective_cache_size,
- DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX, NULL, NULL
+ DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -2167,7 +2336,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&server_version_num,
- PG_VERSION_NUM, PG_VERSION_NUM, PG_VERSION_NUM, NULL, NULL
+ PG_VERSION_NUM, PG_VERSION_NUM, PG_VERSION_NUM,
+ NULL, NULL, NULL
},
{
@@ -2177,7 +2347,8 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_KB
},
&log_temp_files,
- -1, -1, INT_MAX, NULL, NULL
+ -1, -1, INT_MAX,
+ NULL, NULL, NULL
},
{
@@ -2186,12 +2357,13 @@ static struct config_int ConfigureNamesInt[] =
NULL,
},
&pgstat_track_activity_query_size,
- 1024, 100, 102400, NULL, NULL
+ 1024, 100, 102400,
+ NULL, NULL, NULL
},
/* End-of-list marker */
{
- {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
+ {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
}
};
@@ -2205,7 +2377,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&seq_page_cost,
- DEFAULT_SEQ_PAGE_COST, 0, DBL_MAX, NULL, NULL
+ DEFAULT_SEQ_PAGE_COST, 0, DBL_MAX,
+ NULL, NULL, NULL
},
{
{"random_page_cost", PGC_USERSET, QUERY_TUNING_COST,
@@ -2214,7 +2387,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&random_page_cost,
- DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX, NULL, NULL
+ DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX,
+ NULL, NULL, NULL
},
{
{"cpu_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
@@ -2223,7 +2397,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&cpu_tuple_cost,
- DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX, NULL, NULL
+ DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX,
+ NULL, NULL, NULL
},
{
{"cpu_index_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
@@ -2232,7 +2407,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&cpu_index_tuple_cost,
- DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX, NULL, NULL
+ DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX,
+ NULL, NULL, NULL
},
{
{"cpu_operator_cost", PGC_USERSET, QUERY_TUNING_COST,
@@ -2241,7 +2417,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&cpu_operator_cost,
- DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX, NULL, NULL
+ DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX,
+ NULL, NULL, NULL
},
{
@@ -2251,7 +2428,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&cursor_tuple_fraction,
- DEFAULT_CURSOR_TUPLE_FRACTION, 0.0, 1.0, NULL, NULL
+ DEFAULT_CURSOR_TUPLE_FRACTION, 0.0, 1.0,
+ NULL, NULL, NULL
},
{
@@ -2260,8 +2438,9 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&Geqo_selection_bias,
- DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS,
- MAX_GEQO_SELECTION_BIAS, NULL, NULL
+ DEFAULT_GEQO_SELECTION_BIAS,
+ MIN_GEQO_SELECTION_BIAS, MAX_GEQO_SELECTION_BIAS,
+ NULL, NULL, NULL
},
{
{"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
@@ -2269,7 +2448,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&Geqo_seed,
- 0.0, 0.0, 1.0, NULL, NULL
+ 0.0, 0.0, 1.0,
+ NULL, NULL, NULL
},
{
@@ -2278,7 +2458,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&bgwriter_lru_multiplier,
- 2.0, 0.0, 10.0, NULL, NULL
+ 2.0, 0.0, 10.0,
+ NULL, NULL, NULL
},
{
@@ -2288,7 +2469,8 @@ static struct config_real ConfigureNamesReal[] =
GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&phony_random_seed,
- 0.0, -1.0, 1.0, assign_random_seed, show_random_seed
+ 0.0, -1.0, 1.0,
+ check_random_seed, assign_random_seed, show_random_seed
},
{
@@ -2297,7 +2479,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&autovacuum_vac_scale,
- 0.2, 0.0, 100.0, NULL, NULL
+ 0.2, 0.0, 100.0,
+ NULL, NULL, NULL
},
{
{"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
@@ -2305,7 +2488,8 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&autovacuum_anl_scale,
- 0.1, 0.0, 100.0, NULL, NULL
+ 0.1, 0.0, 100.0,
+ NULL, NULL, NULL
},
{
@@ -2314,12 +2498,13 @@ static struct config_real ConfigureNamesReal[] =
NULL
},
&CheckPointCompletionTarget,
- 0.5, 0.0, 1.0, NULL, NULL
+ 0.5, 0.0, 1.0,
+ NULL, NULL, NULL
},
/* End-of-list marker */
{
- {NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL
+ {NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL, NULL
}
};
@@ -2332,7 +2517,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&XLogArchiveCommand,
- "", NULL, show_archive_command
+ "",
+ NULL, NULL, show_archive_command
},
{
@@ -2342,7 +2528,8 @@ static struct config_string ConfigureNamesString[] =
GUC_IS_NAME | GUC_REPORT
},
&client_encoding_string,
- "SQL_ASCII", assign_client_encoding, NULL
+ "SQL_ASCII",
+ check_client_encoding, assign_client_encoding, NULL
},
{
@@ -2351,7 +2538,8 @@ static struct config_string ConfigureNamesString[] =
gettext_noop("If blank, no prefix is used.")
},
&Log_line_prefix,
- "", NULL, NULL
+ "",
+ NULL, NULL, NULL
},
{
@@ -2360,7 +2548,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&log_timezone_string,
- "UNKNOWN", assign_log_timezone, show_log_timezone
+ NULL,
+ check_log_timezone, assign_log_timezone, show_log_timezone
},
{
@@ -2371,7 +2560,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT | GUC_REPORT
},
&datestyle_string,
- "ISO, MDY", assign_datestyle, NULL
+ "ISO, MDY",
+ check_datestyle, assign_datestyle, NULL
},
{
@@ -2381,7 +2571,8 @@ static struct config_string ConfigureNamesString[] =
GUC_IS_NAME
},
&default_tablespace,
- "", assign_default_tablespace, NULL
+ "",
+ check_default_tablespace, NULL, NULL
},
{
@@ -2391,7 +2582,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT | GUC_LIST_QUOTE
},
&temp_tablespaces,
- "", assign_temp_tablespaces, NULL
+ "",
+ check_temp_tablespaces, assign_temp_tablespaces, NULL
},
{
@@ -2404,7 +2596,8 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&Dynamic_library_path,
- "$libdir", NULL, NULL
+ "$libdir",
+ NULL, NULL, NULL
},
{
@@ -2414,7 +2607,8 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&pg_krb_server_keyfile,
- PG_KRB_SRVTAB, NULL, NULL
+ PG_KRB_SRVTAB,
+ NULL, NULL, NULL
},
{
@@ -2423,7 +2617,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&pg_krb_srvnam,
- PG_KRB_SRVNAM, NULL, NULL
+ PG_KRB_SRVNAM,
+ NULL, NULL, NULL
},
{
@@ -2432,7 +2627,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&bonjour_name,
- "", NULL, NULL
+ "",
+ NULL, NULL, NULL
},
/* See main.c about why defaults for LC_foo are not all alike */
@@ -2444,7 +2640,8 @@ static struct config_string ConfigureNamesString[] =
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&locale_collate,
- "C", NULL, NULL
+ "C",
+ NULL, NULL, NULL
},
{
@@ -2454,7 +2651,8 @@ static struct config_string ConfigureNamesString[] =
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&locale_ctype,
- "C", NULL, NULL
+ "C",
+ NULL, NULL, NULL
},
{
@@ -2463,7 +2661,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&locale_messages,
- "", locale_messages_assign, NULL
+ "",
+ check_locale_messages, assign_locale_messages, NULL
},
{
@@ -2472,7 +2671,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&locale_monetary,
- "C", locale_monetary_assign, NULL
+ "C",
+ check_locale_monetary, assign_locale_monetary, NULL
},
{
@@ -2481,7 +2681,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&locale_numeric,
- "C", locale_numeric_assign, NULL
+ "C",
+ check_locale_numeric, assign_locale_numeric, NULL
},
{
@@ -2490,7 +2691,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&locale_time,
- "C", locale_time_assign, NULL
+ "C",
+ check_locale_time, assign_locale_time, NULL
},
{
@@ -2500,7 +2702,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
},
&shared_preload_libraries_string,
- "", NULL, NULL
+ "",
+ NULL, NULL, NULL
},
{
@@ -2510,7 +2713,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT | GUC_LIST_QUOTE
},
&local_preload_libraries_string,
- "", NULL, NULL
+ "",
+ NULL, NULL, NULL
},
{
@@ -2520,7 +2724,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT | GUC_LIST_QUOTE
},
&namespace_search_path,
- "\"$user\",public", assign_search_path, NULL
+ "\"$user\",public",
+ check_search_path, assign_search_path, NULL
},
{
@@ -2531,7 +2736,8 @@ static struct config_string ConfigureNamesString[] =
GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&server_encoding_string,
- "SQL_ASCII", NULL, NULL
+ "SQL_ASCII",
+ NULL, NULL, NULL
},
{
@@ -2542,7 +2748,8 @@ static struct config_string ConfigureNamesString[] =
GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&server_version_string,
- PG_VERSION, NULL, NULL
+ PG_VERSION,
+ NULL, NULL, NULL
},
{
@@ -2553,7 +2760,8 @@ static struct config_string ConfigureNamesString[] =
GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
},
&role_string,
- "none", assign_role, show_role
+ "none",
+ check_role, assign_role, show_role
},
{
@@ -2564,7 +2772,8 @@ static struct config_string ConfigureNamesString[] =
GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
},
&session_authorization_string,
- NULL, assign_session_authorization, show_session_authorization
+ NULL,
+ check_session_authorization, assign_session_authorization, NULL
},
{
@@ -2576,7 +2785,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT
},
&log_destination_string,
- "stderr", assign_log_destination, NULL
+ "stderr",
+ check_log_destination, assign_log_destination, NULL
},
{
{"log_directory", PGC_SIGHUP, LOGGING_WHERE,
@@ -2586,7 +2796,8 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&Log_directory,
- "pg_log", assign_canonical_path, NULL
+ "pg_log",
+ check_canonical_path, NULL, NULL
},
{
{"log_filename", PGC_SIGHUP, LOGGING_WHERE,
@@ -2595,7 +2806,8 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&Log_filename,
- "postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL
+ "postgresql-%Y-%m-%d_%H%M%S.log",
+ NULL, NULL, NULL
},
{
@@ -2605,7 +2817,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&syslog_ident_str,
- "postgres", assign_syslog_ident, NULL
+ "postgres",
+ NULL, assign_syslog_ident, NULL
},
{
@@ -2615,7 +2828,8 @@ static struct config_string ConfigureNamesString[] =
GUC_REPORT
},
&timezone_string,
- "UNKNOWN", assign_timezone, show_timezone
+ NULL,
+ check_timezone, assign_timezone, show_timezone
},
{
{"timezone_abbreviations", PGC_USERSET, CLIENT_CONN_LOCALE,
@@ -2623,7 +2837,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&timezone_abbreviations_string,
- "UNKNOWN", assign_timezone_abbreviations, NULL
+ NULL,
+ check_timezone_abbreviations, assign_timezone_abbreviations, NULL
},
{
@@ -2633,7 +2848,8 @@ static struct config_string ConfigureNamesString[] =
GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&XactIsoLevel_string,
- NULL, assign_XactIsoLevel, show_XactIsoLevel
+ "default",
+ check_XactIsoLevel, assign_XactIsoLevel, show_XactIsoLevel
},
{
@@ -2643,7 +2859,8 @@ static struct config_string ConfigureNamesString[] =
"that starts the server.")
},
&Unix_socket_group,
- "", NULL, NULL
+ "",
+ NULL, NULL, NULL
},
{
@@ -2653,7 +2870,8 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&UnixSocketDir,
- "", assign_canonical_path, NULL
+ "",
+ check_canonical_path, NULL, NULL
},
{
@@ -2663,7 +2881,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT
},
&ListenAddresses,
- "localhost", NULL, NULL
+ "localhost",
+ NULL, NULL, NULL
},
{
@@ -2673,7 +2892,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT | GUC_LIST_QUOTE
},
&custom_variable_classes,
- NULL, assign_custom_variable_classes, NULL
+ NULL,
+ check_custom_variable_classes, NULL, NULL
},
{
@@ -2683,6 +2903,7 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&data_directory,
+ NULL,
NULL, NULL, NULL
},
@@ -2693,6 +2914,7 @@ static struct config_string ConfigureNamesString[] =
GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
},
&ConfigFileName,
+ NULL,
NULL, NULL, NULL
},
@@ -2703,6 +2925,7 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&HbaFileName,
+ NULL,
NULL, NULL, NULL
},
@@ -2713,6 +2936,7 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&IdentFileName,
+ NULL,
NULL, NULL, NULL
},
@@ -2723,7 +2947,8 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&external_pid_file,
- NULL, assign_canonical_path, NULL
+ NULL,
+ check_canonical_path, NULL, NULL
},
{
@@ -2733,7 +2958,8 @@ static struct config_string ConfigureNamesString[] =
GUC_SUPERUSER_ONLY
},
&pgstat_temp_directory,
- "pg_stat_tmp", assign_pgstat_temp_directory, NULL
+ "pg_stat_tmp",
+ check_canonical_path, assign_pgstat_temp_directory, NULL
},
{
@@ -2743,7 +2969,8 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT
},
&SyncRepStandbyNames,
- "", assign_synchronous_standby_names, NULL
+ "",
+ check_synchronous_standby_names, NULL, NULL
},
{
@@ -2752,7 +2979,8 @@ static struct config_string ConfigureNamesString[] =
NULL
},
&TSCurrentConfig,
- "pg_catalog.simple", assignTSCurrentConfig, NULL
+ "pg_catalog.simple",
+ check_TSCurrentConfig, assign_TSCurrentConfig, NULL
},
{
@@ -2767,7 +2995,7 @@ static struct config_string ConfigureNamesString[] =
#else
"none",
#endif
- NULL, NULL
+ NULL, NULL, NULL
},
{
@@ -2777,12 +3005,13 @@ static struct config_string ConfigureNamesString[] =
GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE
},
&application_name,
- "", assign_application_name, NULL
+ "",
+ check_application_name, assign_application_name, NULL
},
/* End-of-list marker */
{
- {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
+ {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
}
};
@@ -2795,7 +3024,8 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&backslash_quote,
- BACKSLASH_QUOTE_SAFE_ENCODING, backslash_quote_options, NULL, NULL
+ BACKSLASH_QUOTE_SAFE_ENCODING, backslash_quote_options,
+ NULL, NULL, NULL
},
{
@@ -2804,7 +3034,8 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&bytea_output,
- BYTEA_OUTPUT_HEX, bytea_output_options, NULL, NULL
+ BYTEA_OUTPUT_HEX, bytea_output_options,
+ NULL, NULL, NULL
},
{
@@ -2814,7 +3045,8 @@ static struct config_enum ConfigureNamesEnum[] =
" the level, the fewer messages are sent.")
},
&client_min_messages,
- NOTICE, client_message_level_options, NULL, NULL
+ NOTICE, client_message_level_options,
+ NULL, NULL, NULL
},
{
@@ -2825,7 +3057,7 @@ static struct config_enum ConfigureNamesEnum[] =
},
&constraint_exclusion,
CONSTRAINT_EXCLUSION_PARTITION, constraint_exclusion_options,
- NULL, NULL
+ NULL, NULL, NULL
},
{
@@ -2834,7 +3066,8 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&DefaultXactIsoLevel,
- XACT_READ_COMMITTED, isolation_level_options, NULL, NULL
+ XACT_READ_COMMITTED, isolation_level_options,
+ NULL, NULL, NULL
},
{
@@ -2844,7 +3077,8 @@ static struct config_enum ConfigureNamesEnum[] =
GUC_REPORT
},
&IntervalStyle,
- INTSTYLE_POSTGRES, intervalstyle_options, NULL, NULL
+ INTSTYLE_POSTGRES, intervalstyle_options,
+ NULL, NULL, NULL
},
{
@@ -2853,7 +3087,8 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&Log_error_verbosity,
- PGERROR_DEFAULT, log_error_verbosity_options, NULL, NULL
+ PGERROR_DEFAULT, log_error_verbosity_options,
+ NULL, NULL, NULL
},
{
@@ -2863,7 +3098,8 @@ static struct config_enum ConfigureNamesEnum[] =
" the level, the fewer messages are sent.")
},
&log_min_messages,
- WARNING, server_message_level_options, NULL, NULL
+ WARNING, server_message_level_options,
+ NULL, NULL, NULL
},
{
@@ -2873,7 +3109,8 @@ static struct config_enum ConfigureNamesEnum[] =
" the level, the fewer messages are sent.")
},
&log_min_error_statement,
- ERROR, server_message_level_options, NULL, NULL
+ ERROR, server_message_level_options,
+ NULL, NULL, NULL
},
{
@@ -2882,7 +3119,8 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&log_statement,
- LOGSTMT_NONE, log_statement_options, NULL, NULL
+ LOGSTMT_NONE, log_statement_options,
+ NULL, NULL, NULL
},
{
@@ -2896,7 +3134,8 @@ static struct config_enum ConfigureNamesEnum[] =
#else
0,
#endif
- syslog_facility_options, assign_syslog_facility, NULL
+ syslog_facility_options,
+ NULL, assign_syslog_facility, NULL
},
{
@@ -2906,7 +3145,7 @@ static struct config_enum ConfigureNamesEnum[] =
},
&SessionReplicationRole,
SESSION_REPLICATION_ROLE_ORIGIN, session_replication_role_options,
- assign_session_replication_role, NULL
+ NULL, assign_session_replication_role, NULL
},
{
@@ -2916,7 +3155,7 @@ static struct config_enum ConfigureNamesEnum[] =
},
&synchronous_commit,
SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
- NULL, NULL
+ NULL, NULL, NULL
},
{
@@ -2930,7 +3169,8 @@ static struct config_enum ConfigureNamesEnum[] =
* client_message_level_options allows too many values, really,
* but it's not worth having a separate options array for this.
*/
- LOG, client_message_level_options, NULL, NULL
+ LOG, client_message_level_options,
+ NULL, NULL, NULL
},
{
@@ -2939,7 +3179,8 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&pgstat_track_functions,
- TRACK_FUNC_OFF, track_function_options, NULL, NULL
+ TRACK_FUNC_OFF, track_function_options,
+ NULL, NULL, NULL
},
{
@@ -2948,7 +3189,8 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&wal_level,
- WAL_LEVEL_MINIMAL, wal_level_options, NULL
+ WAL_LEVEL_MINIMAL, wal_level_options,
+ NULL, NULL, NULL
},
{
@@ -2958,7 +3200,7 @@ static struct config_enum ConfigureNamesEnum[] =
},
&sync_method,
DEFAULT_SYNC_METHOD, sync_method_options,
- assign_xlog_sync_method, NULL
+ NULL, assign_xlog_sync_method, NULL
},
{
@@ -2967,7 +3209,8 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&xmlbinary,
- XMLBINARY_BASE64, xmlbinary_options, NULL, NULL
+ XMLBINARY_BASE64, xmlbinary_options,
+ NULL, NULL, NULL
},
{
@@ -2977,13 +3220,14 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&xmloption,
- XMLOPTION_CONTENT, xmloption_options, NULL, NULL
+ XMLOPTION_CONTENT, xmloption_options,
+ NULL, NULL, NULL
},
/* End-of-list marker */
{
- {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL
+ {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
}
};
@@ -3030,7 +3274,6 @@ 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 validate_option_array_item(const char *name, const char *value,
bool skipIfNoPermissions);
@@ -3079,6 +3322,27 @@ guc_strdup(int elevel, const char *src)
/*
+ * Detect whether strval is referenced anywhere in a GUC string item
+ */
+static bool
+string_field_used(struct config_string * conf, char *strval)
+{
+ GucStack *stack;
+
+ if (strval == *(conf->variable) ||
+ strval == conf->reset_val ||
+ strval == conf->boot_val)
+ return true;
+ for (stack = conf->gen.stack; stack; stack = stack->prev)
+ {
+ if (strval == stack->prior.val.stringval ||
+ strval == stack->masked.val.stringval)
+ return true;
+ }
+ return false;
+}
+
+/*
* Support for assigning to a field of a string GUC item. Free the prior
* value if it's not referenced anywhere else in the item (including stacked
* states).
@@ -3087,87 +3351,119 @@ static void
set_string_field(struct config_string * conf, char **field, char *newval)
{
char *oldval = *field;
- GucStack *stack;
/* Do the assignment */
*field = newval;
- /* Exit if any duplicate references, or if old value was NULL anyway */
- if (oldval == NULL ||
- oldval == *(conf->variable) ||
- oldval == conf->reset_val ||
- oldval == conf->boot_val)
- return;
- for (stack = conf->gen.stack; stack; stack = stack->prev)
- {
- if (oldval == stack->prior.stringval ||
- oldval == stack->masked.stringval)
- return;
- }
-
- /* Not used anymore, so free it */
- free(oldval);
+ /* Free old value if it's not NULL and isn't referenced anymore */
+ if (oldval && !string_field_used(conf, oldval))
+ free(oldval);
}
/*
- * Detect whether strval is referenced anywhere in a GUC string item
+ * Detect whether an "extra" struct is referenced anywhere in a GUC item
*/
static bool
-string_field_used(struct config_string * conf, char *strval)
+extra_field_used(struct config_generic * gconf, void *extra)
{
GucStack *stack;
- if (strval == *(conf->variable) ||
- strval == conf->reset_val ||
- strval == conf->boot_val)
+ if (extra == gconf->extra)
return true;
- for (stack = conf->gen.stack; stack; stack = stack->prev)
+ switch (gconf->vartype)
+ {
+ case PGC_BOOL:
+ if (extra == ((struct config_bool *) gconf)->reset_extra)
+ return true;
+ break;
+ case PGC_INT:
+ if (extra == ((struct config_int *) gconf)->reset_extra)
+ return true;
+ break;
+ case PGC_REAL:
+ if (extra == ((struct config_real *) gconf)->reset_extra)
+ return true;
+ break;
+ case PGC_STRING:
+ if (extra == ((struct config_string *) gconf)->reset_extra)
+ return true;
+ break;
+ case PGC_ENUM:
+ if (extra == ((struct config_enum *) gconf)->reset_extra)
+ return true;
+ break;
+ }
+ for (stack = gconf->stack; stack; stack = stack->prev)
{
- if (strval == stack->prior.stringval ||
- strval == stack->masked.stringval)
+ if (extra == stack->prior.extra ||
+ extra == stack->masked.extra)
return true;
}
+
return false;
}
/*
- * Support for copying a variable's active value into a stack entry
+ * Support for assigning to an "extra" field of a GUC item. Free the prior
+ * value if it's not referenced anywhere else in the item (including stacked
+ * states).
*/
static void
-set_stack_value(struct config_generic * gconf, union config_var_value * val)
+set_extra_field(struct config_generic * gconf, void **field, void *newval)
+{
+ void *oldval = *field;
+
+ /* Do the assignment */
+ *field = newval;
+
+ /* Free old value if it's not NULL and isn't referenced anymore */
+ if (oldval && !extra_field_used(gconf, oldval))
+ free(oldval);
+}
+
+/*
+ * Support for copying a variable's active value into a stack entry.
+ * The "extra" field associated with the active value is copied, too.
+ *
+ * NB: be sure stringval and extra fields of a new stack entry are
+ * initialized to NULL before this is used, else we'll try to free() them.
+ */
+static void
+set_stack_value(struct config_generic * gconf, config_var_value *val)
{
switch (gconf->vartype)
{
case PGC_BOOL:
- val->boolval =
+ val->val.boolval =
*((struct config_bool *) gconf)->variable;
break;
case PGC_INT:
- val->intval =
+ val->val.intval =
*((struct config_int *) gconf)->variable;
break;
case PGC_REAL:
- val->realval =
+ val->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),
+ &(val->val.stringval),
*((struct config_string *) gconf)->variable);
break;
case PGC_ENUM:
- val->enumval =
+ val->val.enumval =
*((struct config_enum *) gconf)->variable;
break;
}
+ set_extra_field(gconf, &(val->extra), gconf->extra);
}
/*
- * Support for discarding a no-longer-needed value in a stack entry
+ * Support for discarding a no-longer-needed value in a stack entry.
+ * The "extra" field associated with the stack entry is cleared, too.
*/
static void
-discard_stack_value(struct config_generic * gconf, union config_var_value * val)
+discard_stack_value(struct config_generic * gconf, config_var_value *val)
{
switch (gconf->vartype)
{
@@ -3179,10 +3475,11 @@ discard_stack_value(struct config_generic * gconf, union config_var_value * val)
break;
case PGC_STRING:
set_string_field((struct config_string *) gconf,
- &(val->stringval),
+ &(val->val.stringval),
NULL);
break;
}
+ set_extra_field(gconf, &(val->extra), NULL);
}
@@ -3594,6 +3891,9 @@ InitializeGUCOptions(void)
/*
* Initialize one GUC option variable to its compiled-in default.
+ *
+ * Note: the reason for calling check_hooks is not that we think the boot_val
+ * might fail, but that the hooks might wish to compute an "extra" struct.
*/
static void
InitializeOneGUCOption(struct config_generic * gconf)
@@ -3602,6 +3902,7 @@ InitializeOneGUCOption(struct config_generic * gconf)
gconf->reset_source = PGC_S_DEFAULT;
gconf->source = PGC_S_DEFAULT;
gconf->stack = NULL;
+ gconf->extra = NULL;
gconf->sourcefile = NULL;
gconf->sourceline = 0;
@@ -3610,96 +3911,91 @@ InitializeOneGUCOption(struct config_generic * gconf)
case PGC_BOOL:
{
struct config_bool *conf = (struct config_bool *) gconf;
+ bool newval = conf->boot_val;
+ void *extra = NULL;
+ if (!call_bool_check_hook(conf, &newval, &extra,
+ PGC_S_DEFAULT, LOG))
+ elog(FATAL, "failed to initialize %s to %d",
+ conf->gen.name, (int) newval);
if (conf->assign_hook)
- if (!(*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;
+ (*conf->assign_hook) (newval, extra);
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
break;
}
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
-
- Assert(conf->boot_val >= conf->min);
- Assert(conf->boot_val <= conf->max);
+ int newval = conf->boot_val;
+ void *extra = NULL;
+
+ Assert(newval >= conf->min);
+ Assert(newval <= conf->max);
+ if (!call_int_check_hook(conf, &newval, &extra,
+ PGC_S_DEFAULT, LOG))
+ elog(FATAL, "failed to initialize %s to %d",
+ conf->gen.name, newval);
if (conf->assign_hook)
- if (!(*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;
+ (*conf->assign_hook) (newval, extra);
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
break;
}
case PGC_REAL:
{
struct config_real *conf = (struct config_real *) gconf;
-
- Assert(conf->boot_val >= conf->min);
- Assert(conf->boot_val <= conf->max);
+ double newval = conf->boot_val;
+ void *extra = NULL;
+
+ Assert(newval >= conf->min);
+ Assert(newval <= conf->max);
+ if (!call_real_check_hook(conf, &newval, &extra,
+ PGC_S_DEFAULT, LOG))
+ elog(FATAL, "failed to initialize %s to %g",
+ conf->gen.name, newval);
if (conf->assign_hook)
- if (!(*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;
+ (*conf->assign_hook) (newval, extra);
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
break;
}
case PGC_STRING:
{
struct config_string *conf = (struct config_string *) gconf;
- char *str;
-
- *conf->variable = NULL;
- conf->reset_val = NULL;
-
- if (conf->boot_val == NULL)
- {
- /* leave the value NULL, do not call assign hook */
- break;
- }
+ char *newval;
+ void *extra = NULL;
- str = guc_strdup(FATAL, conf->boot_val);
- conf->reset_val = str;
+ /* non-NULL boot_val must always get strdup'd */
+ if (conf->boot_val != NULL)
+ newval = guc_strdup(FATAL, conf->boot_val);
+ else
+ newval = NULL;
+ if (!call_string_check_hook(conf, &newval, &extra,
+ PGC_S_DEFAULT, LOG))
+ elog(FATAL, "failed to initialize %s to \"%s\"",
+ conf->gen.name, newval ? newval : "");
if (conf->assign_hook)
- {
- const char *newstr;
-
- 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);
-
- /*
- * See notes in set_config_option about casting
- */
- str = (char *) newstr;
- conf->reset_val = str;
- }
- }
- *conf->variable = str;
+ (*conf->assign_hook) (newval, extra);
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
break;
}
case PGC_ENUM:
{
struct config_enum *conf = (struct config_enum *) gconf;
+ int newval = conf->boot_val;
+ void *extra = NULL;
+ if (!call_enum_check_hook(conf, &newval, &extra,
+ PGC_S_DEFAULT, LOG))
+ elog(FATAL, "failed to initialize %s to %d",
+ conf->gen.name, newval);
if (conf->assign_hook)
- if (!(*conf->assign_hook) (conf->boot_val, true,
- PGC_S_DEFAULT))
- elog(FATAL, "failed to initialize %s to %s",
- conf->gen.name,
- config_enum_lookup_by_value(conf, conf->boot_val));
- *conf->variable = conf->reset_val = conf->boot_val;
+ (*conf->assign_hook) (newval, extra);
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
break;
}
}
@@ -3888,11 +4184,11 @@ ResetAllOptions(void)
struct config_bool *conf = (struct config_bool *) gconf;
if (conf->assign_hook)
- if (!(*conf->assign_hook) (conf->reset_val, true,
- PGC_S_SESSION))
- elog(ERROR, "failed to reset %s to %d",
- conf->gen.name, (int) conf->reset_val);
+ (*conf->assign_hook) (conf->reset_val,
+ conf->reset_extra);
*conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
break;
}
case PGC_INT:
@@ -3900,11 +4196,11 @@ ResetAllOptions(void)
struct config_int *conf = (struct config_int *) gconf;
if (conf->assign_hook)
- if (!(*conf->assign_hook) (conf->reset_val, true,
- PGC_S_SESSION))
- elog(ERROR, "failed to reset %s to %d",
- conf->gen.name, conf->reset_val);
+ (*conf->assign_hook) (conf->reset_val,
+ conf->reset_extra);
*conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
break;
}
case PGC_REAL:
@@ -3912,40 +4208,23 @@ ResetAllOptions(void)
struct config_real *conf = (struct config_real *) gconf;
if (conf->assign_hook)
- if (!(*conf->assign_hook) (conf->reset_val, true,
- PGC_S_SESSION))
- elog(ERROR, "failed to reset %s to %g",
- conf->gen.name, conf->reset_val);
+ (*conf->assign_hook) (conf->reset_val,
+ conf->reset_extra);
*conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
break;
}
case PGC_STRING:
{
struct config_string *conf = (struct config_string *) gconf;
- char *str;
-
- /* We need not strdup here */
- str = conf->reset_val;
-
- if (conf->assign_hook && str)
- {
- const char *newstr;
-
- newstr = (*conf->assign_hook) (str, true,
- PGC_S_SESSION);
- if (newstr == NULL)
- elog(ERROR, "failed to reset %s to \"%s\"",
- conf->gen.name, str);
- else if (newstr != str)
- {
- /*
- * See notes in set_config_option about casting
- */
- str = (char *) newstr;
- }
- }
- set_string_field(conf, conf->variable, str);
+ if (conf->assign_hook)
+ (*conf->assign_hook) (conf->reset_val,
+ conf->reset_extra);
+ set_string_field(conf, conf->variable, conf->reset_val);
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
break;
}
case PGC_ENUM:
@@ -3953,12 +4232,11 @@ ResetAllOptions(void)
struct config_enum *conf = (struct config_enum *) gconf;
if (conf->assign_hook)
- if (!(*conf->assign_hook) (conf->reset_val, true,
- PGC_S_SESSION))
- elog(ERROR, "failed to reset %s to %s",
- conf->gen.name,
- config_enum_lookup_by_value(conf, conf->reset_val));
+ (*conf->assign_hook) (conf->reset_val,
+ conf->reset_extra);
*conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
break;
}
}
@@ -4209,7 +4487,7 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
if (restorePrior || restoreMasked)
{
/* Perform appropriate restoration of the stacked value */
- union config_var_value newvalue;
+ config_var_value newvalue;
GucSource newsource;
if (restoreMasked)
@@ -4228,16 +4506,17 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
case PGC_BOOL:
{
struct config_bool *conf = (struct config_bool *) gconf;
- bool newval = newvalue.boolval;
+ bool newval = newvalue.val.boolval;
+ void *newextra = newvalue.extra;
- if (*conf->variable != newval)
+ if (*conf->variable != newval ||
+ conf->gen.extra != newextra)
{
if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval,
- true, PGC_S_OVERRIDE))
- elog(LOG, "failed to commit %s as %d",
- conf->gen.name, (int) newval);
+ (*conf->assign_hook) (newval, newextra);
*conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
changed = true;
}
break;
@@ -4245,16 +4524,17 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
- int newval = newvalue.intval;
+ int newval = newvalue.val.intval;
+ void *newextra = newvalue.extra;
- if (*conf->variable != newval)
+ if (*conf->variable != newval ||
+ conf->gen.extra != newextra)
{
if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval,
- true, PGC_S_OVERRIDE))
- elog(LOG, "failed to commit %s as %d",
- conf->gen.name, newval);
+ (*conf->assign_hook) (newval, newextra);
*conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
changed = true;
}
break;
@@ -4262,16 +4542,17 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
case PGC_REAL:
{
struct config_real *conf = (struct config_real *) gconf;
- double newval = newvalue.realval;
+ double newval = newvalue.val.realval;
+ void *newextra = newvalue.extra;
- if (*conf->variable != newval)
+ if (*conf->variable != newval ||
+ conf->gen.extra != newextra)
{
if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval,
- true, PGC_S_OVERRIDE))
- elog(LOG, "failed to commit %s as %g",
- conf->gen.name, newval);
+ (*conf->assign_hook) (newval, newextra);
*conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
changed = true;
}
break;
@@ -4279,33 +4560,17 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
case PGC_STRING:
{
struct config_string *conf = (struct config_string *) gconf;
- char *newval = newvalue.stringval;
+ char *newval = newvalue.val.stringval;
+ void *newextra = newvalue.extra;
- if (*conf->variable != newval)
+ if (*conf->variable != newval ||
+ conf->gen.extra != newextra)
{
- 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 as \"%s\"",
- conf->gen.name, newval);
- 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;
- }
- }
-
+ if (conf->assign_hook)
+ (*conf->assign_hook) (newval, newextra);
set_string_field(conf, conf->variable, newval);
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
changed = true;
}
@@ -4315,30 +4580,36 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
* 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);
+ set_string_field(conf, &stack->prior.val.stringval, NULL);
+ set_string_field(conf, &stack->masked.val.stringval, NULL);
break;
}
case PGC_ENUM:
{
struct config_enum *conf = (struct config_enum *) gconf;
- int newval = newvalue.enumval;
+ int newval = newvalue.val.enumval;
+ void *newextra = newvalue.extra;
- if (*conf->variable != newval)
+ if (*conf->variable != newval ||
+ conf->gen.extra != newextra)
{
if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval,
- true, PGC_S_OVERRIDE))
- elog(LOG, "failed to commit %s as %s",
- conf->gen.name,
- config_enum_lookup_by_value(conf, newval));
+ (*conf->assign_hook) (newval, newextra);
*conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
changed = true;
}
break;
}
}
+ /*
+ * Release stacked extra values if not used anymore.
+ */
+ set_extra_field(gconf, &(stack->prior.extra), NULL);
+ set_extra_field(gconf, &(stack->masked.extra), NULL);
+
gconf->source = newsource;
}
@@ -4748,33 +5019,6 @@ config_enum_get_options(struct config_enum * record, const char *prefix,
return retstr.data;
}
-/*
- * Call a GucStringAssignHook function, being careful to free the
- * "newval" string if the hook ereports.
- *
- * This is split out of set_config_option just to avoid the "volatile"
- * qualifiers that would otherwise have to be plastered all over.
- */
-static const char *
-call_string_assign_hook(GucStringAssignHook assign_hook,
- char *newval, bool doit, GucSource source)
-{
- const char *result;
-
- PG_TRY();
- {
- result = (*assign_hook) (newval, doit, source);
- }
- PG_CATCH();
- {
- free(newval);
- PG_RE_THROW();
- }
- PG_END_TRY();
-
- return result;
-}
-
/*
* Sets option `name' to given value. The value should be a string
@@ -4810,6 +5054,7 @@ set_config_option(const char *name, const char *value,
{
struct config_generic *record;
int elevel;
+ bool prohibitValueChange = false;
bool makeDefault;
if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
@@ -4846,15 +5091,21 @@ set_config_option(const char *name, const char *value,
/*
* Check if the option can be set at this time. See guc.h for the precise
- * rules. Note that we don't want to throw errors if we're in the SIGHUP
- * context. In that case we just ignore the attempt and return true.
+ * rules.
*/
switch (record->context)
{
case PGC_INTERNAL:
if (context == PGC_SIGHUP)
+ {
+ /*
+ * Historically we've just silently ignored attempts to set
+ * PGC_INTERNAL variables from the config file. Maybe it'd
+ * be better to use the prohibitValueChange logic for this?
+ */
return true;
- if (context != PGC_INTERNAL)
+ }
+ else if (context != PGC_INTERNAL)
{
ereport(elevel,
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
@@ -4867,19 +5118,23 @@ set_config_option(const char *name, const char *value,
if (context == PGC_SIGHUP)
{
/*
- * 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
- * consistent, but seems overly rigid.)
+ * We are re-reading a PGC_POSTMASTER variable from
+ * postgresql.conf. We can't change the setting, so we should
+ * give a warning if the DBA tries to change it. However,
+ * because of variant formats, canonicalization by check
+ * hooks, etc, we can't just compare the given string directly
+ * to what's stored. Set a flag to check below after we have
+ * the final storable value.
+ *
+ * During the "checking" pass we just do nothing, to avoid
+ * printing the warning twice.
*/
- if (changeVal && !is_newvalue_equal(record, value))
- ereport(elevel,
- (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
- errmsg("parameter \"%s\" cannot be changed without restarting the server",
- name)));
- return true;
+ if (!changeVal)
+ return true;
+
+ prohibitValueChange = true;
}
- if (context != PGC_POSTMASTER)
+ else if (context != PGC_POSTMASTER)
{
ereport(elevel,
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
@@ -5022,6 +5277,7 @@ set_config_option(const char *name, const char *value,
{
struct config_bool *conf = (struct config_bool *) record;
bool newval;
+ void *newextra = NULL;
if (value)
{
@@ -5033,32 +5289,45 @@ set_config_option(const char *name, const char *value,
name)));
return false;
}
+ if (!call_bool_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ return false;
}
else if (source == PGC_S_DEFAULT)
+ {
newval = conf->boot_val;
+ if (!call_bool_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ return false;
+ }
else
{
newval = conf->reset_val;
+ newextra = conf->reset_extra;
source = conf->gen.reset_source;
}
- /* Save old value to support transaction abort */
- if (changeVal && !makeDefault)
- push_old_value(&conf->gen, action);
-
- if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval, changeVal, source))
- {
+ if (prohibitValueChange)
+ {
+ if (*conf->variable != newval)
ereport(elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for parameter \"%s\": %d",
- name, (int) newval)));
- return false;
- }
+ (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+ errmsg("parameter \"%s\" cannot be changed without restarting the server",
+ name)));
+ return false;
+ }
if (changeVal)
{
+ /* Save old value to support transaction abort */
+ if (!makeDefault)
+ push_old_value(&conf->gen, action);
+
+ if (conf->assign_hook)
+ (*conf->assign_hook) (newval, newextra);
*conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
conf->gen.source = source;
}
if (makeDefault)
@@ -5068,17 +5337,25 @@ set_config_option(const char *name, const char *value,
if (conf->gen.reset_source <= source)
{
conf->reset_val = newval;
+ set_extra_field(&conf->gen, &conf->reset_extra,
+ newextra);
conf->gen.reset_source = source;
}
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
if (stack->source <= source)
{
- stack->prior.boolval = newval;
+ stack->prior.val.boolval = newval;
+ set_extra_field(&conf->gen, &stack->prior.extra,
+ newextra);
stack->source = source;
}
}
}
+
+ /* Perhaps we didn't install newextra anywhere */
+ if (newextra && !extra_field_used(&conf->gen, newextra))
+ free(newextra);
break;
}
@@ -5086,6 +5363,7 @@ set_config_option(const char *name, const char *value,
{
struct config_int *conf = (struct config_int *) record;
int newval;
+ void *newextra = NULL;
if (value)
{
@@ -5108,32 +5386,45 @@ set_config_option(const char *name, const char *value,
newval, name, conf->min, conf->max)));
return false;
}
+ if (!call_int_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ return false;
}
else if (source == PGC_S_DEFAULT)
+ {
newval = conf->boot_val;
+ if (!call_int_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ return false;
+ }
else
{
newval = conf->reset_val;
+ newextra = conf->reset_extra;
source = conf->gen.reset_source;
}
- /* Save old value to support transaction abort */
- if (changeVal && !makeDefault)
- push_old_value(&conf->gen, action);
-
- if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval, changeVal, source))
- {
+ if (prohibitValueChange)
+ {
+ if (*conf->variable != newval)
ereport(elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for parameter \"%s\": %d",
- name, newval)));
- return false;
- }
+ (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+ errmsg("parameter \"%s\" cannot be changed without restarting the server",
+ name)));
+ return false;
+ }
if (changeVal)
{
+ /* Save old value to support transaction abort */
+ if (!makeDefault)
+ push_old_value(&conf->gen, action);
+
+ if (conf->assign_hook)
+ (*conf->assign_hook) (newval, newextra);
*conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
conf->gen.source = source;
}
if (makeDefault)
@@ -5143,17 +5434,25 @@ set_config_option(const char *name, const char *value,
if (conf->gen.reset_source <= source)
{
conf->reset_val = newval;
+ set_extra_field(&conf->gen, &conf->reset_extra,
+ newextra);
conf->gen.reset_source = source;
}
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
if (stack->source <= source)
{
- stack->prior.intval = newval;
+ stack->prior.val.intval = newval;
+ set_extra_field(&conf->gen, &stack->prior.extra,
+ newextra);
stack->source = source;
}
}
}
+
+ /* Perhaps we didn't install newextra anywhere */
+ if (newextra && !extra_field_used(&conf->gen, newextra))
+ free(newextra);
break;
}
@@ -5161,6 +5460,7 @@ set_config_option(const char *name, const char *value,
{
struct config_real *conf = (struct config_real *) record;
double newval;
+ void *newextra = NULL;
if (value)
{
@@ -5180,32 +5480,45 @@ set_config_option(const char *name, const char *value,
newval, name, conf->min, conf->max)));
return false;
}
+ if (!call_real_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ return false;
}
else if (source == PGC_S_DEFAULT)
+ {
newval = conf->boot_val;
+ if (!call_real_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ return false;
+ }
else
{
newval = conf->reset_val;
+ newextra = conf->reset_extra;
source = conf->gen.reset_source;
}
- /* Save old value to support transaction abort */
- if (changeVal && !makeDefault)
- push_old_value(&conf->gen, action);
-
- if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval, changeVal, source))
- {
+ if (prohibitValueChange)
+ {
+ if (*conf->variable != newval)
ereport(elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for parameter \"%s\": %g",
- name, newval)));
- return false;
- }
+ (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+ errmsg("parameter \"%s\" cannot be changed without restarting the server",
+ name)));
+ return false;
+ }
if (changeVal)
{
+ /* Save old value to support transaction abort */
+ if (!makeDefault)
+ push_old_value(&conf->gen, action);
+
+ if (conf->assign_hook)
+ (*conf->assign_hook) (newval, newextra);
*conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
conf->gen.source = source;
}
if (makeDefault)
@@ -5215,17 +5528,25 @@ set_config_option(const char *name, const char *value,
if (conf->gen.reset_source <= source)
{
conf->reset_val = newval;
+ set_extra_field(&conf->gen, &conf->reset_extra,
+ newextra);
conf->gen.reset_source = source;
}
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
if (stack->source <= source)
{
- stack->prior.realval = newval;
+ stack->prior.val.realval = newval;
+ set_extra_field(&conf->gen, &stack->prior.extra,
+ newextra);
stack->source = source;
}
}
}
+
+ /* Perhaps we didn't install newextra anywhere */
+ if (newextra && !extra_field_used(&conf->gen, newextra))
+ free(newextra);
break;
}
@@ -5233,95 +5554,88 @@ set_config_option(const char *name, const char *value,
{
struct config_string *conf = (struct config_string *) record;
char *newval;
+ void *newextra = NULL;
if (value)
{
+ /*
+ * The value passed by the caller could be transient,
+ * so we always strdup it.
+ */
newval = guc_strdup(elevel, value);
if (newval == NULL)
return false;
/*
- * The only sort of "parsing" check we need to do is apply
+ * The only built-in "parsing" check we have is to apply
* truncation if GUC_IS_NAME.
*/
if (conf->gen.flags & GUC_IS_NAME)
truncate_identifier(newval, strlen(newval), true);
+
+ if (!call_string_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ {
+ free(newval);
+ return false;
+ }
}
else if (source == PGC_S_DEFAULT)
{
- if (conf->boot_val == NULL)
- newval = NULL;
- else
+ /* non-NULL boot_val must always get strdup'd */
+ if (conf->boot_val != NULL)
{
newval = guc_strdup(elevel, conf->boot_val);
if (newval == NULL)
return false;
}
+ else
+ newval = NULL;
+
+ if (!call_string_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ {
+ free(newval);
+ return false;
+ }
}
else
{
/*
- * We could possibly avoid strdup here, but easier to make
- * this case work the same as the normal assignment case;
- * note the possible free of newval below.
+ * strdup not needed, since reset_val is already under
+ * guc.c's control
*/
- if (conf->reset_val == NULL)
- newval = NULL;
- else
- {
- newval = guc_strdup(elevel, conf->reset_val);
- if (newval == NULL)
- return false;
- }
+ newval = conf->reset_val;
+ newextra = conf->reset_extra;
source = conf->gen.reset_source;
}
- /* Save old value to support transaction abort */
- if (changeVal && !makeDefault)
- push_old_value(&conf->gen, action);
-
- if (conf->assign_hook && newval)
+ if (prohibitValueChange)
{
- const char *hookresult;
-
- /*
- * If the hook ereports, we have to make sure we free
- * newval, else it will be a permanent memory leak.
- */
- hookresult = call_string_assign_hook(conf->assign_hook,
- newval,
- changeVal,
- source);
- if (hookresult == NULL)
- {
- free(newval);
+ /* newval shouldn't be NULL, so we're a bit sloppy here */
+ if (*conf->variable == NULL || newval == NULL ||
+ strcmp(*conf->variable, newval) != 0)
ereport(elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for parameter \"%s\": \"%s\"",
- name, value ? value : "")));
- return false;
- }
- else if (hookresult != newval)
- {
- free(newval);
-
- /*
- * Having to cast away const here is annoying, but the
- * alternative is to declare assign_hooks as returning
- * char*, which would mean they'd have to cast away
- * const, or as both taking and returning char*, which
- * doesn't seem attractive either --- we don't want
- * them to scribble on the passed str.
- */
- newval = (char *) hookresult;
- }
+ (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+ errmsg("parameter \"%s\" cannot be changed without restarting the server",
+ name)));
+ return false;
}
if (changeVal)
{
+ /* Save old value to support transaction abort */
+ if (!makeDefault)
+ push_old_value(&conf->gen, action);
+
+ if (conf->assign_hook)
+ (*conf->assign_hook) (newval, newextra);
set_string_field(conf, conf->variable, newval);
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
conf->gen.source = source;
}
+
if (makeDefault)
{
GucStack *stack;
@@ -5329,27 +5643,37 @@ set_config_option(const char *name, const char *value,
if (conf->gen.reset_source <= source)
{
set_string_field(conf, &conf->reset_val, newval);
+ set_extra_field(&conf->gen, &conf->reset_extra,
+ newextra);
conf->gen.reset_source = source;
}
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
if (stack->source <= source)
{
- set_string_field(conf, &stack->prior.stringval,
+ set_string_field(conf, &stack->prior.val.stringval,
newval);
+ set_extra_field(&conf->gen, &stack->prior.extra,
+ newextra);
stack->source = source;
}
}
}
+
/* Perhaps we didn't install newval anywhere */
if (newval && !string_field_used(conf, newval))
free(newval);
+ /* Perhaps we didn't install newextra anywhere */
+ if (newextra && !extra_field_used(&conf->gen, newextra))
+ free(newextra);
break;
}
+
case PGC_ENUM:
{
struct config_enum *conf = (struct config_enum *) record;
int newval;
+ void *newextra = NULL;
if (value)
{
@@ -5371,33 +5695,45 @@ set_config_option(const char *name, const char *value,
pfree(hintmsg);
return false;
}
+ if (!call_enum_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ return false;
}
else if (source == PGC_S_DEFAULT)
+ {
newval = conf->boot_val;
+ if (!call_enum_check_hook(conf, &newval, &newextra,
+ source, elevel))
+ return false;
+ }
else
{
newval = conf->reset_val;
+ newextra = conf->reset_extra;
source = conf->gen.reset_source;
}
- /* Save old value to support transaction abort */
- if (changeVal && !makeDefault)
- push_old_value(&conf->gen, action);
-
- if (conf->assign_hook)
- if (!(*conf->assign_hook) (newval, changeVal, source))
- {
+ if (prohibitValueChange)
+ {
+ if (*conf->variable != newval)
ereport(elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for parameter \"%s\": \"%s\"",
- name,
- config_enum_lookup_by_value(conf, newval))));
- return false;
- }
+ (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+ errmsg("parameter \"%s\" cannot be changed without restarting the server",
+ name)));
+ return false;
+ }
if (changeVal)
{
+ /* Save old value to support transaction abort */
+ if (!makeDefault)
+ push_old_value(&conf->gen, action);
+
+ if (conf->assign_hook)
+ (*conf->assign_hook) (newval, newextra);
*conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
conf->gen.source = source;
}
if (makeDefault)
@@ -5407,17 +5743,25 @@ set_config_option(const char *name, const char *value,
if (conf->gen.reset_source <= source)
{
conf->reset_val = newval;
+ set_extra_field(&conf->gen, &conf->reset_extra,
+ newextra);
conf->gen.reset_source = source;
}
for (stack = conf->gen.stack; stack; stack = stack->prev)
{
if (stack->source <= source)
{
- stack->prior.enumval = newval;
+ stack->prior.val.enumval = newval;
+ set_extra_field(&conf->gen, &stack->prior.extra,
+ newextra);
stack->source = source;
}
}
}
+
+ /* Perhaps we didn't install newextra anywhere */
+ if (newextra && !extra_field_used(&conf->gen, newextra))
+ free(newextra);
break;
}
}
@@ -5578,51 +5922,6 @@ GetConfigOptionResetString(const char *name)
/*
- * 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,
* convert to the flat string representation used by GUC.
@@ -6115,6 +6414,7 @@ DefineCustomBoolVariable(const char *name,
bool bootValue,
GucContext context,
int flags,
+ GucBoolCheckHook check_hook,
GucBoolAssignHook assign_hook,
GucShowHook show_hook)
{
@@ -6126,6 +6426,7 @@ DefineCustomBoolVariable(const char *name,
var->variable = valueAddr;
var->boot_val = bootValue;
var->reset_val = bootValue;
+ var->check_hook = check_hook;
var->assign_hook = assign_hook;
var->show_hook = show_hook;
define_custom_variable(&var->gen);
@@ -6141,6 +6442,7 @@ DefineCustomIntVariable(const char *name,
int maxValue,
GucContext context,
int flags,
+ GucIntCheckHook check_hook,
GucIntAssignHook assign_hook,
GucShowHook show_hook)
{
@@ -6154,6 +6456,7 @@ DefineCustomIntVariable(const char *name,
var->reset_val = bootValue;
var->min = minValue;
var->max = maxValue;
+ var->check_hook = check_hook;
var->assign_hook = assign_hook;
var->show_hook = show_hook;
define_custom_variable(&var->gen);
@@ -6169,6 +6472,7 @@ DefineCustomRealVariable(const char *name,
double maxValue,
GucContext context,
int flags,
+ GucRealCheckHook check_hook,
GucRealAssignHook assign_hook,
GucShowHook show_hook)
{
@@ -6182,6 +6486,7 @@ DefineCustomRealVariable(const char *name,
var->reset_val = bootValue;
var->min = minValue;
var->max = maxValue;
+ var->check_hook = check_hook;
var->assign_hook = assign_hook;
var->show_hook = show_hook;
define_custom_variable(&var->gen);
@@ -6195,6 +6500,7 @@ DefineCustomStringVariable(const char *name,
const char *bootValue,
GucContext context,
int flags,
+ GucStringCheckHook check_hook,
GucStringAssignHook assign_hook,
GucShowHook show_hook)
{
@@ -6205,9 +6511,7 @@ DefineCustomStringVariable(const char *name,
PGC_STRING, sizeof(struct config_string));
var->variable = valueAddr;
var->boot_val = bootValue;
- /* we could probably do without strdup, but keep it like normal case */
- if (var->boot_val)
- var->reset_val = guc_strdup(ERROR, var->boot_val);
+ var->check_hook = check_hook;
var->assign_hook = assign_hook;
var->show_hook = show_hook;
define_custom_variable(&var->gen);
@@ -6222,6 +6526,7 @@ DefineCustomEnumVariable(const char *name,
const struct config_enum_entry * options,
GucContext context,
int flags,
+ GucEnumCheckHook check_hook,
GucEnumAssignHook assign_hook,
GucShowHook show_hook)
{
@@ -6234,6 +6539,7 @@ DefineCustomEnumVariable(const char *name,
var->boot_val = bootValue;
var->reset_val = bootValue;
var->options = options;
+ var->check_hook = check_hook;
var->assign_hook = assign_hook;
var->show_hook = show_hook;
define_custom_variable(&var->gen);
@@ -6995,67 +7301,6 @@ _ShowOption(struct config_generic * record, bool use_units)
}
-/*
- * Attempt (badly) to detect if a proposed new GUC setting is the same
- * as the current value.
- *
- * XXX this does not really work because it doesn't account for the
- * effects of canonicalization of string values by assign_hooks.
- */
-static bool
-is_newvalue_equal(struct config_generic * record, const char *newvalue)
-{
- /* newvalue == NULL isn't supported */
- Assert(newvalue != NULL);
-
- switch (record->vartype)
- {
- case PGC_BOOL:
- {
- struct config_bool *conf = (struct config_bool *) record;
- bool newval;
-
- return parse_bool(newvalue, &newval)
- && *conf->variable == newval;
- }
- case PGC_INT:
- {
- struct config_int *conf = (struct config_int *) record;
- int newval;
-
- return parse_int(newvalue, &newval, record->flags, NULL)
- && *conf->variable == newval;
- }
- case PGC_REAL:
- {
- struct config_real *conf = (struct config_real *) record;
- double newval;
-
- return parse_real(newvalue, &newval)
- && *conf->variable == newval;
- }
- case PGC_STRING:
- {
- struct config_string *conf = (struct config_string *) record;
-
- return *conf->variable != NULL &&
- strcmp(*conf->variable, newvalue) == 0;
- }
-
- case PGC_ENUM:
- {
- struct config_enum *conf = (struct config_enum *) record;
- int newval;
-
- return config_enum_lookup_by_name(conf, newvalue, &newval) &&
- *conf->variable == newval;
- }
- }
-
- return false;
-}
-
-
#ifdef EXEC_BACKEND
/*
@@ -7673,30 +7918,222 @@ validate_option_array_item(const char *name, const char *value,
/*
- * assign_hook and show_hook subroutines
+ * Called by check_hooks that want to override the normal
+ * ERRCODE_INVALID_PARAMETER_VALUE SQLSTATE for check hook failures.
+ *
+ * Note that GUC_check_errmsg() etc are just macros that result in a direct
+ * assignment to the associated variables. That is ugly, but forced by the
+ * limitations of C's macro mechanisms.
+ */
+void
+GUC_check_errcode(int sqlerrcode)
+{
+ GUC_check_errcode_value = sqlerrcode;
+}
+
+
+/*
+ * Convenience functions to manage calling a variable's check_hook.
+ * These mostly take care of the protocol for letting check hooks supply
+ * portions of the error report on failure.
*/
-static const char *
-assign_log_destination(const char *value, bool doit, GucSource source)
+static bool
+call_bool_check_hook(struct config_bool *conf, bool *newval, void **extra,
+ GucSource source, int elevel)
+{
+ /* Quick success if no hook */
+ if (!conf->check_hook)
+ return true;
+
+ /* Reset variables that might be set by hook */
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
+ GUC_check_errmsg_string = NULL;
+ GUC_check_errdetail_string = NULL;
+ GUC_check_errhint_string = NULL;
+
+ if (!(*conf->check_hook) (newval, extra, source))
+ {
+ ereport(elevel,
+ (errcode(GUC_check_errcode_value),
+ GUC_check_errmsg_string ?
+ errmsg("%s", GUC_check_errmsg_string) :
+ errmsg("invalid value for parameter \"%s\": %d",
+ conf->gen.name, (int) *newval),
+ GUC_check_errdetail_string ?
+ errdetail("%s", GUC_check_errdetail_string) : 0,
+ GUC_check_errhint_string ?
+ errhint("%s", GUC_check_errhint_string) : 0));
+ /* Flush any strings created in ErrorContext */
+ FlushErrorState();
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+call_int_check_hook(struct config_int *conf, int *newval, void **extra,
+ GucSource source, int elevel)
+{
+ /* Quick success if no hook */
+ if (!conf->check_hook)
+ return true;
+
+ /* Reset variables that might be set by hook */
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
+ GUC_check_errmsg_string = NULL;
+ GUC_check_errdetail_string = NULL;
+ GUC_check_errhint_string = NULL;
+
+ if (!(*conf->check_hook) (newval, extra, source))
+ {
+ ereport(elevel,
+ (errcode(GUC_check_errcode_value),
+ GUC_check_errmsg_string ?
+ errmsg("%s", GUC_check_errmsg_string) :
+ errmsg("invalid value for parameter \"%s\": %d",
+ conf->gen.name, *newval),
+ GUC_check_errdetail_string ?
+ errdetail("%s", GUC_check_errdetail_string) : 0,
+ GUC_check_errhint_string ?
+ errhint("%s", GUC_check_errhint_string) : 0));
+ /* Flush any strings created in ErrorContext */
+ FlushErrorState();
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+call_real_check_hook(struct config_real *conf, double *newval, void **extra,
+ GucSource source, int elevel)
+{
+ /* Quick success if no hook */
+ if (!conf->check_hook)
+ return true;
+
+ /* Reset variables that might be set by hook */
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
+ GUC_check_errmsg_string = NULL;
+ GUC_check_errdetail_string = NULL;
+ GUC_check_errhint_string = NULL;
+
+ if (!(*conf->check_hook) (newval, extra, source))
+ {
+ ereport(elevel,
+ (errcode(GUC_check_errcode_value),
+ GUC_check_errmsg_string ?
+ errmsg("%s", GUC_check_errmsg_string) :
+ errmsg("invalid value for parameter \"%s\": %g",
+ conf->gen.name, *newval),
+ GUC_check_errdetail_string ?
+ errdetail("%s", GUC_check_errdetail_string) : 0,
+ GUC_check_errhint_string ?
+ errhint("%s", GUC_check_errhint_string) : 0));
+ /* Flush any strings created in ErrorContext */
+ FlushErrorState();
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+call_string_check_hook(struct config_string *conf, char **newval, void **extra,
+ GucSource source, int elevel)
+{
+ /* Quick success if no hook */
+ if (!conf->check_hook)
+ return true;
+
+ /* Reset variables that might be set by hook */
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
+ GUC_check_errmsg_string = NULL;
+ GUC_check_errdetail_string = NULL;
+ GUC_check_errhint_string = NULL;
+
+ if (!(*conf->check_hook) (newval, extra, source))
+ {
+ ereport(elevel,
+ (errcode(GUC_check_errcode_value),
+ GUC_check_errmsg_string ?
+ errmsg("%s", GUC_check_errmsg_string) :
+ errmsg("invalid value for parameter \"%s\": \"%s\"",
+ conf->gen.name, *newval ? *newval : ""),
+ GUC_check_errdetail_string ?
+ errdetail("%s", GUC_check_errdetail_string) : 0,
+ GUC_check_errhint_string ?
+ errhint("%s", GUC_check_errhint_string) : 0));
+ /* Flush any strings created in ErrorContext */
+ FlushErrorState();
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+call_enum_check_hook(struct config_enum *conf, int *newval, void **extra,
+ GucSource source, int elevel)
+{
+ /* Quick success if no hook */
+ if (!conf->check_hook)
+ return true;
+
+ /* Reset variables that might be set by hook */
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
+ GUC_check_errmsg_string = NULL;
+ GUC_check_errdetail_string = NULL;
+ GUC_check_errhint_string = NULL;
+
+ if (!(*conf->check_hook) (newval, extra, source))
+ {
+ ereport(elevel,
+ (errcode(GUC_check_errcode_value),
+ GUC_check_errmsg_string ?
+ errmsg("%s", GUC_check_errmsg_string) :
+ errmsg("invalid value for parameter \"%s\": \"%s\"",
+ conf->gen.name,
+ config_enum_lookup_by_value(conf, *newval)),
+ GUC_check_errdetail_string ?
+ errdetail("%s", GUC_check_errdetail_string) : 0,
+ GUC_check_errhint_string ?
+ errhint("%s", GUC_check_errhint_string) : 0));
+ /* Flush any strings created in ErrorContext */
+ FlushErrorState();
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+ * check_hook, assign_hook and show_hook subroutines
+ */
+
+static bool
+check_log_destination(char **newval, void **extra, GucSource source)
{
char *rawstring;
List *elemlist;
ListCell *l;
int newlogdest = 0;
+ int *myextra;
/* Need a modifiable copy of string */
- rawstring = pstrdup(value);
+ rawstring = pstrdup(*newval);
/* Parse string into list of identifiers */
if (!SplitIdentifierString(rawstring, ',', &elemlist))
{
/* syntax error in list */
+ GUC_check_errdetail("List syntax is invalid.");
pfree(rawstring);
list_free(elemlist);
- ereport(GUC_complaint_elevel(source),
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid list syntax for parameter \"log_destination\"")));
- return NULL;
+ return false;
}
foreach(l, elemlist)
@@ -7717,105 +8154,103 @@ assign_log_destination(const char *value, bool doit, GucSource source)
#endif
else
{
- ereport(GUC_complaint_elevel(source),
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized \"log_destination\" key word: \"%s\"",
- tok)));
+ GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
pfree(rawstring);
list_free(elemlist);
- return NULL;
+ return false;
}
}
- if (doit)
- Log_destination = newlogdest;
-
pfree(rawstring);
list_free(elemlist);
- return value;
+ myextra = (int *) guc_malloc(ERROR, sizeof(int));
+ *myextra = newlogdest;
+ *extra = (void *) myextra;
+
+ return true;
+}
+
+static void
+assign_log_destination(const char *newval, void *extra)
+{
+ Log_destination = *((int *) extra);
}
-static bool
-assign_syslog_facility(int newval, bool doit, GucSource source)
+static void
+assign_syslog_facility(int newval, void *extra)
{
#ifdef HAVE_SYSLOG
- if (doit)
- set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
- newval);
+ set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
+ newval);
#endif
/* Without syslog support, just ignore it */
-
- return true;
}
-static const char *
-assign_syslog_ident(const char *ident, bool doit, GucSource source)
+static void
+assign_syslog_ident(const char *newval, void *extra)
{
#ifdef HAVE_SYSLOG
- if (doit)
- set_syslog_parameters(ident, syslog_facility);
+ set_syslog_parameters(newval, syslog_facility);
#endif
/* Without syslog support, it will always be set to "none", so ignore */
-
- return ident;
}
-static bool
-assign_session_replication_role(int newval, bool doit, GucSource source)
+static void
+assign_session_replication_role(int newval, void *extra)
{
/*
* Must flush the plan cache when changing replication role; but don't
* flush unnecessarily.
*/
- if (doit && SessionReplicationRole != newval)
- {
+ if (SessionReplicationRole != newval)
ResetPlanCache();
- }
-
- return true;
}
-static const char *
-show_num_temp_buffers(void)
+static bool
+check_temp_buffers(int *newval, void **extra, GucSource source)
{
/*
- * We show the GUC var until local buffers have been initialized, and
- * NLocBuffer afterwards.
+ * Once local buffers have been initialized, it's too late to change this.
*/
- static char nbuf[32];
-
- sprintf(nbuf, "%d", NLocBuffer ? NLocBuffer : num_temp_buffers);
- return nbuf;
+ if (NLocBuffer && NLocBuffer != *newval)
+ {
+ GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temp tables have been accessed in the session.");
+ return false;
+ }
+ return true;
}
static bool
-assign_phony_autocommit(bool newval, bool doit, GucSource source)
+check_phony_autocommit(bool *newval, void **extra, GucSource source)
{
- if (!newval)
+ if (!*newval)
{
- ereport(GUC_complaint_elevel(source),
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("SET AUTOCOMMIT TO OFF is no longer supported")));
+ GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
+ GUC_check_errmsg("SET AUTOCOMMIT TO OFF is no longer supported");
return false;
}
return true;
}
-static const char *
-assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
+static bool
+check_custom_variable_classes(char **newval, void **extra, GucSource source)
{
/*
* Check syntax. newval must be a comma separated list of identifiers.
* Whitespace is allowed but removed from the result.
*/
bool hasSpaceAfterToken = false;
- const char *cp = newval;
+ const char *cp = *newval;
int symLen = 0;
char c;
StringInfoData buf;
+ /* Default NULL is OK */
+ if (cp == NULL)
+ return true;
+
initStringInfo(&buf);
while ((c = *cp++) != '\0')
{
@@ -7844,7 +8279,7 @@ assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
* non-identifier character
*/
pfree(buf.data);
- return NULL;
+ return false;
}
appendStringInfoChar(&buf, c);
symLen++;
@@ -7855,21 +8290,20 @@ assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
buf.data[--buf.len] = '\0';
/* GUC wants the result malloc'd */
- newval = guc_strdup(LOG, buf.data);
+ free(*newval);
+ *newval = guc_strdup(LOG, buf.data);
pfree(buf.data);
- return newval;
+ return true;
}
static bool
-assign_debug_assertions(bool newval, bool doit, GucSource source)
+check_debug_assertions(bool *newval, void **extra, GucSource source)
{
#ifndef USE_ASSERT_CHECKING
- if (newval)
+ if (*newval)
{
- ereport(GUC_complaint_elevel(source),
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("assertion checking is not supported by this build")));
+ GUC_check_errmsg("assertion checking is not supported by this build");
return false;
}
#endif
@@ -7877,14 +8311,12 @@ assign_debug_assertions(bool newval, bool doit, GucSource source)
}
static bool
-assign_bonjour(bool newval, bool doit, GucSource source)
+check_bonjour(bool *newval, void **extra, GucSource source)
{
#ifndef USE_BONJOUR
- if (newval)
+ if (*newval)
{
- ereport(GUC_complaint_elevel(source),
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("Bonjour is not supported by this build")));
+ GUC_check_errmsg("Bonjour is not supported by this build");
return false;
}
#endif
@@ -7892,14 +8324,12 @@ assign_bonjour(bool newval, bool doit, GucSource source)
}
static bool
-assign_ssl(bool newval, bool doit, GucSource source)
+check_ssl(bool *newval, void **extra, GucSource source)
{
#ifndef USE_SSL
- if (newval)
+ if (*newval)
{
- ereport(GUC_complaint_elevel(source),
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("SSL is not supported by this build")));
+ GUC_check_errmsg("SSL is not supported by this build");
return false;
}
#endif
@@ -7907,57 +8337,48 @@ assign_ssl(bool newval, bool doit, GucSource source)
}
static bool
-assign_stage_log_stats(bool newval, bool doit, GucSource source)
+check_stage_log_stats(bool *newval, void **extra, GucSource source)
{
- if (newval && log_statement_stats)
+ if (*newval && log_statement_stats)
{
- 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 */
- if (source != PGC_S_OVERRIDE)
- return false;
+ GUC_check_errdetail("Cannot enable parameter when \"log_statement_stats\" is true.");
+ return false;
}
return true;
}
static bool
-assign_log_stats(bool newval, bool doit, GucSource source)
+check_log_stats(bool *newval, void **extra, GucSource source)
{
- if (newval &&
+ if (*newval &&
(log_parser_stats || log_planner_stats || log_executor_stats))
{
- 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 */
- if (source != PGC_S_OVERRIDE)
- return false;
+ GUC_check_errdetail("Cannot enable \"log_statement_stats\" when "
+ "\"log_parser_stats\", \"log_planner_stats\", "
+ "or \"log_executor_stats\" is true.");
+ return false;
}
return true;
}
-static const char *
-assign_canonical_path(const char *newval, bool doit, GucSource source)
+static bool
+check_canonical_path(char **newval, void **extra, GucSource source)
{
- if (doit)
- {
- char *canon_val = guc_strdup(ERROR, newval);
-
- canonicalize_path(canon_val);
- return canon_val;
- }
- else
- return newval;
+ /*
+ * Since canonicalize_path never enlarges the string, we can just
+ * modify newval in-place. But watch out for NULL, which is the
+ * default value for external_pid_file.
+ */
+ if (*newval)
+ canonicalize_path(*newval);
+ return true;
}
-static const char *
-assign_timezone_abbreviations(const char *newval, bool doit, GucSource source)
+static bool
+check_timezone_abbreviations(char **newval, void **extra, GucSource source)
{
/*
- * The powerup value shown above for timezone_abbreviations is "UNKNOWN".
+ * The boot_val given above for timezone_abbreviations is NULL.
* When we see this we just do nothing. If this value isn't overridden
* from the config file then pg_timezone_abbrev_initialize() will
* eventually replace it with "Default". This hack has two purposes: to
@@ -7965,34 +8386,32 @@ assign_timezone_abbreviations(const char *newval, bool doit, GucSource source)
* the config file, and to avoid trying to read the timezone abbrev files
* during InitializeGUCOptions(). The latter doesn't work in an
* EXEC_BACKEND subprocess because my_exec_path hasn't been set yet and so
- * we can't locate PGSHAREDIR. (Essentially the same hack is used to
- * delay initializing TimeZone ... if we have any more, we should try to
- * clean up and centralize this mechanism ...)
+ * we can't locate PGSHAREDIR.
*/
- if (strcmp(newval, "UNKNOWN") == 0)
+ if (*newval == NULL)
{
- return newval;
+ Assert(source == PGC_S_DEFAULT);
+ return true;
}
- /* Loading abbrev file is expensive, so only do it when value changes */
- if (timezone_abbreviations_string == NULL ||
- strcmp(timezone_abbreviations_string, newval) != 0)
- {
- int elevel;
+ /* OK, load the file and produce a malloc'd TimeZoneAbbrevTable */
+ *extra = load_tzoffsets(*newval);
- /*
- * If reading config file, only the postmaster should bleat loudly
- * about problems. Otherwise, it's just this one process doing it,
- * and we use WARNING message level.
- */
- if (source == PGC_S_FILE)
- elevel = IsUnderPostmaster ? DEBUG3 : LOG;
- else
- elevel = WARNING;
- if (!load_tzoffsets(newval, doit, elevel))
- return NULL;
- }
- return newval;
+ /* tzparser.c returns NULL on failure, reporting via GUC_check_errmsg */
+ if (!*extra)
+ return false;
+
+ return true;
+}
+
+static void
+assign_timezone_abbreviations(const char *newval, void *extra)
+{
+ /* Do nothing for the boot_val default of NULL */
+ if (!extra)
+ return;
+
+ InstallTimeZoneAbbrevs((TimeZoneAbbrevTable *) extra);
}
/*
@@ -8004,10 +8423,10 @@ assign_timezone_abbreviations(const char *newval, bool doit, GucSource source)
void
pg_timezone_abbrev_initialize(void)
{
- if (strcmp(timezone_abbreviations_string, "UNKNOWN") == 0)
+ if (timezone_abbreviations_string == NULL)
{
SetConfigOption("timezone_abbreviations", "Default",
- PGC_POSTMASTER, PGC_S_ARGV);
+ PGC_POSTMASTER, PGC_S_DEFAULT);
}
}
@@ -8020,54 +8439,61 @@ show_archive_command(void)
return "(disabled)";
}
-static bool
-assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
+static void
+assign_tcp_keepalives_idle(int newval, void *extra)
{
- if (doit)
- return (pq_setkeepalivesidle(newval, MyProcPort) == STATUS_OK);
-
- return true;
+ /*
+ * The kernel API provides no way to test a value without setting it;
+ * and once we set it we might fail to unset it. So there seems little
+ * point in fully implementing the check-then-assign GUC API for these
+ * variables. Instead we just do the assignment on demand. pqcomm.c
+ * reports any problems via elog(LOG).
+ *
+ * This approach means that the GUC value might have little to do with
+ * the actual kernel value, so we use a show_hook that retrieves the
+ * kernel value rather than trusting GUC's copy.
+ */
+ (void) pq_setkeepalivesidle(newval, MyProcPort);
}
static const char *
show_tcp_keepalives_idle(void)
{
+ /* See comments in assign_tcp_keepalives_idle */
static char nbuf[16];
snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
return nbuf;
}
-static bool
-assign_tcp_keepalives_interval(int newval, bool doit, GucSource source)
+static void
+assign_tcp_keepalives_interval(int newval, void *extra)
{
- if (doit)
- return (pq_setkeepalivesinterval(newval, MyProcPort) == STATUS_OK);
-
- return true;
+ /* See comments in assign_tcp_keepalives_idle */
+ (void) pq_setkeepalivesinterval(newval, MyProcPort);
}
static const char *
show_tcp_keepalives_interval(void)
{
+ /* See comments in assign_tcp_keepalives_idle */
static char nbuf[16];
snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
return nbuf;
}
-static bool
-assign_tcp_keepalives_count(int newval, bool doit, GucSource source)
+static void
+assign_tcp_keepalives_count(int newval, void *extra)
{
- if (doit)
- return (pq_setkeepalivescount(newval, MyProcPort) == STATUS_OK);
-
- return true;
+ /* See comments in assign_tcp_keepalives_idle */
+ (void) pq_setkeepalivescount(newval, MyProcPort);
}
static const char *
show_tcp_keepalives_count(void)
{
+ /* See comments in assign_tcp_keepalives_idle */
static char nbuf[16];
snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
@@ -8075,31 +8501,35 @@ show_tcp_keepalives_count(void)
}
static bool
-assign_maxconnections(int newval, bool doit, GucSource source)
+check_maxconnections(int *newval, void **extra, GucSource source)
{
- if (newval + autovacuum_max_workers + 1 > MAX_BACKENDS)
+ if (*newval + autovacuum_max_workers + 1 > MAX_BACKENDS)
return false;
-
- if (doit)
- MaxBackends = newval + autovacuum_max_workers + 1;
-
return true;
}
+static void
+assign_maxconnections(int newval, void *extra)
+{
+ MaxBackends = newval + autovacuum_max_workers + 1;
+}
+
static bool
-assign_autovacuum_max_workers(int newval, bool doit, GucSource source)
+check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
{
- if (MaxConnections + newval + 1 > MAX_BACKENDS)
+ if (MaxConnections + *newval + 1 > MAX_BACKENDS)
return false;
-
- if (doit)
- MaxBackends = MaxConnections + newval + 1;
-
return true;
}
+static void
+assign_autovacuum_max_workers(int newval, void *extra)
+{
+ MaxBackends = MaxConnections + newval + 1;
+}
+
static bool
-assign_effective_io_concurrency(int newval, bool doit, GucSource source)
+check_effective_io_concurrency(int *newval, void **extra, GucSource source)
{
#ifdef USE_PREFETCH
double new_prefetch_pages = 0.0;
@@ -8108,6 +8538,8 @@ assign_effective_io_concurrency(int newval, bool doit, GucSource source)
/*----------
* The user-visible GUC parameter is the number of drives (spindles),
* which we need to translate to a number-of-pages-to-prefetch target.
+ * The target value is stashed in *extra and then assigned to the actual
+ * variable by assign_effective_io_concurrency.
*
* The expected number of prefetch pages needed to keep N drives busy is:
*
@@ -8132,18 +8564,21 @@ assign_effective_io_concurrency(int newval, bool doit, GucSource source)
* Experimental results show that both of these formulas aren't aggressive
* enough, but we don't really have any better proposals.
*
- * Note that if newval = 0 (disabled), we must set target = 0.
+ * Note that if *newval = 0 (disabled), we must set target = 0.
*----------
*/
- for (i = 1; i <= newval; i++)
- new_prefetch_pages += (double) newval / (double) i;
+ for (i = 1; i <= *newval; i++)
+ new_prefetch_pages += (double) *newval / (double) i;
/* This range check shouldn't fail, but let's be paranoid */
if (new_prefetch_pages >= 0.0 && new_prefetch_pages < (double) INT_MAX)
{
- if (doit)
- target_prefetch_pages = (int) rint(new_prefetch_pages);
+ int *myextra = (int *) guc_malloc(ERROR, sizeof(int));
+
+ *myextra = (int) rint(new_prefetch_pages);
+ *extra = (void *) myextra;
+
return true;
}
else
@@ -8153,57 +8588,54 @@ assign_effective_io_concurrency(int newval, bool doit, GucSource source)
#endif /* USE_PREFETCH */
}
-static const char *
-assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source)
+static void
+assign_effective_io_concurrency(int newval, void *extra)
{
- if (doit)
- {
- char *canon_val = guc_strdup(ERROR, newval);
- char *tname;
- char *fname;
-
- canonicalize_path(canon_val);
-
- tname = guc_malloc(ERROR, strlen(canon_val) + 12); /* /pgstat.tmp */
- sprintf(tname, "%s/pgstat.tmp", canon_val);
- fname = guc_malloc(ERROR, strlen(canon_val) + 13); /* /pgstat.stat */
- sprintf(fname, "%s/pgstat.stat", canon_val);
+#ifdef USE_PREFETCH
+ target_prefetch_pages = *((int *) extra);
+#endif /* USE_PREFETCH */
+}
- if (pgstat_stat_tmpname)
- free(pgstat_stat_tmpname);
- pgstat_stat_tmpname = tname;
- if (pgstat_stat_filename)
- free(pgstat_stat_filename);
- pgstat_stat_filename = fname;
+static void
+assign_pgstat_temp_directory(const char *newval, void *extra)
+{
+ /* check_canonical_path already canonicalized newval for us */
+ char *tname;
+ char *fname;
- return canon_val;
- }
- else
- return newval;
+ tname = guc_malloc(ERROR, strlen(newval) + 12); /* /pgstat.tmp */
+ sprintf(tname, "%s/pgstat.tmp", newval);
+ fname = guc_malloc(ERROR, strlen(newval) + 13); /* /pgstat.stat */
+ sprintf(fname, "%s/pgstat.stat", newval);
+
+ if (pgstat_stat_tmpname)
+ free(pgstat_stat_tmpname);
+ pgstat_stat_tmpname = tname;
+ if (pgstat_stat_filename)
+ free(pgstat_stat_filename);
+ pgstat_stat_filename = fname;
}
-static const char *
-assign_application_name(const char *newval, bool doit, GucSource source)
+static bool
+check_application_name(char **newval, void **extra, GucSource source)
{
- if (doit)
- {
- /* Only allow clean ASCII chars in the application name */
- char *repval = guc_strdup(ERROR, newval);
- char *p;
+ /* Only allow clean ASCII chars in the application name */
+ char *p;
- for (p = repval; *p; p++)
- {
- if (*p < 32 || *p > 126)
- *p = '?';
- }
+ for (p = *newval; *p; p++)
+ {
+ if (*p < 32 || *p > 126)
+ *p = '?';
+ }
- /* Update the pg_stat_activity view */
- pgstat_report_appname(repval);
+ return true;
+}
- return repval;
- }
- else
- return newval;
+static void
+assign_application_name(const char *newval, void *extra)
+{
+ /* Update the pg_stat_activity view */
+ pgstat_report_appname(newval);
}
static const char *
diff --git a/src/backend/utils/misc/tzparser.c b/src/backend/utils/misc/tzparser.c
index e63ce58e69a..b2f6dd3a2bb 100644
--- a/src/backend/utils/misc/tzparser.c
+++ b/src/backend/utils/misc/tzparser.c
@@ -3,10 +3,12 @@
* tzparser.c
* Functions for parsing timezone offset files
*
- * Note: we generally should not throw any errors in this file, but instead
- * try to return an error code. This is not completely bulletproof at
- * present --- in particular out-of-memory will throw an error. Could
- * probably fix with PG_TRY if necessary.
+ * Note: this code is invoked from the check_hook for the GUC variable
+ * timezone_abbreviations. Therefore, it should report problems using
+ * GUC_check_errmsg() and related functions, and try to avoid throwing
+ * elog(ERROR). This is not completely bulletproof at present --- in
+ * particular out-of-memory will throw an error. Could probably fix with
+ * PG_TRY if necessary.
*
*
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
@@ -24,15 +26,13 @@
#include "miscadmin.h"
#include "storage/fd.h"
-#include "utils/datetime.h"
+#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/tzparser.h"
#define WHITESPACE " \t\n\r"
-static int tz_elevel; /* to avoid passing this around a lot */
-
static bool validateTzEntry(tzEntry *tzentry);
static bool splitTzLine(const char *filename, int lineno,
char *line, tzEntry *tzentry);
@@ -58,20 +58,16 @@ validateTzEntry(tzEntry *tzentry)
*/
if (strlen(tzentry->abbrev) > TOKMAXLEN)
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("time zone abbreviation \"%s\" is too long (maximum %d characters) in time zone file \"%s\", line %d",
- tzentry->abbrev, TOKMAXLEN,
- tzentry->filename, tzentry->lineno)));
+ GUC_check_errmsg("time zone abbreviation \"%s\" is too long (maximum %d characters) in time zone file \"%s\", line %d",
+ tzentry->abbrev, TOKMAXLEN,
+ tzentry->filename, tzentry->lineno);
return false;
}
if (tzentry->offset % 900 != 0)
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("time zone offset %d is not a multiple of 900 sec (15 min) in time zone file \"%s\", line %d",
- tzentry->offset,
- tzentry->filename, tzentry->lineno)));
+ GUC_check_errmsg("time zone offset %d is not a multiple of 900 sec (15 min) in time zone file \"%s\", line %d",
+ tzentry->offset,
+ tzentry->filename, tzentry->lineno);
return false;
}
@@ -81,11 +77,9 @@ validateTzEntry(tzEntry *tzentry)
if (tzentry->offset > 14 * 60 * 60 ||
tzentry->offset < -14 * 60 * 60)
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("time zone offset %d is out of range in time zone file \"%s\", line %d",
- tzentry->offset,
- tzentry->filename, tzentry->lineno)));
+ GUC_check_errmsg("time zone offset %d is out of range in time zone file \"%s\", line %d",
+ tzentry->offset,
+ tzentry->filename, tzentry->lineno);
return false;
}
@@ -118,10 +112,8 @@ splitTzLine(const char *filename, int lineno, char *line, tzEntry *tzentry)
abbrev = strtok(line, WHITESPACE);
if (!abbrev)
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("missing time zone abbreviation in time zone file \"%s\", line %d",
- filename, lineno)));
+ GUC_check_errmsg("missing time zone abbreviation in time zone file \"%s\", line %d",
+ filename, lineno);
return false;
}
tzentry->abbrev = abbrev;
@@ -129,19 +121,15 @@ splitTzLine(const char *filename, int lineno, char *line, tzEntry *tzentry)
offset = strtok(NULL, WHITESPACE);
if (!offset)
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("missing time zone offset in time zone file \"%s\", line %d",
- filename, lineno)));
+ GUC_check_errmsg("missing time zone offset in time zone file \"%s\", line %d",
+ filename, lineno);
return false;
}
tzentry->offset = strtol(offset, &offset_endptr, 10);
if (offset_endptr == offset || *offset_endptr != '\0')
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid number for time zone offset in time zone file \"%s\", line %d",
- filename, lineno)));
+ GUC_check_errmsg("invalid number for time zone offset in time zone file \"%s\", line %d",
+ filename, lineno);
return false;
}
@@ -163,10 +151,8 @@ splitTzLine(const char *filename, int lineno, char *line, tzEntry *tzentry)
if (remain[0] != '#') /* must be a comment */
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid syntax in time zone file \"%s\", line %d",
- filename, lineno)));
+ GUC_check_errmsg("invalid syntax in time zone file \"%s\", line %d",
+ filename, lineno);
return false;
}
return true;
@@ -229,13 +215,11 @@ addToArray(tzEntry **base, int *arraysize, int n,
return n;
}
/* same abbrev but something is different, complain */
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("time zone abbreviation \"%s\" is multiply defined",
- entry->abbrev),
- errdetail("Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s\", line %d.",
- midptr->filename, midptr->lineno,
- entry->filename, entry->lineno)));
+ GUC_check_errmsg("time zone abbreviation \"%s\" is multiply defined",
+ entry->abbrev);
+ GUC_check_errdetail("Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s\", line %d.",
+ midptr->filename, midptr->lineno,
+ entry->filename, entry->lineno);
return -1;
}
}
@@ -296,12 +280,10 @@ ParseTzFile(const char *filename, int depth,
{
if (!isalpha((unsigned char) *p))
{
- /* at level 0, we need no ereport since guc.c will say enough */
+ /* at level 0, just use guc.c's regular "invalid value" message */
if (depth > 0)
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid time zone file name \"%s\"",
- filename)));
+ GUC_check_errmsg("invalid time zone file name \"%s\"",
+ filename);
return -1;
}
}
@@ -313,10 +295,8 @@ ParseTzFile(const char *filename, int depth,
*/
if (depth > 3)
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("time zone file recursion limit exceeded in file \"%s\"",
- filename)));
+ GUC_check_errmsg("time zone file recursion limit exceeded in file \"%s\"",
+ filename);
return -1;
}
@@ -340,12 +320,10 @@ ParseTzFile(const char *filename, int depth,
tzdir = AllocateDir(file_path);
if (tzdir == NULL)
{
- ereport(tz_elevel,
- (errcode_for_file_access(),
- errmsg("could not open directory \"%s\": %m",
- file_path),
- errhint("This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location.",
- my_exec_path)));
+ GUC_check_errmsg("could not open directory \"%s\": %m",
+ file_path);
+ GUC_check_errhint("This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location.",
+ my_exec_path);
return -1;
}
FreeDir(tzdir);
@@ -356,10 +334,8 @@ ParseTzFile(const char *filename, int depth,
* complaint is enough
*/
if (errno != ENOENT || depth > 0)
- ereport(tz_elevel,
- (errcode_for_file_access(),
- errmsg("could not read time zone file \"%s\": %m",
- filename)));
+ GUC_check_errmsg("could not read time zone file \"%s\": %m",
+ filename);
return -1;
}
@@ -371,10 +347,8 @@ ParseTzFile(const char *filename, int depth,
{
if (ferror(tzFile))
{
- ereport(tz_elevel,
- (errcode_for_file_access(),
- errmsg("could not read time zone file \"%s\": %m",
- filename)));
+ GUC_check_errmsg("could not read time zone file \"%s\": %m",
+ filename);
return -1;
}
/* else we're at EOF after all */
@@ -383,10 +357,8 @@ ParseTzFile(const char *filename, int depth,
if (strlen(tzbuf) == sizeof(tzbuf) - 1)
{
/* the line is too long for tzbuf */
- ereport(tz_elevel,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("line is too long in time zone file \"%s\", line %d",
- filename, lineno)));
+ GUC_check_errmsg("line is too long in time zone file \"%s\", line %d",
+ filename, lineno);
return -1;
}
@@ -408,10 +380,8 @@ ParseTzFile(const char *filename, int depth,
includeFile = strtok(includeFile, WHITESPACE);
if (!includeFile || !*includeFile)
{
- ereport(tz_elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("@INCLUDE without file name in time zone file \"%s\", line %d",
- filename, lineno)));
+ GUC_check_errmsg("@INCLUDE without file name in time zone file \"%s\", line %d",
+ filename, lineno);
return -1;
}
n = ParseTzFile(includeFile, depth + 1,
@@ -444,23 +414,20 @@ ParseTzFile(const char *filename, int depth,
/*
* load_tzoffsets --- read and parse the specified timezone offset file
*
- * filename: name specified by user
- * doit: whether to actually apply the new values, or just check
- * elevel: elog reporting level (will be less than ERROR)
- *
- * Returns TRUE if OK, FALSE if not; should avoid erroring out
+ * On success, return a filled-in TimeZoneAbbrevTable, which must have been
+ * malloc'd not palloc'd. On failure, return NULL, using GUC_check_errmsg
+ * and friends to give details of the problem.
*/
-bool
-load_tzoffsets(const char *filename, bool doit, int elevel)
+TimeZoneAbbrevTable *
+load_tzoffsets(const char *filename)
{
+ TimeZoneAbbrevTable *result = NULL;
MemoryContext tmpContext;
MemoryContext oldContext;
tzEntry *array;
int arraysize;
int n;
- tz_elevel = elevel;
-
/*
* Create a temp memory context to work in. This makes it easy to clean
* up afterwards.
@@ -479,13 +446,20 @@ load_tzoffsets(const char *filename, bool doit, int elevel)
/* Parse the file(s) */
n = ParseTzFile(filename, 0, &array, &arraysize, 0);
- /* If no errors and we should apply the result, pass it to datetime.c */
- if (n >= 0 && doit)
- InstallTimeZoneAbbrevs(array, n);
+ /* If no errors so far, allocate result and let datetime.c convert data */
+ if (n >= 0)
+ {
+ result = malloc(offsetof(TimeZoneAbbrevTable, abbrevs) +
+ n * sizeof(datetkn));
+ if (!result)
+ GUC_check_errmsg("out of memory");
+ else
+ ConvertTimeZoneAbbrevs(result, array, n);
+ }
/* Clean up */
MemoryContextSwitchTo(oldContext);
MemoryContextDelete(tmpContext);
- return (n >= 0);
+ return result;
}