OSDN Git Service

Remove silent_mode. You get the same functionality with "pg_ctl -l
[pg-rex/syncrep.git] / src / backend / utils / misc / guc.c
index 0bf1845..c5782e2 100644 (file)
  * 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);
 
@@ -351,6 +369,23 @@ static const struct config_enum_entry constraint_exclusion_options[] = {
 };
 
 /*
+ * Although only "on", "off", and "local" are documented, we
+ * accept all the likely variants of "on" and "off".
+ */
+static const struct config_enum_entry synchronous_commit_options[] = {
+       {"local", SYNCHRONOUS_COMMIT_LOCAL_FLUSH, false},
+       {"on", SYNCHRONOUS_COMMIT_ON, false},
+       {"off", SYNCHRONOUS_COMMIT_OFF, false},
+       {"true", SYNCHRONOUS_COMMIT_ON, true},
+       {"false", SYNCHRONOUS_COMMIT_OFF, true},
+       {"yes", SYNCHRONOUS_COMMIT_ON, true},
+       {"no", SYNCHRONOUS_COMMIT_OFF, true},
+       {"1", SYNCHRONOUS_COMMIT_ON, true},
+       {"0", SYNCHRONOUS_COMMIT_OFF, true},
+       {NULL, 0, false}
+};
+
+/*
  * Options for enum values stored in other modules
  */
 extern const struct config_enum_entry wal_level_options[];
@@ -390,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;
@@ -427,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;
@@ -438,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;
 
 
 /*
@@ -467,6 +502,7 @@ const char *const GucContext_Names[] =
 const char *const GucSource_Names[] =
 {
         /* PGC_S_DEFAULT */ "default",
+        /* PGC_S_DYNAMIC_DEFAULT */ "default",
         /* PGC_S_ENV_VAR */ "environment variable",
         /* PGC_S_FILE */ "configuration file",
         /* PGC_S_ARGV */ "command line",
@@ -626,7 +662,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_seqscan,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -634,7 +671,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_indexscan,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -642,7 +680,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_bitmapscan,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -650,7 +689,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_tidscan,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -658,7 +698,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_sort,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -666,7 +707,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_hashagg,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_material", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -674,7 +716,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_material,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -682,7 +725,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_nestloop,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -690,7 +734,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_mergejoin,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
@@ -698,7 +743,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_hashjoin,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
@@ -707,7 +753,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 */
@@ -717,7 +764,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,
@@ -725,7 +773,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &enable_bonjour,
-               false, assign_bonjour, NULL
+               false,
+               check_bonjour, NULL, NULL
        },
        {
                {"ssl", PGC_POSTMASTER, CONN_AUTH_SECURITY,
@@ -733,7 +782,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &EnableSSL,
-               false, assign_ssl, NULL
+               false,
+               check_ssl, NULL, NULL
        },
        {
                {"fsync", PGC_SIGHUP, WAL_SETTINGS,
@@ -744,23 +794,8 @@ static struct config_bool ConfigureNamesBool[] =
                                                 "an operating system or hardware crash.")
                },
                &enableFsync,
-               true, NULL, NULL
-       },
-       {
-               {"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
-                       gettext_noop("Sets immediate fsync at commit."),
-                       NULL
-               },
-               &XactSyncCommit,
-               true, NULL, NULL
-       },
-       {
-               {"synchronous_replication", PGC_USERSET, WAL_REPLICATION,
-                       gettext_noop("Requests synchronous replication."),
-                       NULL
-               },
-               &sync_rep_mode,
-               false, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
@@ -773,7 +808,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,
@@ -785,16 +821,8 @@ static struct config_bool ConfigureNamesBool[] =
                                                 "is possible.")
                },
                &fullPageWrites,
-               true, NULL, NULL
-       },
-       {
-               {"silent_mode", PGC_POSTMASTER, LOGGING_WHERE,
-                       gettext_noop("Runs the server silently."),
-                       gettext_noop("If this parameter is set, the server will automatically run in the "
-                                "background and any controlling terminals are dissociated.")
-               },
-               &SilentMode,
-               false, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
@@ -802,7 +830,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &log_checkpoints,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"log_connections", PGC_BACKEND, LOGGING_WHAT,
@@ -810,7 +839,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Log_connections,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"log_disconnections", PGC_BACKEND, LOGGING_WHAT,
@@ -818,7 +848,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Log_disconnections,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"debug_assertions", PGC_USERSET, DEVELOPER_OPTIONS,
@@ -832,7 +863,7 @@ static struct config_bool ConfigureNamesBool[] =
 #else
                false,
 #endif
-               assign_debug_assertions, NULL
+               check_debug_assertions, NULL, NULL
        },
 
        {
@@ -841,7 +872,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &ExitOnAnyError,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"restart_after_crash", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
@@ -849,7 +881,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &restart_after_crash,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
 
        {
@@ -858,7 +891,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &log_duration,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
@@ -866,7 +900,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Debug_print_parse,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
@@ -874,7 +909,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Debug_print_rewritten,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
@@ -882,7 +918,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Debug_print_plan,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
@@ -890,7 +927,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Debug_pretty_print,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"log_parser_stats", PGC_SUSET, STATS_MONITORING,
@@ -898,7 +936,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,
@@ -906,7 +945,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,
@@ -914,7 +954,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,
@@ -922,7 +963,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
        {
@@ -932,7 +974,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &log_btree_build_stats,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 #endif
 
@@ -944,7 +987,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,
@@ -952,7 +996,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &pgstat_track_counts,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
 
        {
@@ -961,7 +1006,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
        },
 
        {
@@ -970,7 +1016,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &autovacuum_start_daemon,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
 
        {
@@ -980,7 +1027,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &Trace_notify,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
 #ifdef LOCK_DEBUG
@@ -991,7 +1039,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,
@@ -1000,7 +1049,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,
@@ -1009,7 +1059,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,
@@ -1018,7 +1069,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &Debug_deadlocks,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 #endif
 
@@ -1028,7 +1080,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &log_lock_waits,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
        {
@@ -1040,7 +1093,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,
@@ -1048,7 +1102,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &SQL_inheritance,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
@@ -1058,7 +1113,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,
@@ -1070,7 +1126,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,
@@ -1078,7 +1135,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Db_user_namespace,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                /* only here for backwards compatibility */
@@ -1088,7 +1146,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,
@@ -1096,7 +1155,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &DefaultXactReadOnly,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
@@ -1105,7 +1165,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,
@@ -1113,7 +1174,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &DefaultXactDeferrable,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
@@ -1122,7 +1184,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,
@@ -1130,7 +1193,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &check_function_bodies,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
        {
                {"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
@@ -1140,7 +1204,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,
@@ -1148,7 +1213,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &default_with_oids,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"logging_collector", PGC_POSTMASTER, LOGGING_WHERE,
@@ -1156,7 +1222,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Logging_collector,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
        {
                {"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
@@ -1164,7 +1231,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &Log_truncate_on_rotation,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
 #ifdef TRACE_SORT
@@ -1175,7 +1243,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &trace_sort,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 #endif
 
@@ -1188,7 +1257,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &trace_syncscan,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 #endif
 
@@ -1202,7 +1272,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &optimize_bounded_sort,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
 #endif
 
@@ -1214,7 +1285,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &XLOG_DEBUG,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 #endif
 
@@ -1226,10 +1298,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
        },
 
        {
@@ -1238,7 +1311,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &pg_krb_caseins_users,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
        {
@@ -1247,7 +1321,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &escape_string_warning,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
 
        {
@@ -1257,7 +1332,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_REPORT
                },
                &standard_conforming_strings,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
 
        {
@@ -1266,7 +1342,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &synchronize_seqscans,
-               true, NULL, NULL
+               true,
+               NULL, NULL, NULL
        },
 
        {
@@ -1275,7 +1352,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &XLogArchiveMode,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
        {
@@ -1284,7 +1362,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &EnableHotStandby,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
        {
@@ -1293,7 +1372,8 @@ static struct config_bool ConfigureNamesBool[] =
                        NULL
                },
                &hot_standby_feedback,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
        {
@@ -1303,7 +1383,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &allowSystemTableMods,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
        {
@@ -1314,7 +1395,8 @@ static struct config_bool ConfigureNamesBool[] =
                        GUC_NOT_IN_SAMPLE
                },
                &IgnoreSystemIndexes,
-               false, NULL, NULL
+               false,
+               NULL, NULL, NULL
        },
 
        {
@@ -1324,7 +1406,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
        },
 
        {
@@ -1333,12 +1416,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
        }
 };
 
@@ -1353,7 +1437,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,
@@ -1362,7 +1447,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,
@@ -1371,7 +1457,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,
@@ -1382,7 +1469,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,
@@ -1393,7 +1481,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,
@@ -1401,7 +1490,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,
@@ -1409,7 +1499,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,
@@ -1417,7 +1508,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,
@@ -1425,18 +1517,20 @@ 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
        },
 
        {
-               /* This is PGC_SIGHUP so all backends have the same value. */
-               {"deadlock_timeout", PGC_SIGHUP, LOCK_MANAGEMENT,
+               /* This is PGC_SUSET to prevent hiding from log_lock_waits. */
+               {"deadlock_timeout", PGC_SUSET, LOCK_MANAGEMENT,
                        gettext_noop("Sets the time to wait on a lock before checking for deadlock."),
                        NULL,
                        GUC_UNIT_MS
                },
                &DeadlockTimeout,
-               1000, 1, INT_MAX / 1000, NULL, NULL
+               1000, 1, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1446,7 +1540,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &max_standby_archive_delay,
-               30 * 1000, -1, INT_MAX / 1000, NULL, NULL
+               30 * 1000, -1, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1456,7 +1551,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &max_standby_streaming_delay,
-               30 * 1000, -1, INT_MAX / 1000, NULL, NULL
+               30 * 1000, -1, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1466,7 +1562,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
        },
 
        {
@@ -1475,7 +1572,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &MaxConnections,
-               100, 1, MAX_BACKENDS, assign_maxconnections, NULL
+               100, 1, MAX_BACKENDS,
+               check_maxconnections, assign_maxconnections, NULL
        },
 
        {
@@ -1484,7 +1582,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &ReservedBackends,
-               3, 0, MAX_BACKENDS, NULL, NULL
+               3, 0, MAX_BACKENDS,
+               NULL, NULL, NULL
        },
 
        /*
@@ -1498,7 +1597,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
        },
 
        {
@@ -1508,7 +1608,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
        },
 
        {
@@ -1517,7 +1618,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &PostPortNumber,
-               DEF_PGPORT, 1, 65535, NULL, NULL
+               DEF_PGPORT, 1, 65535,
+               NULL, NULL, NULL
        },
 
        {
@@ -1531,7 +1633,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
        },
 
        {
@@ -1544,7 +1647,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
        },
 
        {
@@ -1556,7 +1660,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_KB
                },
                &work_mem,
-               1024, 64, MAX_KILOBYTES, NULL, NULL
+               1024, 64, MAX_KILOBYTES,
+               NULL, NULL, NULL
        },
 
        {
@@ -1566,7 +1671,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
        },
 
        /*
@@ -1581,7 +1687,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
        },
 
        {
@@ -1590,7 +1697,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &VacuumCostPageHit,
-               1, 0, 10000, NULL, NULL
+               1, 0, 10000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1599,7 +1707,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &VacuumCostPageMiss,
-               10, 0, 10000, NULL, NULL
+               10, 0, 10000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1608,7 +1717,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &VacuumCostPageDirty,
-               20, 0, 10000, NULL, NULL
+               20, 0, 10000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1617,7 +1727,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &VacuumCostLimit,
-               200, 1, 10000, NULL, NULL
+               200, 1, 10000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1627,7 +1738,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &VacuumCostDelay,
-               0, 0, 100, NULL, NULL
+               0, 0, 100,
+               NULL, NULL, NULL
        },
 
        {
@@ -1637,7 +1749,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &autovacuum_vac_cost_delay,
-               20, -1, 100, NULL, NULL
+               20, -1, 100,
+               NULL, NULL, NULL
        },
 
        {
@@ -1646,7 +1759,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &autovacuum_vac_cost_limit,
-               -1, -1, 10000, NULL, NULL
+               -1, -1, 10000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1655,7 +1769,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &max_files_per_process,
-               1000, 25, INT_MAX, NULL, NULL
+               1000, 25, INT_MAX,
+               NULL, NULL, NULL
        },
 
        /*
@@ -1667,7 +1782,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
@@ -1678,7 +1794,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,
@@ -1687,7 +1804,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
 
@@ -1698,7 +1816,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &StatementTimeout,
-               0, 0, INT_MAX, NULL, NULL
+               0, 0, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1707,7 +1826,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &vacuum_freeze_min_age,
-               50000000, 0, 1000000000, NULL, NULL
+               50000000, 0, 1000000000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1716,7 +1836,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &vacuum_freeze_table_age,
-               150000000, 0, 2000000000, NULL, NULL
+               150000000, 0, 2000000000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1725,7 +1846,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &vacuum_defer_cleanup_age,
-               0, 0, 1000000, NULL, NULL
+               0, 0, 1000000,
+               NULL, NULL, NULL
        },
 
        /*
@@ -1739,18 +1861,20 @@ 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
        },
 
        {
                {"max_pred_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
                        gettext_noop("Sets the maximum number of predicate locks per transaction."),
                        gettext_noop("The shared predicate lock table is sized on the assumption that "
-                         "at most max_pred_locks_per_transaction * max_connections distinct "
+                                                "at most max_pred_locks_per_transaction * max_connections distinct "
                                                 "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
        },
 
        {
@@ -1760,7 +1884,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_S
                },
                &AuthenticationTimeout,
-               60, 1, 600, NULL, NULL
+               60, 1, 600,
+               NULL, NULL, NULL
        },
 
        {
@@ -1771,7 +1896,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
        },
 
        {
@@ -1780,7 +1906,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &wal_keep_segments,
-               0, 0, INT_MAX, NULL, NULL
+               0, 0, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1789,7 +1916,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &CheckPointSegments,
-               3, 1, INT_MAX, NULL, NULL
+               3, 1, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1799,7 +1927,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_S
                },
                &CheckPointTimeout,
-               300, 30, 3600, NULL, NULL
+               300, 30, 3600,
+               NULL, NULL, NULL
        },
 
        {
@@ -1812,7 +1941,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_S
                },
                &CheckPointWarning,
-               30, 0, INT_MAX, NULL, NULL
+               30, 0, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1822,7 +1952,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
        },
 
        {
@@ -1832,7 +1963,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &WalWriterDelay,
-               200, 1, 10000, NULL, NULL
+               200, 1, 10000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1842,7 +1974,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &max_wal_senders,
-               0, 0, MAX_BACKENDS, NULL, NULL
+               0, 0, MAX_BACKENDS,
+               NULL, NULL, NULL
        },
 
        {
@@ -1852,7 +1985,19 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &WalSndDelay,
-               1000, 1, 10000, NULL, NULL
+               1000, 1, 10000,
+               NULL, NULL, NULL
+       },
+
+       {
+               {"replication_timeout", PGC_SIGHUP, WAL_REPLICATION,
+                       gettext_noop("Sets the maximum time to wait for WAL replication."),
+                       NULL,
+                       GUC_UNIT_MS
+               },
+               &replication_timeout,
+               60 * 1000, 0, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1862,7 +2007,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &CommitDelay,
-               0, 0, 100000, NULL, NULL
+               0, 0, 100000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1872,7 +2018,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &CommitSiblings,
-               5, 0, 1000, NULL, NULL
+               5, 0, 1000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1883,7 +2030,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
        },
 
        {
@@ -1894,7 +2042,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &log_min_duration_statement,
-               -1, -1, INT_MAX / 1000, NULL, NULL
+               -1, -1, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1905,7 +2054,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &Log_autovacuum_min_duration,
-               -1, -1, INT_MAX / 1000, NULL, NULL
+               -1, -1, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -1915,7 +2065,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MS
                },
                &BgWriterDelay,
-               200, 10, 10000, NULL, NULL
+               200, 10, 10000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1924,7 +2075,8 @@ static struct config_int ConfigureNamesInt[] =
                        NULL
                },
                &bgwriter_lru_maxpages,
-               100, 0, 1000, NULL, NULL
+               100, 0, 1000,
+               NULL, NULL, NULL
        },
 
        {
@@ -1944,7 +2096,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
        },
 
        {
@@ -1954,7 +2106,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
        },
 
        {
@@ -1964,7 +2117,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
        },
 
        {
@@ -1974,7 +2128,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
        },
 
        {
@@ -1984,7 +2139,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
        },
 
        {
@@ -1994,7 +2150,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
        },
 
        {
@@ -2004,7 +2161,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
        },
 
        {
@@ -2014,7 +2172,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
        },
 
        {
@@ -2024,7 +2183,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
        },
 
        {
@@ -2037,7 +2197,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
        },
 
        {
@@ -2047,7 +2207,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,
@@ -2055,7 +2216,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,
@@ -2063,7 +2225,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 */
@@ -2073,7 +2236,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 */
@@ -2082,7 +2246,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
        },
 
        {
@@ -2092,7 +2257,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
        },
 
        {
@@ -2102,7 +2268,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
        },
 
        {
@@ -2112,7 +2279,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
        },
 
        {
@@ -2123,7 +2291,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
        },
 
        {
@@ -2133,7 +2302,8 @@ static struct config_int ConfigureNamesInt[] =
                        0
                },
                &GinFuzzySearchLimit,
-               0, 0, INT_MAX, NULL, NULL
+               0, 0, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -2145,7 +2315,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
        },
 
        {
@@ -2156,7 +2327,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
        },
 
        {
@@ -2166,7 +2338,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
        },
 
        {
@@ -2175,12 +2348,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
        }
 };
 
@@ -2194,7 +2368,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,
@@ -2203,7 +2378,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,
@@ -2212,7 +2388,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,
@@ -2221,7 +2398,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,
@@ -2230,7 +2408,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
        },
 
        {
@@ -2240,7 +2419,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
        },
 
        {
@@ -2249,8 +2429,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,
@@ -2258,7 +2439,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
        },
 
        {
@@ -2267,7 +2449,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
        },
 
        {
@@ -2277,7 +2460,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
        },
 
        {
@@ -2286,7 +2470,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,
@@ -2294,7 +2479,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
        },
 
        {
@@ -2303,12 +2489,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
        }
 };
 
@@ -2321,7 +2508,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &XLogArchiveCommand,
-               "", NULL, show_archive_command
+               "",
+               NULL, NULL, show_archive_command
        },
 
        {
@@ -2331,7 +2519,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
        },
 
        {
@@ -2340,7 +2529,8 @@ static struct config_string ConfigureNamesString[] =
                        gettext_noop("If blank, no prefix is used.")
                },
                &Log_line_prefix,
-               "", NULL, NULL
+               "",
+               NULL, NULL, NULL
        },
 
        {
@@ -2349,7 +2539,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
        },
 
        {
@@ -2360,7 +2551,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
        },
 
        {
@@ -2370,7 +2562,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_IS_NAME
                },
                &default_tablespace,
-               "", assign_default_tablespace, NULL
+               "",
+               check_default_tablespace, NULL, NULL
        },
 
        {
@@ -2380,7 +2573,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
        },
 
        {
@@ -2393,7 +2587,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_SUPERUSER_ONLY
                },
                &Dynamic_library_path,
-               "$libdir", NULL, NULL
+               "$libdir",
+               NULL, NULL, NULL
        },
 
        {
@@ -2403,7 +2598,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_SUPERUSER_ONLY
                },
                &pg_krb_server_keyfile,
-               PG_KRB_SRVTAB, NULL, NULL
+               PG_KRB_SRVTAB,
+               NULL, NULL, NULL
        },
 
        {
@@ -2412,7 +2608,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &pg_krb_srvnam,
-               PG_KRB_SRVNAM, NULL, NULL
+               PG_KRB_SRVNAM,
+               NULL, NULL, NULL
        },
 
        {
@@ -2421,7 +2618,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 */
@@ -2433,7 +2631,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
                },
                &locale_collate,
-               "C", NULL, NULL
+               "C",
+               NULL, NULL, NULL
        },
 
        {
@@ -2443,7 +2642,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
                },
                &locale_ctype,
-               "C", NULL, NULL
+               "C",
+               NULL, NULL, NULL
        },
 
        {
@@ -2452,7 +2652,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &locale_messages,
-               "", locale_messages_assign, NULL
+               "",
+               check_locale_messages, assign_locale_messages, NULL
        },
 
        {
@@ -2461,7 +2662,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &locale_monetary,
-               "C", locale_monetary_assign, NULL
+               "C",
+               check_locale_monetary, assign_locale_monetary, NULL
        },
 
        {
@@ -2470,7 +2672,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &locale_numeric,
-               "C", locale_numeric_assign, NULL
+               "C",
+               check_locale_numeric, assign_locale_numeric, NULL
        },
 
        {
@@ -2479,7 +2682,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &locale_time,
-               "C", locale_time_assign, NULL
+               "C",
+               check_locale_time, assign_locale_time, NULL
        },
 
        {
@@ -2489,7 +2693,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
                },
                &shared_preload_libraries_string,
-               "", NULL, NULL
+               "",
+               NULL, NULL, NULL
        },
 
        {
@@ -2499,7 +2704,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_LIST_INPUT | GUC_LIST_QUOTE
                },
                &local_preload_libraries_string,
-               "", NULL, NULL
+               "",
+               NULL, NULL, NULL
        },
 
        {
@@ -2509,7 +2715,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
        },
 
        {
@@ -2520,7 +2727,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
        },
 
        {
@@ -2531,7 +2739,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
        },
 
        {
@@ -2542,7 +2751,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
        },
 
        {
@@ -2553,7 +2763,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
        },
 
        {
@@ -2565,7 +2776,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,
@@ -2575,7 +2787,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,
@@ -2584,7 +2797,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
        },
 
        {
@@ -2594,7 +2808,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &syslog_ident_str,
-               "postgres", assign_syslog_ident, NULL
+               "postgres",
+               NULL, assign_syslog_ident, NULL
        },
 
        {
@@ -2604,7 +2819,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,
@@ -2612,7 +2828,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &timezone_abbreviations_string,
-               "UNKNOWN", assign_timezone_abbreviations, NULL
+               NULL,
+               check_timezone_abbreviations, assign_timezone_abbreviations, NULL
        },
 
        {
@@ -2622,7 +2839,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
        },
 
        {
@@ -2632,7 +2850,8 @@ static struct config_string ConfigureNamesString[] =
                                                 "that starts the server.")
                },
                &Unix_socket_group,
-               "", NULL, NULL
+               "",
+               NULL, NULL, NULL
        },
 
        {
@@ -2642,7 +2861,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_SUPERUSER_ONLY
                },
                &UnixSocketDir,
-               "", assign_canonical_path, NULL
+               "",
+               check_canonical_path, NULL, NULL
        },
 
        {
@@ -2652,7 +2872,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_LIST_INPUT
                },
                &ListenAddresses,
-               "localhost", NULL, NULL
+               "localhost",
+               NULL, NULL, NULL
        },
 
        {
@@ -2662,7 +2883,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
        },
 
        {
@@ -2672,6 +2894,7 @@ static struct config_string ConfigureNamesString[] =
                        GUC_SUPERUSER_ONLY
                },
                &data_directory,
+               NULL,
                NULL, NULL, NULL
        },
 
@@ -2682,6 +2905,7 @@ static struct config_string ConfigureNamesString[] =
                        GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
                },
                &ConfigFileName,
+               NULL,
                NULL, NULL, NULL
        },
 
@@ -2692,6 +2916,7 @@ static struct config_string ConfigureNamesString[] =
                        GUC_SUPERUSER_ONLY
                },
                &HbaFileName,
+               NULL,
                NULL, NULL, NULL
        },
 
@@ -2702,6 +2927,7 @@ static struct config_string ConfigureNamesString[] =
                        GUC_SUPERUSER_ONLY
                },
                &IdentFileName,
+               NULL,
                NULL, NULL, NULL
        },
 
@@ -2712,7 +2938,8 @@ static struct config_string ConfigureNamesString[] =
                        GUC_SUPERUSER_ONLY
                },
                &external_pid_file,
-               NULL, assign_canonical_path, NULL
+               NULL,
+               check_canonical_path, NULL, NULL
        },
 
        {
@@ -2722,17 +2949,19 @@ 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
        },
 
        {
                {"synchronous_standby_names", PGC_SIGHUP, WAL_REPLICATION,
-                       gettext_noop("List of potential standby names to synchronise with."),
+                       gettext_noop("List of potential standby names to synchronize with."),
                        NULL,
                        GUC_LIST_INPUT
                },
                &SyncRepStandbyNames,
-               "", assign_synchronous_standby_names, NULL
+               "",
+               check_synchronous_standby_names, NULL, NULL
        },
 
        {
@@ -2741,7 +2970,8 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &TSCurrentConfig,
-               "pg_catalog.simple", assignTSCurrentConfig, NULL
+               "pg_catalog.simple",
+               check_TSCurrentConfig, assign_TSCurrentConfig, NULL
        },
 
        {
@@ -2756,7 +2986,7 @@ static struct config_string ConfigureNamesString[] =
 #else
                "none",
 #endif
-               NULL, NULL
+               NULL, NULL, NULL
        },
 
        {
@@ -2766,12 +2996,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
        }
 };
 
@@ -2784,7 +3015,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
        },
 
        {
@@ -2793,7 +3025,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
        },
 
        {
@@ -2803,7 +3036,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
        },
 
        {
@@ -2814,7 +3048,7 @@ static struct config_enum ConfigureNamesEnum[] =
                },
                &constraint_exclusion,
                CONSTRAINT_EXCLUSION_PARTITION, constraint_exclusion_options,
-               NULL, NULL
+               NULL, NULL, NULL
        },
 
        {
@@ -2823,7 +3057,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
        },
 
        {
@@ -2833,7 +3068,8 @@ static struct config_enum ConfigureNamesEnum[] =
                        GUC_REPORT
                },
                &IntervalStyle,
-               INTSTYLE_POSTGRES, intervalstyle_options, NULL, NULL
+               INTSTYLE_POSTGRES, intervalstyle_options,
+               NULL, NULL, NULL
        },
 
        {
@@ -2842,7 +3078,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
        },
 
        {
@@ -2852,7 +3089,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
        },
 
        {
@@ -2862,7 +3100,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
        },
 
        {
@@ -2871,7 +3110,8 @@ static struct config_enum ConfigureNamesEnum[] =
                        NULL
                },
                &log_statement,
-               LOGSTMT_NONE, log_statement_options, NULL, NULL
+               LOGSTMT_NONE, log_statement_options,
+               NULL, NULL, NULL
        },
 
        {
@@ -2885,7 +3125,8 @@ static struct config_enum ConfigureNamesEnum[] =
 #else
                0,
 #endif
-               syslog_facility_options, assign_syslog_facility, NULL
+               syslog_facility_options,
+               NULL, assign_syslog_facility, NULL
        },
 
        {
@@ -2895,7 +3136,17 @@ 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
+       },
+
+       {
+               {"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
+                       gettext_noop("Sets the current transaction's synchronization level."),
+                       NULL
+               },
+               &synchronous_commit,
+               SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
+               NULL, NULL, NULL
        },
 
        {
@@ -2905,11 +3156,13 @@ static struct config_enum ConfigureNamesEnum[] =
                                                 " the level, the fewer messages are sent.")
                },
                &trace_recovery_messages,
+
                /*
-                * client_message_level_options allows too many values, really,
-                * but it's not worth having a separate options array for this.
+                * 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
        },
 
        {
@@ -2918,7 +3171,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
        },
 
        {
@@ -2927,7 +3181,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
        },
 
        {
@@ -2937,7 +3192,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
        },
 
        {
@@ -2946,7 +3201,8 @@ static struct config_enum ConfigureNamesEnum[] =
                        NULL
                },
                &xmlbinary,
-               XMLBINARY_BASE64, xmlbinary_options, NULL, NULL
+               XMLBINARY_BASE64, xmlbinary_options,
+               NULL, NULL, NULL
        },
 
        {
@@ -2956,13 +3212,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
        }
 };
 
@@ -3003,13 +3260,13 @@ static int      GUCNestLevel = 0;       /* 1 when in main transaction */
 
 static int     guc_var_compare(const void *a, const void *b);
 static int     guc_name_compare(const char *namea, const char *nameb);
+static void InitializeGUCOptionsFromEnvironment(void);
 static void InitializeOneGUCOption(struct config_generic * gconf);
 static void push_old_value(struct config_generic * gconf, GucAction action);
 static void ReportGUCOption(struct config_generic * record);
 static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
 static void ShowAllGUCConfig(DestReceiver *dest);
 static char *_ShowOption(struct config_generic * record, bool use_units);
-static bool is_newvalue_equal(struct config_generic * record, const char *newvalue);
 static bool validate_option_array_item(const char *name, const char *value,
                                                   bool skipIfNoPermissions);
 
@@ -3058,6 +3315,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).
@@ -3066,87 +3344,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)
        {
-               if (strval == stack->prior.stringval ||
-                       strval == stack->masked.stringval)
+               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 (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_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, union config_var_value * val)
+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)
        {
@@ -3158,10 +3468,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);
 }
 
 
@@ -3493,8 +3804,6 @@ void
 InitializeGUCOptions(void)
 {
        int                     i;
-       char       *env;
-       long            stack_rlimit;
 
        /*
         * Before log_line_prefix could possibly receive a nonempty setting, make
@@ -3533,9 +3842,25 @@ InitializeGUCOptions(void)
 
        /*
         * For historical reasons, some GUC parameters can receive defaults from
-        * environment variables.  Process those settings.      NB: if you add or
-        * remove anything here, see also ProcessConfigFile().
+        * environment variables.  Process those settings.
         */
+       InitializeGUCOptionsFromEnvironment();
+}
+
+/*
+ * Assign any GUC values that can come from the server's environment.
+ *
+ * This is called from InitializeGUCOptions, and also from ProcessConfigFile
+ * to deal with the possibility that a setting has been removed from
+ * postgresql.conf and should now get a value from the environment.
+ * (The latter is a kludge that should probably go away someday; if so,
+ * fold this back into InitializeGUCOptions.)
+ */
+static void
+InitializeGUCOptionsFromEnvironment(void)
+{
+       char       *env;
+       long            stack_rlimit;
 
        env = getenv("PGPORT");
        if (env != NULL)
@@ -3573,6 +3898,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)
@@ -3581,6 +3909,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;
 
@@ -3589,96 +3918,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;
                        }
        }
@@ -3867,11 +4191,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:
@@ -3879,11 +4203,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:
@@ -3891,40 +4215,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:
@@ -3932,12 +4239,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;
                                }
                }
@@ -4188,7 +4494,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)
@@ -4207,16 +4513,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;
@@ -4224,16 +4531,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;
@@ -4241,16 +4549,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;
@@ -4258,33 +4567,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;
                                                        }
 
@@ -4294,30 +4587,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;
                        }
 
@@ -4727,33 +5026,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
@@ -4789,6 +5061,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)
@@ -4825,15 +5098,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),
@@ -4846,19 +5125,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),
@@ -5001,6 +5284,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)
                                {
@@ -5012,32 +5296,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)
@@ -5047,17 +5344,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;
                        }
 
@@ -5065,6 +5370,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)
                                {
@@ -5087,32 +5393,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)
@@ -5122,17 +5441,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;
                        }
 
@@ -5140,6 +5467,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)
                                {
@@ -5159,32 +5487,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)
@@ -5194,17 +5535,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;
                        }
 
@@ -5212,95 +5561,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;
@@ -5308,27 +5650,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)
                                {
@@ -5350,33 +5702,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)
@@ -5386,17 +5750,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;
                        }
        }
@@ -5557,51 +5929,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.
@@ -6013,6 +6340,7 @@ define_custom_variable(struct config_generic * variable)
        switch (pHolder->gen.source)
        {
                case PGC_S_DEFAULT:
+               case PGC_S_DYNAMIC_DEFAULT:
                case PGC_S_ENV_VAR:
                case PGC_S_FILE:
                case PGC_S_ARGV:
@@ -6094,6 +6422,7 @@ DefineCustomBoolVariable(const char *name,
                                                 bool bootValue,
                                                 GucContext context,
                                                 int flags,
+                                                GucBoolCheckHook check_hook,
                                                 GucBoolAssignHook assign_hook,
                                                 GucShowHook show_hook)
 {
@@ -6105,6 +6434,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);
@@ -6120,6 +6450,7 @@ DefineCustomIntVariable(const char *name,
                                                int maxValue,
                                                GucContext context,
                                                int flags,
+                                               GucIntCheckHook check_hook,
                                                GucIntAssignHook assign_hook,
                                                GucShowHook show_hook)
 {
@@ -6133,6 +6464,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);
@@ -6148,6 +6480,7 @@ DefineCustomRealVariable(const char *name,
                                                 double maxValue,
                                                 GucContext context,
                                                 int flags,
+                                                GucRealCheckHook check_hook,
                                                 GucRealAssignHook assign_hook,
                                                 GucShowHook show_hook)
 {
@@ -6161,6 +6494,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);
@@ -6174,6 +6508,7 @@ DefineCustomStringVariable(const char *name,
                                                   const char *bootValue,
                                                   GucContext context,
                                                   int flags,
+                                                  GucStringCheckHook check_hook,
                                                   GucStringAssignHook assign_hook,
                                                   GucShowHook show_hook)
 {
@@ -6184,9 +6519,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);
@@ -6201,6 +6534,7 @@ DefineCustomEnumVariable(const char *name,
                                                 const struct config_enum_entry * options,
                                                 GucContext context,
                                                 int flags,
+                                                GucEnumCheckHook check_hook,
                                                 GucEnumAssignHook assign_hook,
                                                 GucShowHook show_hook)
 {
@@ -6213,6 +6547,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);
@@ -6974,67 +7309,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
 
 /*
@@ -7652,30 +7926,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)
@@ -7696,105 +8162,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 bool
-assign_syslog_facility(int newval, bool doit, GucSource source)
+static void
+assign_log_destination(const char *newval, void *extra)
+{
+       Log_destination = *((int *) extra);
+}
+
+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 temporary 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')
        {
@@ -7823,7 +8287,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++;
@@ -7834,21 +8298,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
@@ -7856,14 +8319,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
@@ -7871,14 +8332,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
@@ -7886,92 +8345,81 @@ 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".
-        * 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
-        * avoid wasting cycles loading values that might soon be overridden from
-        * the config file, and to avoid trying to read the timezone abbrev files
+        * 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 avoid
+        * wasting cycles loading values that might soon be overridden from 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);
 }
 
 /*
@@ -7979,15 +8427,13 @@ assign_timezone_abbreviations(const char *newval, bool doit, GucSource source)
  *
  * This is called after initial loading of postgresql.conf.  If no
  * timezone_abbreviations setting was found therein, select default.
+ * If a non-default value is already installed, nothing will happen.
  */
 void
 pg_timezone_abbrev_initialize(void)
 {
-       if (strcmp(timezone_abbreviations_string, "UNKNOWN") == 0)
-       {
-               SetConfigOption("timezone_abbreviations", "Default",
-                                               PGC_POSTMASTER, PGC_S_ARGV);
-       }
+       SetConfigOption("timezone_abbreviations", "Default",
+                                       PGC_POSTMASTER, PGC_S_DYNAMIC_DEFAULT);
 }
 
 static const char *
@@ -7999,54 +8445,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));
@@ -8054,31 +8507,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;
@@ -8087,6 +8544,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:
         *
@@ -8111,18 +8570,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
@@ -8132,57 +8594,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 *