LCOV - code coverage report
Current view: top level - src/backend/utils/misc - guc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 1926 2496 77.2 %
Date: 2019-09-22 08:06:49 Functions: 144 149 96.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*--------------------------------------------------------------------
       2             :  * guc.c
       3             :  *
       4             :  * Support for grand unified configuration scheme, including SET
       5             :  * command, configuration file, and command line options.
       6             :  * See src/backend/utils/misc/README for more information.
       7             :  *
       8             :  *
       9             :  * Copyright (c) 2000-2019, PostgreSQL Global Development Group
      10             :  * Written by Peter Eisentraut <peter_e@gmx.net>.
      11             :  *
      12             :  * IDENTIFICATION
      13             :  *    src/backend/utils/misc/guc.c
      14             :  *
      15             :  *--------------------------------------------------------------------
      16             :  */
      17             : #include "postgres.h"
      18             : 
      19             : #include <ctype.h>
      20             : #include <float.h>
      21             : #include <math.h>
      22             : #include <limits.h>
      23             : #include <unistd.h>
      24             : #include <sys/stat.h>
      25             : #ifdef HAVE_SYSLOG
      26             : #include <syslog.h>
      27             : #endif
      28             : 
      29             : #include "access/commit_ts.h"
      30             : #include "access/gin.h"
      31             : #include "access/rmgr.h"
      32             : #include "access/tableam.h"
      33             : #include "access/transam.h"
      34             : #include "access/twophase.h"
      35             : #include "access/xact.h"
      36             : #include "access/xlog_internal.h"
      37             : #include "catalog/namespace.h"
      38             : #include "catalog/pg_authid.h"
      39             : #include "commands/async.h"
      40             : #include "commands/prepare.h"
      41             : #include "commands/user.h"
      42             : #include "commands/vacuum.h"
      43             : #include "commands/variable.h"
      44             : #include "commands/trigger.h"
      45             : #include "common/string.h"
      46             : #include "funcapi.h"
      47             : #include "jit/jit.h"
      48             : #include "libpq/auth.h"
      49             : #include "libpq/libpq.h"
      50             : #include "libpq/pqformat.h"
      51             : #include "miscadmin.h"
      52             : #include "optimizer/cost.h"
      53             : #include "optimizer/geqo.h"
      54             : #include "optimizer/optimizer.h"
      55             : #include "optimizer/paths.h"
      56             : #include "optimizer/planmain.h"
      57             : #include "parser/parse_expr.h"
      58             : #include "parser/parse_type.h"
      59             : #include "parser/parser.h"
      60             : #include "parser/scansup.h"
      61             : #include "pgstat.h"
      62             : #include "postmaster/autovacuum.h"
      63             : #include "postmaster/bgworker_internals.h"
      64             : #include "postmaster/bgwriter.h"
      65             : #include "postmaster/postmaster.h"
      66             : #include "postmaster/syslogger.h"
      67             : #include "postmaster/walwriter.h"
      68             : #include "replication/logicallauncher.h"
      69             : #include "replication/slot.h"
      70             : #include "replication/syncrep.h"
      71             : #include "replication/walreceiver.h"
      72             : #include "replication/walsender.h"
      73             : #include "storage/bufmgr.h"
      74             : #include "storage/dsm_impl.h"
      75             : #include "storage/standby.h"
      76             : #include "storage/fd.h"
      77             : #include "storage/large_object.h"
      78             : #include "storage/pg_shmem.h"
      79             : #include "storage/proc.h"
      80             : #include "storage/predicate.h"
      81             : #include "tcop/tcopprot.h"
      82             : #include "tsearch/ts_cache.h"
      83             : #include "utils/builtins.h"
      84             : #include "utils/bytea.h"
      85             : #include "utils/guc_tables.h"
      86             : #include "utils/float.h"
      87             : #include "utils/memutils.h"
      88             : #include "utils/pg_locale.h"
      89             : #include "utils/pg_lsn.h"
      90             : #include "utils/plancache.h"
      91             : #include "utils/portal.h"
      92             : #include "utils/ps_status.h"
      93             : #include "utils/rls.h"
      94             : #include "utils/snapmgr.h"
      95             : #include "utils/tzparser.h"
      96             : #include "utils/varlena.h"
      97             : #include "utils/xml.h"
      98             : 
      99             : #ifndef PG_KRB_SRVTAB
     100             : #define PG_KRB_SRVTAB ""
     101             : #endif
     102             : 
     103             : #define CONFIG_FILENAME "postgresql.conf"
     104             : #define HBA_FILENAME    "pg_hba.conf"
     105             : #define IDENT_FILENAME  "pg_ident.conf"
     106             : 
     107             : #ifdef EXEC_BACKEND
     108             : #define CONFIG_EXEC_PARAMS "global/config_exec_params"
     109             : #define CONFIG_EXEC_PARAMS_NEW "global/config_exec_params.new"
     110             : #endif
     111             : 
     112             : /*
     113             :  * Precision with which REAL type guc values are to be printed for GUC
     114             :  * serialization.
     115             :  */
     116             : #define REALTYPE_PRECISION 17
     117             : 
     118             : /* XXX these should appear in other modules' header files */
     119             : extern bool Log_disconnections;
     120             : extern int  CommitDelay;
     121             : extern int  CommitSiblings;
     122             : extern char *default_tablespace;
     123             : extern char *temp_tablespaces;
     124             : extern bool ignore_checksum_failure;
     125             : extern bool synchronize_seqscans;
     126             : 
     127             : #ifdef TRACE_SYNCSCAN
     128             : extern bool trace_syncscan;
     129             : #endif
     130             : #ifdef DEBUG_BOUNDED_SORT
     131             : extern bool optimize_bounded_sort;
     132             : #endif
     133             : 
     134             : static int  GUC_check_errcode_value;
     135             : 
     136             : /* global variables for check hook support */
     137             : char       *GUC_check_errmsg_string;
     138             : char       *GUC_check_errdetail_string;
     139             : char       *GUC_check_errhint_string;
     140             : 
     141             : static void do_serialize(char **destptr, Size *maxbytes, const char *fmt,...) pg_attribute_printf(3, 4);
     142             : 
     143             : static void set_config_sourcefile(const char *name, char *sourcefile,
     144             :                                   int sourceline);
     145             : static bool call_bool_check_hook(struct config_bool *conf, bool *newval,
     146             :                                  void **extra, GucSource source, int elevel);
     147             : static bool call_int_check_hook(struct config_int *conf, int *newval,
     148             :                                 void **extra, GucSource source, int elevel);
     149             : static bool call_real_check_hook(struct config_real *conf, double *newval,
     150             :                                  void **extra, GucSource source, int elevel);
     151             : static bool call_string_check_hook(struct config_string *conf, char **newval,
     152             :                                    void **extra, GucSource source, int elevel);
     153             : static bool call_enum_check_hook(struct config_enum *conf, int *newval,
     154             :                                  void **extra, GucSource source, int elevel);
     155             : 
     156             : static bool check_log_destination(char **newval, void **extra, GucSource source);
     157             : static void assign_log_destination(const char *newval, void *extra);
     158             : 
     159             : static bool check_wal_consistency_checking(char **newval, void **extra,
     160             :                                            GucSource source);
     161             : static void assign_wal_consistency_checking(const char *newval, void *extra);
     162             : 
     163             : #ifdef HAVE_SYSLOG
     164             : static int  syslog_facility = LOG_LOCAL0;
     165             : #else
     166             : static int  syslog_facility = 0;
     167             : #endif
     168             : 
     169             : static void assign_syslog_facility(int newval, void *extra);
     170             : static void assign_syslog_ident(const char *newval, void *extra);
     171             : static void assign_session_replication_role(int newval, void *extra);
     172             : static bool check_temp_buffers(int *newval, void **extra, GucSource source);
     173             : static bool check_bonjour(bool *newval, void **extra, GucSource source);
     174             : static bool check_ssl(bool *newval, void **extra, GucSource source);
     175             : static bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
     176             : static bool check_log_stats(bool *newval, void **extra, GucSource source);
     177             : static bool check_canonical_path(char **newval, void **extra, GucSource source);
     178             : static bool check_timezone_abbreviations(char **newval, void **extra, GucSource source);
     179             : static void assign_timezone_abbreviations(const char *newval, void *extra);
     180             : static void pg_timezone_abbrev_initialize(void);
     181             : static const char *show_archive_command(void);
     182             : static void assign_tcp_keepalives_idle(int newval, void *extra);
     183             : static void assign_tcp_keepalives_interval(int newval, void *extra);
     184             : static void assign_tcp_keepalives_count(int newval, void *extra);
     185             : static void assign_tcp_user_timeout(int newval, void *extra);
     186             : static const char *show_tcp_keepalives_idle(void);
     187             : static const char *show_tcp_keepalives_interval(void);
     188             : static const char *show_tcp_keepalives_count(void);
     189             : static const char *show_tcp_user_timeout(void);
     190             : static bool check_maxconnections(int *newval, void **extra, GucSource source);
     191             : static bool check_max_worker_processes(int *newval, void **extra, GucSource source);
     192             : static bool check_autovacuum_max_workers(int *newval, void **extra, GucSource source);
     193             : static bool check_max_wal_senders(int *newval, void **extra, GucSource source);
     194             : static bool check_autovacuum_work_mem(int *newval, void **extra, GucSource source);
     195             : static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
     196             : static void assign_effective_io_concurrency(int newval, void *extra);
     197             : static void assign_pgstat_temp_directory(const char *newval, void *extra);
     198             : static bool check_application_name(char **newval, void **extra, GucSource source);
     199             : static void assign_application_name(const char *newval, void *extra);
     200             : static bool check_cluster_name(char **newval, void **extra, GucSource source);
     201             : static const char *show_unix_socket_permissions(void);
     202             : static const char *show_log_file_mode(void);
     203             : static const char *show_data_directory_mode(void);
     204             : static bool check_recovery_target_timeline(char **newval, void **extra, GucSource source);
     205             : static void assign_recovery_target_timeline(const char *newval, void *extra);
     206             : static bool check_recovery_target(char **newval, void **extra, GucSource source);
     207             : static void assign_recovery_target(const char *newval, void *extra);
     208             : static bool check_recovery_target_xid(char **newval, void **extra, GucSource source);
     209             : static void assign_recovery_target_xid(const char *newval, void *extra);
     210             : static bool check_recovery_target_time(char **newval, void **extra, GucSource source);
     211             : static void assign_recovery_target_time(const char *newval, void *extra);
     212             : static bool check_recovery_target_name(char **newval, void **extra, GucSource source);
     213             : static void assign_recovery_target_name(const char *newval, void *extra);
     214             : static bool check_recovery_target_lsn(char **newval, void **extra, GucSource source);
     215             : static void assign_recovery_target_lsn(const char *newval, void *extra);
     216             : static bool check_primary_slot_name(char **newval, void **extra, GucSource source);
     217             : static bool check_default_with_oids(bool *newval, void **extra, GucSource source);
     218             : 
     219             : /* Private functions in guc-file.l that need to be called from guc.c */
     220             : static ConfigVariable *ProcessConfigFileInternal(GucContext context,
     221             :                                                  bool applySettings, int elevel);
     222             : 
     223             : 
     224             : /*
     225             :  * Options for enum values defined in this module.
     226             :  *
     227             :  * NOTE! Option values may not contain double quotes!
     228             :  */
     229             : 
     230             : static const struct config_enum_entry bytea_output_options[] = {
     231             :     {"escape", BYTEA_OUTPUT_ESCAPE, false},
     232             :     {"hex", BYTEA_OUTPUT_HEX, false},
     233             :     {NULL, 0, false}
     234             : };
     235             : 
     236             : /*
     237             :  * We have different sets for client and server message level options because
     238             :  * they sort slightly different (see "log" level), and because "fatal"/"panic"
     239             :  * aren't sensible for client_min_messages.
     240             :  */
     241             : static const struct config_enum_entry client_message_level_options[] = {
     242             :     {"debug5", DEBUG5, false},
     243             :     {"debug4", DEBUG4, false},
     244             :     {"debug3", DEBUG3, false},
     245             :     {"debug2", DEBUG2, false},
     246             :     {"debug1", DEBUG1, false},
     247             :     {"debug", DEBUG2, true},
     248             :     {"log", LOG, false},
     249             :     {"info", INFO, true},
     250             :     {"notice", NOTICE, false},
     251             :     {"warning", WARNING, false},
     252             :     {"error", ERROR, false},
     253             :     {NULL, 0, false}
     254             : };
     255             : 
     256             : static const struct config_enum_entry server_message_level_options[] = {
     257             :     {"debug5", DEBUG5, false},
     258             :     {"debug4", DEBUG4, false},
     259             :     {"debug3", DEBUG3, false},
     260             :     {"debug2", DEBUG2, false},
     261             :     {"debug1", DEBUG1, false},
     262             :     {"debug", DEBUG2, true},
     263             :     {"info", INFO, false},
     264             :     {"notice", NOTICE, false},
     265             :     {"warning", WARNING, false},
     266             :     {"error", ERROR, false},
     267             :     {"log", LOG, false},
     268             :     {"fatal", FATAL, false},
     269             :     {"panic", PANIC, false},
     270             :     {NULL, 0, false}
     271             : };
     272             : 
     273             : static const struct config_enum_entry intervalstyle_options[] = {
     274             :     {"postgres", INTSTYLE_POSTGRES, false},
     275             :     {"postgres_verbose", INTSTYLE_POSTGRES_VERBOSE, false},
     276             :     {"sql_standard", INTSTYLE_SQL_STANDARD, false},
     277             :     {"iso_8601", INTSTYLE_ISO_8601, false},
     278             :     {NULL, 0, false}
     279             : };
     280             : 
     281             : static const struct config_enum_entry log_error_verbosity_options[] = {
     282             :     {"terse", PGERROR_TERSE, false},
     283             :     {"default", PGERROR_DEFAULT, false},
     284             :     {"verbose", PGERROR_VERBOSE, false},
     285             :     {NULL, 0, false}
     286             : };
     287             : 
     288             : static const struct config_enum_entry log_statement_options[] = {
     289             :     {"none", LOGSTMT_NONE, false},
     290             :     {"ddl", LOGSTMT_DDL, false},
     291             :     {"mod", LOGSTMT_MOD, false},
     292             :     {"all", LOGSTMT_ALL, false},
     293             :     {NULL, 0, false}
     294             : };
     295             : 
     296             : static const struct config_enum_entry isolation_level_options[] = {
     297             :     {"serializable", XACT_SERIALIZABLE, false},
     298             :     {"repeatable read", XACT_REPEATABLE_READ, false},
     299             :     {"read committed", XACT_READ_COMMITTED, false},
     300             :     {"read uncommitted", XACT_READ_UNCOMMITTED, false},
     301             :     {NULL, 0}
     302             : };
     303             : 
     304             : static const struct config_enum_entry session_replication_role_options[] = {
     305             :     {"origin", SESSION_REPLICATION_ROLE_ORIGIN, false},
     306             :     {"replica", SESSION_REPLICATION_ROLE_REPLICA, false},
     307             :     {"local", SESSION_REPLICATION_ROLE_LOCAL, false},
     308             :     {NULL, 0, false}
     309             : };
     310             : 
     311             : static const struct config_enum_entry syslog_facility_options[] = {
     312             : #ifdef HAVE_SYSLOG
     313             :     {"local0", LOG_LOCAL0, false},
     314             :     {"local1", LOG_LOCAL1, false},
     315             :     {"local2", LOG_LOCAL2, false},
     316             :     {"local3", LOG_LOCAL3, false},
     317             :     {"local4", LOG_LOCAL4, false},
     318             :     {"local5", LOG_LOCAL5, false},
     319             :     {"local6", LOG_LOCAL6, false},
     320             :     {"local7", LOG_LOCAL7, false},
     321             : #else
     322             :     {"none", 0, false},
     323             : #endif
     324             :     {NULL, 0}
     325             : };
     326             : 
     327             : static const struct config_enum_entry track_function_options[] = {
     328             :     {"none", TRACK_FUNC_OFF, false},
     329             :     {"pl", TRACK_FUNC_PL, false},
     330             :     {"all", TRACK_FUNC_ALL, false},
     331             :     {NULL, 0, false}
     332             : };
     333             : 
     334             : static const struct config_enum_entry xmlbinary_options[] = {
     335             :     {"base64", XMLBINARY_BASE64, false},
     336             :     {"hex", XMLBINARY_HEX, false},
     337             :     {NULL, 0, false}
     338             : };
     339             : 
     340             : static const struct config_enum_entry xmloption_options[] = {
     341             :     {"content", XMLOPTION_CONTENT, false},
     342             :     {"document", XMLOPTION_DOCUMENT, false},
     343             :     {NULL, 0, false}
     344             : };
     345             : 
     346             : /*
     347             :  * Although only "on", "off", and "safe_encoding" are documented, we
     348             :  * accept all the likely variants of "on" and "off".
     349             :  */
     350             : static const struct config_enum_entry backslash_quote_options[] = {
     351             :     {"safe_encoding", BACKSLASH_QUOTE_SAFE_ENCODING, false},
     352             :     {"on", BACKSLASH_QUOTE_ON, false},
     353             :     {"off", BACKSLASH_QUOTE_OFF, false},
     354             :     {"true", BACKSLASH_QUOTE_ON, true},
     355             :     {"false", BACKSLASH_QUOTE_OFF, true},
     356             :     {"yes", BACKSLASH_QUOTE_ON, true},
     357             :     {"no", BACKSLASH_QUOTE_OFF, true},
     358             :     {"1", BACKSLASH_QUOTE_ON, true},
     359             :     {"0", BACKSLASH_QUOTE_OFF, true},
     360             :     {NULL, 0, false}
     361             : };
     362             : 
     363             : /*
     364             :  * Although only "on", "off", and "partition" are documented, we
     365             :  * accept all the likely variants of "on" and "off".
     366             :  */
     367             : static const struct config_enum_entry constraint_exclusion_options[] = {
     368             :     {"partition", CONSTRAINT_EXCLUSION_PARTITION, false},
     369             :     {"on", CONSTRAINT_EXCLUSION_ON, false},
     370             :     {"off", CONSTRAINT_EXCLUSION_OFF, false},
     371             :     {"true", CONSTRAINT_EXCLUSION_ON, true},
     372             :     {"false", CONSTRAINT_EXCLUSION_OFF, true},
     373             :     {"yes", CONSTRAINT_EXCLUSION_ON, true},
     374             :     {"no", CONSTRAINT_EXCLUSION_OFF, true},
     375             :     {"1", CONSTRAINT_EXCLUSION_ON, true},
     376             :     {"0", CONSTRAINT_EXCLUSION_OFF, true},
     377             :     {NULL, 0, false}
     378             : };
     379             : 
     380             : /*
     381             :  * Although only "on", "off", "remote_apply", "remote_write", and "local" are
     382             :  * documented, we accept all the likely variants of "on" and "off".
     383             :  */
     384             : static const struct config_enum_entry synchronous_commit_options[] = {
     385             :     {"local", SYNCHRONOUS_COMMIT_LOCAL_FLUSH, false},
     386             :     {"remote_write", SYNCHRONOUS_COMMIT_REMOTE_WRITE, false},
     387             :     {"remote_apply", SYNCHRONOUS_COMMIT_REMOTE_APPLY, false},
     388             :     {"on", SYNCHRONOUS_COMMIT_ON, false},
     389             :     {"off", SYNCHRONOUS_COMMIT_OFF, false},
     390             :     {"true", SYNCHRONOUS_COMMIT_ON, true},
     391             :     {"false", SYNCHRONOUS_COMMIT_OFF, true},
     392             :     {"yes", SYNCHRONOUS_COMMIT_ON, true},
     393             :     {"no", SYNCHRONOUS_COMMIT_OFF, true},
     394             :     {"1", SYNCHRONOUS_COMMIT_ON, true},
     395             :     {"0", SYNCHRONOUS_COMMIT_OFF, true},
     396             :     {NULL, 0, false}
     397             : };
     398             : 
     399             : /*
     400             :  * Although only "on", "off", "try" are documented, we accept all the likely
     401             :  * variants of "on" and "off".
     402             :  */
     403             : static const struct config_enum_entry huge_pages_options[] = {
     404             :     {"off", HUGE_PAGES_OFF, false},
     405             :     {"on", HUGE_PAGES_ON, false},
     406             :     {"try", HUGE_PAGES_TRY, false},
     407             :     {"true", HUGE_PAGES_ON, true},
     408             :     {"false", HUGE_PAGES_OFF, true},
     409             :     {"yes", HUGE_PAGES_ON, true},
     410             :     {"no", HUGE_PAGES_OFF, true},
     411             :     {"1", HUGE_PAGES_ON, true},
     412             :     {"0", HUGE_PAGES_OFF, true},
     413             :     {NULL, 0, false}
     414             : };
     415             : 
     416             : static const struct config_enum_entry force_parallel_mode_options[] = {
     417             :     {"off", FORCE_PARALLEL_OFF, false},
     418             :     {"on", FORCE_PARALLEL_ON, false},
     419             :     {"regress", FORCE_PARALLEL_REGRESS, false},
     420             :     {"true", FORCE_PARALLEL_ON, true},
     421             :     {"false", FORCE_PARALLEL_OFF, true},
     422             :     {"yes", FORCE_PARALLEL_ON, true},
     423             :     {"no", FORCE_PARALLEL_OFF, true},
     424             :     {"1", FORCE_PARALLEL_ON, true},
     425             :     {"0", FORCE_PARALLEL_OFF, true},
     426             :     {NULL, 0, false}
     427             : };
     428             : 
     429             : static const struct config_enum_entry plan_cache_mode_options[] = {
     430             :     {"auto", PLAN_CACHE_MODE_AUTO, false},
     431             :     {"force_generic_plan", PLAN_CACHE_MODE_FORCE_GENERIC_PLAN, false},
     432             :     {"force_custom_plan", PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN, false},
     433             :     {NULL, 0, false}
     434             : };
     435             : 
     436             : /*
     437             :  * password_encryption used to be a boolean, so accept all the likely
     438             :  * variants of "on", too. "off" used to store passwords in plaintext,
     439             :  * but we don't support that anymore.
     440             :  */
     441             : static const struct config_enum_entry password_encryption_options[] = {
     442             :     {"md5", PASSWORD_TYPE_MD5, false},
     443             :     {"scram-sha-256", PASSWORD_TYPE_SCRAM_SHA_256, false},
     444             :     {"on", PASSWORD_TYPE_MD5, true},
     445             :     {"true", PASSWORD_TYPE_MD5, true},
     446             :     {"yes", PASSWORD_TYPE_MD5, true},
     447             :     {"1", PASSWORD_TYPE_MD5, true},
     448             :     {NULL, 0, false}
     449             : };
     450             : 
     451             : const struct config_enum_entry ssl_protocol_versions_info[] = {
     452             :     {"", PG_TLS_ANY, false},
     453             :     {"TLSv1", PG_TLS1_VERSION, false},
     454             :     {"TLSv1.1", PG_TLS1_1_VERSION, false},
     455             :     {"TLSv1.2", PG_TLS1_2_VERSION, false},
     456             :     {"TLSv1.3", PG_TLS1_3_VERSION, false},
     457             :     {NULL, 0, false}
     458             : };
     459             : 
     460             : static struct config_enum_entry shared_memory_options[] = {
     461             : #ifndef WIN32
     462             :     {"sysv", SHMEM_TYPE_SYSV, false},
     463             : #endif
     464             : #ifndef EXEC_BACKEND
     465             :     {"mmap", SHMEM_TYPE_MMAP, false},
     466             : #endif
     467             : #ifdef WIN32
     468             :     {"windows", SHMEM_TYPE_WINDOWS, false},
     469             : #endif
     470             :     {NULL, 0, false}
     471             : };
     472             : 
     473             : /*
     474             :  * Options for enum values stored in other modules
     475             :  */
     476             : extern const struct config_enum_entry wal_level_options[];
     477             : extern const struct config_enum_entry archive_mode_options[];
     478             : extern const struct config_enum_entry recovery_target_action_options[];
     479             : extern const struct config_enum_entry sync_method_options[];
     480             : extern const struct config_enum_entry dynamic_shared_memory_options[];
     481             : 
     482             : /*
     483             :  * GUC option variables that are exported from this module
     484             :  */
     485             : bool        log_duration = false;
     486             : bool        Debug_print_plan = false;
     487             : bool        Debug_print_parse = false;
     488             : bool        Debug_print_rewritten = false;
     489             : bool        Debug_pretty_print = true;
     490             : 
     491             : bool        log_parser_stats = false;
     492             : bool        log_planner_stats = false;
     493             : bool        log_executor_stats = false;
     494             : bool        log_statement_stats = false;    /* this is sort of all three above
     495             :                                              * together */
     496             : bool        log_btree_build_stats = false;
     497             : char       *event_source;
     498             : 
     499             : bool        row_security;
     500             : bool        check_function_bodies = true;
     501             : 
     502             : /*
     503             :  * This GUC exists solely for backward compatibility, check its definition for
     504             :  * details.
     505             :  */
     506             : bool        default_with_oids = false;
     507             : bool        session_auth_is_superuser;
     508             : 
     509             : int         log_min_error_statement = ERROR;
     510             : int         log_min_messages = WARNING;
     511             : int         client_min_messages = NOTICE;
     512             : int         log_min_duration_statement = -1;
     513             : int         log_temp_files = -1;
     514             : double      log_xact_sample_rate = 0;
     515             : int         trace_recovery_messages = LOG;
     516             : 
     517             : int         temp_file_limit = -1;
     518             : 
     519             : int         num_temp_buffers = 1024;
     520             : 
     521             : char       *cluster_name = "";
     522             : char       *ConfigFileName;
     523             : char       *HbaFileName;
     524             : char       *IdentFileName;
     525             : char       *external_pid_file;
     526             : 
     527             : char       *pgstat_temp_directory;
     528             : 
     529             : char       *application_name;
     530             : 
     531             : int         tcp_keepalives_idle;
     532             : int         tcp_keepalives_interval;
     533             : int         tcp_keepalives_count;
     534             : int         tcp_user_timeout;
     535             : 
     536             : /*
     537             :  * SSL renegotiation was been removed in PostgreSQL 9.5, but we tolerate it
     538             :  * being set to zero (meaning never renegotiate) for backward compatibility.
     539             :  * This avoids breaking compatibility with clients that have never supported
     540             :  * renegotiation and therefore always try to zero it.
     541             :  */
     542             : int         ssl_renegotiation_limit;
     543             : 
     544             : /*
     545             :  * This really belongs in pg_shmem.c, but is defined here so that it doesn't
     546             :  * need to be duplicated in all the different implementations of pg_shmem.c.
     547             :  */
     548             : int         huge_pages;
     549             : 
     550             : /*
     551             :  * These variables are all dummies that don't do anything, except in some
     552             :  * cases provide the value for SHOW to display.  The real state is elsewhere
     553             :  * and is kept in sync by assign_hooks.
     554             :  */
     555             : static char *syslog_ident_str;
     556             : static double phony_random_seed;
     557             : static char *client_encoding_string;
     558             : static char *datestyle_string;
     559             : static char *locale_collate;
     560             : static char *locale_ctype;
     561             : static char *server_encoding_string;
     562             : static char *server_version_string;
     563             : static int  server_version_num;
     564             : static char *timezone_string;
     565             : static char *log_timezone_string;
     566             : static char *timezone_abbreviations_string;
     567             : static char *data_directory;
     568             : static char *session_authorization_string;
     569             : static int  max_function_args;
     570             : static int  max_index_keys;
     571             : static int  max_identifier_length;
     572             : static int  block_size;
     573             : static int  segment_size;
     574             : static int  wal_block_size;
     575             : static bool data_checksums;
     576             : static bool integer_datetimes;
     577             : static bool assert_enabled;
     578             : static char *recovery_target_timeline_string;
     579             : static char *recovery_target_string;
     580             : static char *recovery_target_xid_string;
     581             : static char *recovery_target_name_string;
     582             : static char *recovery_target_lsn_string;
     583             : 
     584             : 
     585             : /* should be static, but commands/variable.c needs to get at this */
     586             : char       *role_string;
     587             : 
     588             : 
     589             : /*
     590             :  * Displayable names for context types (enum GucContext)
     591             :  *
     592             :  * Note: these strings are deliberately not localized.
     593             :  */
     594             : const char *const GucContext_Names[] =
     595             : {
     596             :      /* PGC_INTERNAL */ "internal",
     597             :      /* PGC_POSTMASTER */ "postmaster",
     598             :      /* PGC_SIGHUP */ "sighup",
     599             :      /* PGC_SU_BACKEND */ "superuser-backend",
     600             :      /* PGC_BACKEND */ "backend",
     601             :      /* PGC_SUSET */ "superuser",
     602             :      /* PGC_USERSET */ "user"
     603             : };
     604             : 
     605             : /*
     606             :  * Displayable names for source types (enum GucSource)
     607             :  *
     608             :  * Note: these strings are deliberately not localized.
     609             :  */
     610             : const char *const GucSource_Names[] =
     611             : {
     612             :      /* PGC_S_DEFAULT */ "default",
     613             :      /* PGC_S_DYNAMIC_DEFAULT */ "default",
     614             :      /* PGC_S_ENV_VAR */ "environment variable",
     615             :      /* PGC_S_FILE */ "configuration file",
     616             :      /* PGC_S_ARGV */ "command line",
     617             :      /* PGC_S_GLOBAL */ "global",
     618             :      /* PGC_S_DATABASE */ "database",
     619             :      /* PGC_S_USER */ "user",
     620             :      /* PGC_S_DATABASE_USER */ "database user",
     621             :      /* PGC_S_CLIENT */ "client",
     622             :      /* PGC_S_OVERRIDE */ "override",
     623             :      /* PGC_S_INTERACTIVE */ "interactive",
     624             :      /* PGC_S_TEST */ "test",
     625             :      /* PGC_S_SESSION */ "session"
     626             : };
     627             : 
     628             : /*
     629             :  * Displayable names for the groupings defined in enum config_group
     630             :  */
     631             : const char *const config_group_names[] =
     632             : {
     633             :     /* UNGROUPED */
     634             :     gettext_noop("Ungrouped"),
     635             :     /* FILE_LOCATIONS */
     636             :     gettext_noop("File Locations"),
     637             :     /* CONN_AUTH */
     638             :     gettext_noop("Connections and Authentication"),
     639             :     /* CONN_AUTH_SETTINGS */
     640             :     gettext_noop("Connections and Authentication / Connection Settings"),
     641             :     /* CONN_AUTH_AUTH */
     642             :     gettext_noop("Connections and Authentication / Authentication"),
     643             :     /* CONN_AUTH_SSL */
     644             :     gettext_noop("Connections and Authentication / SSL"),
     645             :     /* RESOURCES */
     646             :     gettext_noop("Resource Usage"),
     647             :     /* RESOURCES_MEM */
     648             :     gettext_noop("Resource Usage / Memory"),
     649             :     /* RESOURCES_DISK */
     650             :     gettext_noop("Resource Usage / Disk"),
     651             :     /* RESOURCES_KERNEL */
     652             :     gettext_noop("Resource Usage / Kernel Resources"),
     653             :     /* RESOURCES_VACUUM_DELAY */
     654             :     gettext_noop("Resource Usage / Cost-Based Vacuum Delay"),
     655             :     /* RESOURCES_BGWRITER */
     656             :     gettext_noop("Resource Usage / Background Writer"),
     657             :     /* RESOURCES_ASYNCHRONOUS */
     658             :     gettext_noop("Resource Usage / Asynchronous Behavior"),
     659             :     /* WAL */
     660             :     gettext_noop("Write-Ahead Log"),
     661             :     /* WAL_SETTINGS */
     662             :     gettext_noop("Write-Ahead Log / Settings"),
     663             :     /* WAL_CHECKPOINTS */
     664             :     gettext_noop("Write-Ahead Log / Checkpoints"),
     665             :     /* WAL_ARCHIVING */
     666             :     gettext_noop("Write-Ahead Log / Archiving"),
     667             :     /* WAL_ARCHIVE_RECOVERY */
     668             :     gettext_noop("Write-Ahead Log / Archive Recovery"),
     669             :     /* WAL_RECOVERY_TARGET */
     670             :     gettext_noop("Write-Ahead Log / Recovery Target"),
     671             :     /* REPLICATION */
     672             :     gettext_noop("Replication"),
     673             :     /* REPLICATION_SENDING */
     674             :     gettext_noop("Replication / Sending Servers"),
     675             :     /* REPLICATION_MASTER */
     676             :     gettext_noop("Replication / Master Server"),
     677             :     /* REPLICATION_STANDBY */
     678             :     gettext_noop("Replication / Standby Servers"),
     679             :     /* REPLICATION_SUBSCRIBERS */
     680             :     gettext_noop("Replication / Subscribers"),
     681             :     /* QUERY_TUNING */
     682             :     gettext_noop("Query Tuning"),
     683             :     /* QUERY_TUNING_METHOD */
     684             :     gettext_noop("Query Tuning / Planner Method Configuration"),
     685             :     /* QUERY_TUNING_COST */
     686             :     gettext_noop("Query Tuning / Planner Cost Constants"),
     687             :     /* QUERY_TUNING_GEQO */
     688             :     gettext_noop("Query Tuning / Genetic Query Optimizer"),
     689             :     /* QUERY_TUNING_OTHER */
     690             :     gettext_noop("Query Tuning / Other Planner Options"),
     691             :     /* LOGGING */
     692             :     gettext_noop("Reporting and Logging"),
     693             :     /* LOGGING_WHERE */
     694             :     gettext_noop("Reporting and Logging / Where to Log"),
     695             :     /* LOGGING_WHEN */
     696             :     gettext_noop("Reporting and Logging / When to Log"),
     697             :     /* LOGGING_WHAT */
     698             :     gettext_noop("Reporting and Logging / What to Log"),
     699             :     /* PROCESS_TITLE */
     700             :     gettext_noop("Process Title"),
     701             :     /* STATS */
     702             :     gettext_noop("Statistics"),
     703             :     /* STATS_MONITORING */
     704             :     gettext_noop("Statistics / Monitoring"),
     705             :     /* STATS_COLLECTOR */
     706             :     gettext_noop("Statistics / Query and Index Statistics Collector"),
     707             :     /* AUTOVACUUM */
     708             :     gettext_noop("Autovacuum"),
     709             :     /* CLIENT_CONN */
     710             :     gettext_noop("Client Connection Defaults"),
     711             :     /* CLIENT_CONN_STATEMENT */
     712             :     gettext_noop("Client Connection Defaults / Statement Behavior"),
     713             :     /* CLIENT_CONN_LOCALE */
     714             :     gettext_noop("Client Connection Defaults / Locale and Formatting"),
     715             :     /* CLIENT_CONN_PRELOAD */
     716             :     gettext_noop("Client Connection Defaults / Shared Library Preloading"),
     717             :     /* CLIENT_CONN_OTHER */
     718             :     gettext_noop("Client Connection Defaults / Other Defaults"),
     719             :     /* LOCK_MANAGEMENT */
     720             :     gettext_noop("Lock Management"),
     721             :     /* COMPAT_OPTIONS */
     722             :     gettext_noop("Version and Platform Compatibility"),
     723             :     /* COMPAT_OPTIONS_PREVIOUS */
     724             :     gettext_noop("Version and Platform Compatibility / Previous PostgreSQL Versions"),
     725             :     /* COMPAT_OPTIONS_CLIENT */
     726             :     gettext_noop("Version and Platform Compatibility / Other Platforms and Clients"),
     727             :     /* ERROR_HANDLING */
     728             :     gettext_noop("Error Handling"),
     729             :     /* PRESET_OPTIONS */
     730             :     gettext_noop("Preset Options"),
     731             :     /* CUSTOM_OPTIONS */
     732             :     gettext_noop("Customized Options"),
     733             :     /* DEVELOPER_OPTIONS */
     734             :     gettext_noop("Developer Options"),
     735             :     /* help_config wants this array to be null-terminated */
     736             :     NULL
     737             : };
     738             : 
     739             : /*
     740             :  * Displayable names for GUC variable types (enum config_type)
     741             :  *
     742             :  * Note: these strings are deliberately not localized.
     743             :  */
     744             : const char *const config_type_names[] =
     745             : {
     746             :      /* PGC_BOOL */ "bool",
     747             :      /* PGC_INT */ "integer",
     748             :      /* PGC_REAL */ "real",
     749             :      /* PGC_STRING */ "string",
     750             :      /* PGC_ENUM */ "enum"
     751             : };
     752             : 
     753             : /*
     754             :  * Unit conversion tables.
     755             :  *
     756             :  * There are two tables, one for memory units, and another for time units.
     757             :  * For each supported conversion from one unit to another, we have an entry
     758             :  * in the table.
     759             :  *
     760             :  * To keep things simple, and to avoid possible roundoff error,
     761             :  * conversions are never chained.  There needs to be a direct conversion
     762             :  * between all units (of the same type).
     763             :  *
     764             :  * The conversions for each base unit must be kept in order from greatest to
     765             :  * smallest human-friendly unit; convert_xxx_from_base_unit() rely on that.
     766             :  * (The order of the base-unit groups does not matter.)
     767             :  */
     768             : #define MAX_UNIT_LEN        3   /* length of longest recognized unit string */
     769             : 
     770             : typedef struct
     771             : {
     772             :     char        unit[MAX_UNIT_LEN + 1]; /* unit, as a string, like "kB" or
     773             :                                          * "min" */
     774             :     int         base_unit;      /* GUC_UNIT_XXX */
     775             :     double      multiplier;     /* Factor for converting unit -> base_unit */
     776             : } unit_conversion;
     777             : 
     778             : /* Ensure that the constants in the tables don't overflow or underflow */
     779             : #if BLCKSZ < 1024 || BLCKSZ > (1024*1024)
     780             : #error BLCKSZ must be between 1KB and 1MB
     781             : #endif
     782             : #if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024*1024)
     783             : #error XLOG_BLCKSZ must be between 1KB and 1MB
     784             : #endif
     785             : 
     786             : static const char *memory_units_hint = gettext_noop("Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\".");
     787             : 
     788             : static const unit_conversion memory_unit_conversion_table[] =
     789             : {
     790             :     {"TB", GUC_UNIT_BYTE, 1024.0 * 1024.0 * 1024.0 * 1024.0},
     791             :     {"GB", GUC_UNIT_BYTE, 1024.0 * 1024.0 * 1024.0},
     792             :     {"MB", GUC_UNIT_BYTE, 1024.0 * 1024.0},
     793             :     {"kB", GUC_UNIT_BYTE, 1024.0},
     794             :     {"B", GUC_UNIT_BYTE, 1.0},
     795             : 
     796             :     {"TB", GUC_UNIT_KB, 1024.0 * 1024.0 * 1024.0},
     797             :     {"GB", GUC_UNIT_KB, 1024.0 * 1024.0},
     798             :     {"MB", GUC_UNIT_KB, 1024.0},
     799             :     {"kB", GUC_UNIT_KB, 1.0},
     800             :     {"B", GUC_UNIT_KB, 1.0 / 1024.0},
     801             : 
     802             :     {"TB", GUC_UNIT_MB, 1024.0 * 1024.0},
     803             :     {"GB", GUC_UNIT_MB, 1024.0},
     804             :     {"MB", GUC_UNIT_MB, 1.0},
     805             :     {"kB", GUC_UNIT_MB, 1.0 / 1024.0},
     806             :     {"B", GUC_UNIT_MB, 1.0 / (1024.0 * 1024.0)},
     807             : 
     808             :     {"TB", GUC_UNIT_BLOCKS, (1024.0 * 1024.0 * 1024.0) / (BLCKSZ / 1024)},
     809             :     {"GB", GUC_UNIT_BLOCKS, (1024.0 * 1024.0) / (BLCKSZ / 1024)},
     810             :     {"MB", GUC_UNIT_BLOCKS, 1024.0 / (BLCKSZ / 1024)},
     811             :     {"kB", GUC_UNIT_BLOCKS, 1.0 / (BLCKSZ / 1024)},
     812             :     {"B", GUC_UNIT_BLOCKS, 1.0 / BLCKSZ},
     813             : 
     814             :     {"TB", GUC_UNIT_XBLOCKS, (1024.0 * 1024.0 * 1024.0) / (XLOG_BLCKSZ / 1024)},
     815             :     {"GB", GUC_UNIT_XBLOCKS, (1024.0 * 1024.0) / (XLOG_BLCKSZ / 1024)},
     816             :     {"MB", GUC_UNIT_XBLOCKS, 1024.0 / (XLOG_BLCKSZ / 1024)},
     817             :     {"kB", GUC_UNIT_XBLOCKS, 1.0 / (XLOG_BLCKSZ / 1024)},
     818             :     {"B", GUC_UNIT_XBLOCKS, 1.0 / XLOG_BLCKSZ},
     819             : 
     820             :     {""}                      /* end of table marker */
     821             : };
     822             : 
     823             : static const char *time_units_hint = gettext_noop("Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", and \"d\".");
     824             : 
     825             : static const unit_conversion time_unit_conversion_table[] =
     826             : {
     827             :     {"d", GUC_UNIT_MS, 1000 * 60 * 60 * 24},
     828             :     {"h", GUC_UNIT_MS, 1000 * 60 * 60},
     829             :     {"min", GUC_UNIT_MS, 1000 * 60},
     830             :     {"s", GUC_UNIT_MS, 1000},
     831             :     {"ms", GUC_UNIT_MS, 1},
     832             :     {"us", GUC_UNIT_MS, 1.0 / 1000},
     833             : 
     834             :     {"d", GUC_UNIT_S, 60 * 60 * 24},
     835             :     {"h", GUC_UNIT_S, 60 * 60},
     836             :     {"min", GUC_UNIT_S, 60},
     837             :     {"s", GUC_UNIT_S, 1},
     838             :     {"ms", GUC_UNIT_S, 1.0 / 1000},
     839             :     {"us", GUC_UNIT_S, 1.0 / (1000 * 1000)},
     840             : 
     841             :     {"d", GUC_UNIT_MIN, 60 * 24},
     842             :     {"h", GUC_UNIT_MIN, 60},
     843             :     {"min", GUC_UNIT_MIN, 1},
     844             :     {"s", GUC_UNIT_MIN, 1.0 / 60},
     845             :     {"ms", GUC_UNIT_MIN, 1.0 / (1000 * 60)},
     846             :     {"us", GUC_UNIT_MIN, 1.0 / (1000 * 1000 * 60)},
     847             : 
     848             :     {""}                      /* end of table marker */
     849             : };
     850             : 
     851             : /*
     852             :  * Contents of GUC tables
     853             :  *
     854             :  * See src/backend/utils/misc/README for design notes.
     855             :  *
     856             :  * TO ADD AN OPTION:
     857             :  *
     858             :  * 1. Declare a global variable of type bool, int, double, or char*
     859             :  *    and make use of it.
     860             :  *
     861             :  * 2. Decide at what times it's safe to set the option. See guc.h for
     862             :  *    details.
     863             :  *
     864             :  * 3. Decide on a name, a default value, upper and lower bounds (if
     865             :  *    applicable), etc.
     866             :  *
     867             :  * 4. Add a record below.
     868             :  *
     869             :  * 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
     870             :  *    appropriate.
     871             :  *
     872             :  * 6. Don't forget to document the option (at least in config.sgml).
     873             :  *
     874             :  * 7. If it's a new GUC_LIST_QUOTE option, you must add it to
     875             :  *    variable_is_guc_list_quote() in src/bin/pg_dump/dumputils.c.
     876             :  */
     877             : 
     878             : 
     879             : /******** option records follow ********/
     880             : 
     881             : static struct config_bool ConfigureNamesBool[] =
     882             : {
     883             :     {
     884             :         {"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
     885             :             gettext_noop("Enables the planner's use of sequential-scan plans."),
     886             :             NULL,
     887             :             GUC_EXPLAIN
     888             :         },
     889             :         &enable_seqscan,
     890             :         true,
     891             :         NULL, NULL, NULL
     892             :     },
     893             :     {
     894             :         {"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
     895             :             gettext_noop("Enables the planner's use of index-scan plans."),
     896             :             NULL,
     897             :             GUC_EXPLAIN
     898             :         },
     899             :         &enable_indexscan,
     900             :         true,
     901             :         NULL, NULL, NULL
     902             :     },
     903             :     {
     904             :         {"enable_indexonlyscan", PGC_USERSET, QUERY_TUNING_METHOD,
     905             :             gettext_noop("Enables the planner's use of index-only-scan plans."),
     906             :             NULL,
     907             :             GUC_EXPLAIN
     908             :         },
     909             :         &enable_indexonlyscan,
     910             :         true,
     911             :         NULL, NULL, NULL
     912             :     },
     913             :     {
     914             :         {"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
     915             :             gettext_noop("Enables the planner's use of bitmap-scan plans."),
     916             :             NULL,
     917             :             GUC_EXPLAIN
     918             :         },
     919             :         &enable_bitmapscan,
     920             :         true,
     921             :         NULL, NULL, NULL
     922             :     },
     923             :     {
     924             :         {"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
     925             :             gettext_noop("Enables the planner's use of TID scan plans."),
     926             :             NULL,
     927             :             GUC_EXPLAIN
     928             :         },
     929             :         &enable_tidscan,
     930             :         true,
     931             :         NULL, NULL, NULL
     932             :     },
     933             :     {
     934             :         {"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
     935             :             gettext_noop("Enables the planner's use of explicit sort steps."),
     936             :             NULL,
     937             :             GUC_EXPLAIN
     938             :         },
     939             :         &enable_sort,
     940             :         true,
     941             :         NULL, NULL, NULL
     942             :     },
     943             :     {
     944             :         {"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
     945             :             gettext_noop("Enables the planner's use of hashed aggregation plans."),
     946             :             NULL,
     947             :             GUC_EXPLAIN
     948             :         },
     949             :         &enable_hashagg,
     950             :         true,
     951             :         NULL, NULL, NULL
     952             :     },
     953             :     {
     954             :         {"enable_material", PGC_USERSET, QUERY_TUNING_METHOD,
     955             :             gettext_noop("Enables the planner's use of materialization."),
     956             :             NULL,
     957             :             GUC_EXPLAIN
     958             :         },
     959             :         &enable_material,
     960             :         true,
     961             :         NULL, NULL, NULL
     962             :     },
     963             :     {
     964             :         {"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
     965             :             gettext_noop("Enables the planner's use of nested-loop join plans."),
     966             :             NULL,
     967             :             GUC_EXPLAIN
     968             :         },
     969             :         &enable_nestloop,
     970             :         true,
     971             :         NULL, NULL, NULL
     972             :     },
     973             :     {
     974             :         {"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
     975             :             gettext_noop("Enables the planner's use of merge join plans."),
     976             :             NULL,
     977             :             GUC_EXPLAIN
     978             :         },
     979             :         &enable_mergejoin,
     980             :         true,
     981             :         NULL, NULL, NULL
     982             :     },
     983             :     {
     984             :         {"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
     985             :             gettext_noop("Enables the planner's use of hash join plans."),
     986             :             NULL,
     987             :             GUC_EXPLAIN
     988             :         },
     989             :         &enable_hashjoin,
     990             :         true,
     991             :         NULL, NULL, NULL
     992             :     },
     993             :     {
     994             :         {"enable_gathermerge", PGC_USERSET, QUERY_TUNING_METHOD,
     995             :             gettext_noop("Enables the planner's use of gather merge plans."),
     996             :             NULL,
     997             :             GUC_EXPLAIN
     998             :         },
     999             :         &enable_gathermerge,
    1000             :         true,
    1001             :         NULL, NULL, NULL
    1002             :     },
    1003             :     {
    1004             :         {"enable_partitionwise_join", PGC_USERSET, QUERY_TUNING_METHOD,
    1005             :             gettext_noop("Enables partitionwise join."),
    1006             :             NULL,
    1007             :             GUC_EXPLAIN
    1008             :         },
    1009             :         &enable_partitionwise_join,
    1010             :         false,
    1011             :         NULL, NULL, NULL
    1012             :     },
    1013             :     {
    1014             :         {"enable_partitionwise_aggregate", PGC_USERSET, QUERY_TUNING_METHOD,
    1015             :             gettext_noop("Enables partitionwise aggregation and grouping."),
    1016             :             NULL,
    1017             :             GUC_EXPLAIN
    1018             :         },
    1019             :         &enable_partitionwise_aggregate,
    1020             :         false,
    1021             :         NULL, NULL, NULL
    1022             :     },
    1023             :     {
    1024             :         {"enable_parallel_append", PGC_USERSET, QUERY_TUNING_METHOD,
    1025             :             gettext_noop("Enables the planner's use of parallel append plans."),
    1026             :             NULL,
    1027             :             GUC_EXPLAIN
    1028             :         },
    1029             :         &enable_parallel_append,
    1030             :         true,
    1031             :         NULL, NULL, NULL
    1032             :     },
    1033             :     {
    1034             :         {"enable_parallel_hash", PGC_USERSET, QUERY_TUNING_METHOD,
    1035             :             gettext_noop("Enables the planner's use of parallel hash plans."),
    1036             :             NULL,
    1037             :             GUC_EXPLAIN
    1038             :         },
    1039             :         &enable_parallel_hash,
    1040             :         true,
    1041             :         NULL, NULL, NULL
    1042             :     },
    1043             :     {
    1044             :         {"enable_partition_pruning", PGC_USERSET, QUERY_TUNING_METHOD,
    1045             :             gettext_noop("Enable plan-time and run-time partition pruning."),
    1046             :             gettext_noop("Allows the query planner and executor to compare partition "
    1047             :                          "bounds to conditions in the query to determine which "
    1048             :                          "partitions must be scanned."),
    1049             :             GUC_EXPLAIN
    1050             :         },
    1051             :         &enable_partition_pruning,
    1052             :         true,
    1053             :         NULL, NULL, NULL
    1054             :     },
    1055             :     {
    1056             :         {"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
    1057             :             gettext_noop("Enables genetic query optimization."),
    1058             :             gettext_noop("This algorithm attempts to do planning without "
    1059             :                          "exhaustive searching."),
    1060             :             GUC_EXPLAIN
    1061             :         },
    1062             :         &enable_geqo,
    1063             :         true,
    1064             :         NULL, NULL, NULL
    1065             :     },
    1066             :     {
    1067             :         /* Not for general use --- used by SET SESSION AUTHORIZATION */
    1068             :         {"is_superuser", PGC_INTERNAL, UNGROUPED,
    1069             :             gettext_noop("Shows whether the current user is a superuser."),
    1070             :             NULL,
    1071             :             GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    1072             :         },
    1073             :         &session_auth_is_superuser,
    1074             :         false,
    1075             :         NULL, NULL, NULL
    1076             :     },
    1077             :     {
    1078             :         {"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    1079             :             gettext_noop("Enables advertising the server via Bonjour."),
    1080             :             NULL
    1081             :         },
    1082             :         &enable_bonjour,
    1083             :         false,
    1084             :         check_bonjour, NULL, NULL
    1085             :     },
    1086             :     {
    1087             :         {"track_commit_timestamp", PGC_POSTMASTER, REPLICATION,
    1088             :             gettext_noop("Collects transaction commit time."),
    1089             :             NULL
    1090             :         },
    1091             :         &track_commit_timestamp,
    1092             :         false,
    1093             :         NULL, NULL, NULL
    1094             :     },
    1095             :     {
    1096             :         {"ssl", PGC_SIGHUP, CONN_AUTH_SSL,
    1097             :             gettext_noop("Enables SSL connections."),
    1098             :             NULL
    1099             :         },
    1100             :         &EnableSSL,
    1101             :         false,
    1102             :         check_ssl, NULL, NULL
    1103             :     },
    1104             :     {
    1105             :         {"ssl_passphrase_command_supports_reload", PGC_SIGHUP, CONN_AUTH_SSL,
    1106             :             gettext_noop("Also use ssl_passphrase_command during server reload."),
    1107             :             NULL
    1108             :         },
    1109             :         &ssl_passphrase_command_supports_reload,
    1110             :         false,
    1111             :         NULL, NULL, NULL
    1112             :     },
    1113             :     {
    1114             :         {"ssl_prefer_server_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
    1115             :             gettext_noop("Give priority to server ciphersuite order."),
    1116             :             NULL
    1117             :         },
    1118             :         &SSLPreferServerCiphers,
    1119             :         true,
    1120             :         NULL, NULL, NULL
    1121             :     },
    1122             :     {
    1123             :         {"fsync", PGC_SIGHUP, WAL_SETTINGS,
    1124             :             gettext_noop("Forces synchronization of updates to disk."),
    1125             :             gettext_noop("The server will use the fsync() system call in several places to make "
    1126             :                          "sure that updates are physically written to disk. This insures "
    1127             :                          "that a database cluster will recover to a consistent state after "
    1128             :                          "an operating system or hardware crash.")
    1129             :         },
    1130             :         &enableFsync,
    1131             :         true,
    1132             :         NULL, NULL, NULL
    1133             :     },
    1134             :     {
    1135             :         {"ignore_checksum_failure", PGC_SUSET, DEVELOPER_OPTIONS,
    1136             :             gettext_noop("Continues processing after a checksum failure."),
    1137             :             gettext_noop("Detection of a checksum failure normally causes PostgreSQL to "
    1138             :                          "report an error, aborting the current transaction. Setting "
    1139             :                          "ignore_checksum_failure to true causes the system to ignore the failure "
    1140             :                          "(but still report a warning), and continue processing. This "
    1141             :                          "behavior could cause crashes or other serious problems. Only "
    1142             :                          "has an effect if checksums are enabled."),
    1143             :             GUC_NOT_IN_SAMPLE
    1144             :         },
    1145             :         &ignore_checksum_failure,
    1146             :         false,
    1147             :         NULL, NULL, NULL
    1148             :     },
    1149             :     {
    1150             :         {"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
    1151             :             gettext_noop("Continues processing past damaged page headers."),
    1152             :             gettext_noop("Detection of a damaged page header normally causes PostgreSQL to "
    1153             :                          "report an error, aborting the current transaction. Setting "
    1154             :                          "zero_damaged_pages to true causes the system to instead report a "
    1155             :                          "warning, zero out the damaged page, and continue processing. This "
    1156             :                          "behavior will destroy data, namely all the rows on the damaged page."),
    1157             :             GUC_NOT_IN_SAMPLE
    1158             :         },
    1159             :         &zero_damaged_pages,
    1160             :         false,
    1161             :         NULL, NULL, NULL
    1162             :     },
    1163             :     {
    1164             :         {"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
    1165             :             gettext_noop("Writes full pages to WAL when first modified after a checkpoint."),
    1166             :             gettext_noop("A page write in process during an operating system crash might be "
    1167             :                          "only partially written to disk.  During recovery, the row changes "
    1168             :                          "stored in WAL are not enough to recover.  This option writes "
    1169             :                          "pages when first modified after a checkpoint to WAL so full recovery "
    1170             :                          "is possible.")
    1171             :         },
    1172             :         &fullPageWrites,
    1173             :         true,
    1174             :         NULL, NULL, NULL
    1175             :     },
    1176             : 
    1177             :     {
    1178             :         {"wal_log_hints", PGC_POSTMASTER, WAL_SETTINGS,
    1179             :             gettext_noop("Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modifications."),
    1180             :             NULL
    1181             :         },
    1182             :         &wal_log_hints,
    1183             :         false,
    1184             :         NULL, NULL, NULL
    1185             :     },
    1186             : 
    1187             :     {
    1188             :         {"wal_compression", PGC_SUSET, WAL_SETTINGS,
    1189             :             gettext_noop("Compresses full-page writes written in WAL file."),
    1190             :             NULL
    1191             :         },
    1192             :         &wal_compression,
    1193             :         false,
    1194             :         NULL, NULL, NULL
    1195             :     },
    1196             : 
    1197             :     {
    1198             :         {"wal_init_zero", PGC_SUSET, WAL_SETTINGS,
    1199             :             gettext_noop("Writes zeroes to new WAL files before first use."),
    1200             :             NULL
    1201             :         },
    1202             :         &wal_init_zero,
    1203             :         true,
    1204             :         NULL, NULL, NULL
    1205             :     },
    1206             : 
    1207             :     {
    1208             :         {"wal_recycle", PGC_SUSET, WAL_SETTINGS,
    1209             :             gettext_noop("Recycles WAL files by renaming them."),
    1210             :             NULL
    1211             :         },
    1212             :         &wal_recycle,
    1213             :         true,
    1214             :         NULL, NULL, NULL
    1215             :     },
    1216             : 
    1217             :     {
    1218             :         {"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
    1219             :             gettext_noop("Logs each checkpoint."),
    1220             :             NULL
    1221             :         },
    1222             :         &log_checkpoints,
    1223             :         false,
    1224             :         NULL, NULL, NULL
    1225             :     },
    1226             :     {
    1227             :         {"log_connections", PGC_SU_BACKEND, LOGGING_WHAT,
    1228             :             gettext_noop("Logs each successful connection."),
    1229             :             NULL
    1230             :         },
    1231             :         &Log_connections,
    1232             :         false,
    1233             :         NULL, NULL, NULL
    1234             :     },
    1235             :     {
    1236             :         {"log_disconnections", PGC_SU_BACKEND, LOGGING_WHAT,
    1237             :             gettext_noop("Logs end of a session, including duration."),
    1238             :             NULL
    1239             :         },
    1240             :         &Log_disconnections,
    1241             :         false,
    1242             :         NULL, NULL, NULL
    1243             :     },
    1244             :     {
    1245             :         {"log_replication_commands", PGC_SUSET, LOGGING_WHAT,
    1246             :             gettext_noop("Logs each replication command."),
    1247             :             NULL
    1248             :         },
    1249             :         &log_replication_commands,
    1250             :         false,
    1251             :         NULL, NULL, NULL
    1252             :     },
    1253             :     {
    1254             :         {"debug_assertions", PGC_INTERNAL, PRESET_OPTIONS,
    1255             :             gettext_noop("Shows whether the running server has assertion checks enabled."),
    1256             :             NULL,
    1257             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    1258             :         },
    1259             :         &assert_enabled,
    1260             : #ifdef USE_ASSERT_CHECKING
    1261             :         true,
    1262             : #else
    1263             :         false,
    1264             : #endif
    1265             :         NULL, NULL, NULL
    1266             :     },
    1267             : 
    1268             :     {
    1269             :         {"exit_on_error", PGC_USERSET, ERROR_HANDLING_OPTIONS,
    1270             :             gettext_noop("Terminate session on any error."),
    1271             :             NULL
    1272             :         },
    1273             :         &ExitOnAnyError,
    1274             :         false,
    1275             :         NULL, NULL, NULL
    1276             :     },
    1277             :     {
    1278             :         {"restart_after_crash", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
    1279             :             gettext_noop("Reinitialize server after backend crash."),
    1280             :             NULL
    1281             :         },
    1282             :         &restart_after_crash,
    1283             :         true,
    1284             :         NULL, NULL, NULL
    1285             :     },
    1286             : 
    1287             :     {
    1288             :         {"log_duration", PGC_SUSET, LOGGING_WHAT,
    1289             :             gettext_noop("Logs the duration of each completed SQL statement."),
    1290             :             NULL
    1291             :         },
    1292             :         &log_duration,
    1293             :         false,
    1294             :         NULL, NULL, NULL
    1295             :     },
    1296             :     {
    1297             :         {"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
    1298             :             gettext_noop("Logs each query's parse tree."),
    1299             :             NULL
    1300             :         },
    1301             :         &Debug_print_parse,
    1302             :         false,
    1303             :         NULL, NULL, NULL
    1304             :     },
    1305             :     {
    1306             :         {"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
    1307             :             gettext_noop("Logs each query's rewritten parse tree."),
    1308             :             NULL
    1309             :         },
    1310             :         &Debug_print_rewritten,
    1311             :         false,
    1312             :         NULL, NULL, NULL
    1313             :     },
    1314             :     {
    1315             :         {"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
    1316             :             gettext_noop("Logs each query's execution plan."),
    1317             :             NULL
    1318             :         },
    1319             :         &Debug_print_plan,
    1320             :         false,
    1321             :         NULL, NULL, NULL
    1322             :     },
    1323             :     {
    1324             :         {"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
    1325             :             gettext_noop("Indents parse and plan tree displays."),
    1326             :             NULL
    1327             :         },
    1328             :         &Debug_pretty_print,
    1329             :         true,
    1330             :         NULL, NULL, NULL
    1331             :     },
    1332             :     {
    1333             :         {"log_parser_stats", PGC_SUSET, STATS_MONITORING,
    1334             :             gettext_noop("Writes parser performance statistics to the server log."),
    1335             :             NULL
    1336             :         },
    1337             :         &log_parser_stats,
    1338             :         false,
    1339             :         check_stage_log_stats, NULL, NULL
    1340             :     },
    1341             :     {
    1342             :         {"log_planner_stats", PGC_SUSET, STATS_MONITORING,
    1343             :             gettext_noop("Writes planner performance statistics to the server log."),
    1344             :             NULL
    1345             :         },
    1346             :         &log_planner_stats,
    1347             :         false,
    1348             :         check_stage_log_stats, NULL, NULL
    1349             :     },
    1350             :     {
    1351             :         {"log_executor_stats", PGC_SUSET, STATS_MONITORING,
    1352             :             gettext_noop("Writes executor performance statistics to the server log."),
    1353             :             NULL
    1354             :         },
    1355             :         &log_executor_stats,
    1356             :         false,
    1357             :         check_stage_log_stats, NULL, NULL
    1358             :     },
    1359             :     {
    1360             :         {"log_statement_stats", PGC_SUSET, STATS_MONITORING,
    1361             :             gettext_noop("Writes cumulative performance statistics to the server log."),
    1362             :             NULL
    1363             :         },
    1364             :         &log_statement_stats,
    1365             :         false,
    1366             :         check_log_stats, NULL, NULL
    1367             :     },
    1368             : #ifdef BTREE_BUILD_STATS
    1369             :     {
    1370             :         {"log_btree_build_stats", PGC_SUSET, DEVELOPER_OPTIONS,
    1371             :             gettext_noop("Logs system resource usage statistics (memory and CPU) on various B-tree operations."),
    1372             :             NULL,
    1373             :             GUC_NOT_IN_SAMPLE
    1374             :         },
    1375             :         &log_btree_build_stats,
    1376             :         false,
    1377             :         NULL, NULL, NULL
    1378             :     },
    1379             : #endif
    1380             : 
    1381             :     {
    1382             :         {"track_activities", PGC_SUSET, STATS_COLLECTOR,
    1383             :             gettext_noop("Collects information about executing commands."),
    1384             :             gettext_noop("Enables the collection of information on the currently "
    1385             :                          "executing command of each session, along with "
    1386             :                          "the time at which that command began execution.")
    1387             :         },
    1388             :         &pgstat_track_activities,
    1389             :         true,
    1390             :         NULL, NULL, NULL
    1391             :     },
    1392             :     {
    1393             :         {"track_counts", PGC_SUSET, STATS_COLLECTOR,
    1394             :             gettext_noop("Collects statistics on database activity."),
    1395             :             NULL
    1396             :         },
    1397             :         &pgstat_track_counts,
    1398             :         true,
    1399             :         NULL, NULL, NULL
    1400             :     },
    1401             :     {
    1402             :         {"track_io_timing", PGC_SUSET, STATS_COLLECTOR,
    1403             :             gettext_noop("Collects timing statistics for database I/O activity."),
    1404             :             NULL
    1405             :         },
    1406             :         &track_io_timing,
    1407             :         false,
    1408             :         NULL, NULL, NULL
    1409             :     },
    1410             : 
    1411             :     {
    1412             :         {"update_process_title", PGC_SUSET, PROCESS_TITLE,
    1413             :             gettext_noop("Updates the process title to show the active SQL command."),
    1414             :             gettext_noop("Enables updating of the process title every time a new SQL command is received by the server.")
    1415             :         },
    1416             :         &update_process_title,
    1417             : #ifdef WIN32
    1418             :         false,
    1419             : #else
    1420             :         true,
    1421             : #endif
    1422             :         NULL, NULL, NULL
    1423             :     },
    1424             : 
    1425             :     {
    1426             :         {"autovacuum", PGC_SIGHUP, AUTOVACUUM,
    1427             :             gettext_noop("Starts the autovacuum subprocess."),
    1428             :             NULL
    1429             :         },
    1430             :         &autovacuum_start_daemon,
    1431             :         true,
    1432             :         NULL, NULL, NULL
    1433             :     },
    1434             : 
    1435             :     {
    1436             :         {"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
    1437             :             gettext_noop("Generates debugging output for LISTEN and NOTIFY."),
    1438             :             NULL,
    1439             :             GUC_NOT_IN_SAMPLE
    1440             :         },
    1441             :         &Trace_notify,
    1442             :         false,
    1443             :         NULL, NULL, NULL
    1444             :     },
    1445             : 
    1446             : #ifdef LOCK_DEBUG
    1447             :     {
    1448             :         {"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
    1449             :             gettext_noop("Emits information about lock usage."),
    1450             :             NULL,
    1451             :             GUC_NOT_IN_SAMPLE
    1452             :         },
    1453             :         &Trace_locks,
    1454             :         false,
    1455             :         NULL, NULL, NULL
    1456             :     },
    1457             :     {
    1458             :         {"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
    1459             :             gettext_noop("Emits information about user lock usage."),
    1460             :             NULL,
    1461             :             GUC_NOT_IN_SAMPLE
    1462             :         },
    1463             :         &Trace_userlocks,
    1464             :         false,
    1465             :         NULL, NULL, NULL
    1466             :     },
    1467             :     {
    1468             :         {"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
    1469             :             gettext_noop("Emits information about lightweight lock usage."),
    1470             :             NULL,
    1471             :             GUC_NOT_IN_SAMPLE
    1472             :         },
    1473             :         &Trace_lwlocks,
    1474             :         false,
    1475             :         NULL, NULL, NULL
    1476             :     },
    1477             :     {
    1478             :         {"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
    1479             :             gettext_noop("Dumps information about all current locks when a deadlock timeout occurs."),
    1480             :             NULL,
    1481             :             GUC_NOT_IN_SAMPLE
    1482             :         },
    1483             :         &Debug_deadlocks,
    1484             :         false,
    1485             :         NULL, NULL, NULL
    1486             :     },
    1487             : #endif
    1488             : 
    1489             :     {
    1490             :         {"log_lock_waits", PGC_SUSET, LOGGING_WHAT,
    1491             :             gettext_noop("Logs long lock waits."),
    1492             :             NULL
    1493             :         },
    1494             :         &log_lock_waits,
    1495             :         false,
    1496             :         NULL, NULL, NULL
    1497             :     },
    1498             : 
    1499             :     {
    1500             :         {"log_hostname", PGC_SIGHUP, LOGGING_WHAT,
    1501             :             gettext_noop("Logs the host name in the connection logs."),
    1502             :             gettext_noop("By default, connection logs only show the IP address "
    1503             :                          "of the connecting host. If you want them to show the host name you "
    1504             :                          "can turn this on, but depending on your host name resolution "
    1505             :                          "setup it might impose a non-negligible performance penalty.")
    1506             :         },
    1507             :         &log_hostname,
    1508             :         false,
    1509             :         NULL, NULL, NULL
    1510             :     },
    1511             :     {
    1512             :         {"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
    1513             :             gettext_noop("Treats \"expr=NULL\" as \"expr IS NULL\"."),
    1514             :             gettext_noop("When turned on, expressions of the form expr = NULL "
    1515             :                          "(or NULL = expr) are treated as expr IS NULL, that is, they "
    1516             :                          "return true if expr evaluates to the null value, and false "
    1517             :                          "otherwise. The correct behavior of expr = NULL is to always "
    1518             :                          "return null (unknown).")
    1519             :         },
    1520             :         &Transform_null_equals,
    1521             :         false,
    1522             :         NULL, NULL, NULL
    1523             :     },
    1524             :     {
    1525             :         {"db_user_namespace", PGC_SIGHUP, CONN_AUTH_AUTH,
    1526             :             gettext_noop("Enables per-database user names."),
    1527             :             NULL
    1528             :         },
    1529             :         &Db_user_namespace,
    1530             :         false,
    1531             :         NULL, NULL, NULL
    1532             :     },
    1533             :     {
    1534             :         {"default_transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
    1535             :             gettext_noop("Sets the default read-only status of new transactions."),
    1536             :             NULL
    1537             :         },
    1538             :         &DefaultXactReadOnly,
    1539             :         false,
    1540             :         NULL, NULL, NULL
    1541             :     },
    1542             :     {
    1543             :         {"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
    1544             :             gettext_noop("Sets the current transaction's read-only status."),
    1545             :             NULL,
    1546             :             GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    1547             :         },
    1548             :         &XactReadOnly,
    1549             :         false,
    1550             :         check_transaction_read_only, NULL, NULL
    1551             :     },
    1552             :     {
    1553             :         {"default_transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
    1554             :             gettext_noop("Sets the default deferrable status of new transactions."),
    1555             :             NULL
    1556             :         },
    1557             :         &DefaultXactDeferrable,
    1558             :         false,
    1559             :         NULL, NULL, NULL
    1560             :     },
    1561             :     {
    1562             :         {"transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
    1563             :             gettext_noop("Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures."),
    1564             :             NULL,
    1565             :             GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    1566             :         },
    1567             :         &XactDeferrable,
    1568             :         false,
    1569             :         check_transaction_deferrable, NULL, NULL
    1570             :     },
    1571             :     {
    1572             :         {"row_security", PGC_USERSET, CLIENT_CONN_STATEMENT,
    1573             :             gettext_noop("Enable row security."),
    1574             :             gettext_noop("When enabled, row security will be applied to all users.")
    1575             :         },
    1576             :         &row_security,
    1577             :         true,
    1578             :         NULL, NULL, NULL
    1579             :     },
    1580             :     {
    1581             :         {"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
    1582             :             gettext_noop("Check function bodies during CREATE FUNCTION."),
    1583             :             NULL
    1584             :         },
    1585             :         &check_function_bodies,
    1586             :         true,
    1587             :         NULL, NULL, NULL
    1588             :     },
    1589             :     {
    1590             :         {"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
    1591             :             gettext_noop("Enable input of NULL elements in arrays."),
    1592             :             gettext_noop("When turned on, unquoted NULL in an array input "
    1593             :                          "value means a null value; "
    1594             :                          "otherwise it is taken literally.")
    1595             :         },
    1596             :         &Array_nulls,
    1597             :         true,
    1598             :         NULL, NULL, NULL
    1599             :     },
    1600             : 
    1601             :     /*
    1602             :      * WITH OIDS support, and consequently default_with_oids, was removed in
    1603             :      * PostgreSQL 12, but we tolerate the parameter being set to false to
    1604             :      * avoid unnecessarily breaking older dump files.
    1605             :      */
    1606             :     {
    1607             :         {"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
    1608             :             gettext_noop("WITH OIDS is no longer supported; this can only be false."),
    1609             :             NULL,
    1610             :             GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
    1611             :         },
    1612             :         &default_with_oids,
    1613             :         false,
    1614             :         check_default_with_oids, NULL, NULL
    1615             :     },
    1616             :     {
    1617             :         {"logging_collector", PGC_POSTMASTER, LOGGING_WHERE,
    1618             :             gettext_noop("Start a subprocess to capture stderr output and/or csvlogs into log files."),
    1619             :             NULL
    1620             :         },
    1621             :         &Logging_collector,
    1622             :         false,
    1623             :         NULL, NULL, NULL
    1624             :     },
    1625             :     {
    1626             :         {"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
    1627             :             gettext_noop("Truncate existing log files of same name during log rotation."),
    1628             :             NULL
    1629             :         },
    1630             :         &Log_truncate_on_rotation,
    1631             :         false,
    1632             :         NULL, NULL, NULL
    1633             :     },
    1634             : 
    1635             : #ifdef TRACE_SORT
    1636             :     {
    1637             :         {"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
    1638             :             gettext_noop("Emit information about resource usage in sorting."),
    1639             :             NULL,
    1640             :             GUC_NOT_IN_SAMPLE
    1641             :         },
    1642             :         &trace_sort,
    1643             :         false,
    1644             :         NULL, NULL, NULL
    1645             :     },
    1646             : #endif
    1647             : 
    1648             : #ifdef TRACE_SYNCSCAN
    1649             :     /* this is undocumented because not exposed in a standard build */
    1650             :     {
    1651             :         {"trace_syncscan", PGC_USERSET, DEVELOPER_OPTIONS,
    1652             :             gettext_noop("Generate debugging output for synchronized scanning."),
    1653             :             NULL,
    1654             :             GUC_NOT_IN_SAMPLE
    1655             :         },
    1656             :         &trace_syncscan,
    1657             :         false,
    1658             :         NULL, NULL, NULL
    1659             :     },
    1660             : #endif
    1661             : 
    1662             : #ifdef DEBUG_BOUNDED_SORT
    1663             :     /* this is undocumented because not exposed in a standard build */
    1664             :     {
    1665             :         {
    1666             :             "optimize_bounded_sort", PGC_USERSET, QUERY_TUNING_METHOD,
    1667             :             gettext_noop("Enable bounded sorting using heap sort."),
    1668             :             NULL,
    1669             :             GUC_NOT_IN_SAMPLE | GUC_EXPLAIN
    1670             :         },
    1671             :         &optimize_bounded_sort,
    1672             :         true,
    1673             :         NULL, NULL, NULL
    1674             :     },
    1675             : #endif
    1676             : 
    1677             : #ifdef WAL_DEBUG
    1678             :     {
    1679             :         {"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
    1680             :             gettext_noop("Emit WAL-related debugging output."),
    1681             :             NULL,
    1682             :             GUC_NOT_IN_SAMPLE
    1683             :         },
    1684             :         &XLOG_DEBUG,
    1685             :         false,
    1686             :         NULL, NULL, NULL
    1687             :     },
    1688             : #endif
    1689             : 
    1690             :     {
    1691             :         {"integer_datetimes", PGC_INTERNAL, PRESET_OPTIONS,
    1692             :             gettext_noop("Datetimes are integer based."),
    1693             :             NULL,
    1694             :             GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    1695             :         },
    1696             :         &integer_datetimes,
    1697             :         true,
    1698             :         NULL, NULL, NULL
    1699             :     },
    1700             : 
    1701             :     {
    1702             :         {"krb_caseins_users", PGC_SIGHUP, CONN_AUTH_AUTH,
    1703             :             gettext_noop("Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."),
    1704             :             NULL
    1705             :         },
    1706             :         &pg_krb_caseins_users,
    1707             :         false,
    1708             :         NULL, NULL, NULL
    1709             :     },
    1710             : 
    1711             :     {
    1712             :         {"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
    1713             :             gettext_noop("Warn about backslash escapes in ordinary string literals."),
    1714             :             NULL
    1715             :         },
    1716             :         &escape_string_warning,
    1717             :         true,
    1718             :         NULL, NULL, NULL
    1719             :     },
    1720             : 
    1721             :     {
    1722             :         {"standard_conforming_strings", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
    1723             :             gettext_noop("Causes '...' strings to treat backslashes literally."),
    1724             :             NULL,
    1725             :             GUC_REPORT
    1726             :         },
    1727             :         &standard_conforming_strings,
    1728             :         true,
    1729             :         NULL, NULL, NULL
    1730             :     },
    1731             : 
    1732             :     {
    1733             :         {"synchronize_seqscans", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
    1734             :             gettext_noop("Enable synchronized sequential scans."),
    1735             :             NULL
    1736             :         },
    1737             :         &synchronize_seqscans,
    1738             :         true,
    1739             :         NULL, NULL, NULL
    1740             :     },
    1741             : 
    1742             :     {
    1743             :         {"recovery_target_inclusive", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
    1744             :             gettext_noop("Sets whether to include or exclude transaction with recovery target."),
    1745             :             NULL
    1746             :         },
    1747             :         &recoveryTargetInclusive,
    1748             :         true,
    1749             :         NULL, NULL, NULL
    1750             :     },
    1751             : 
    1752             :     {
    1753             :         {"hot_standby", PGC_POSTMASTER, REPLICATION_STANDBY,
    1754             :             gettext_noop("Allows connections and queries during recovery."),
    1755             :             NULL
    1756             :         },
    1757             :         &EnableHotStandby,
    1758             :         true,
    1759             :         NULL, NULL, NULL
    1760             :     },
    1761             : 
    1762             :     {
    1763             :         {"hot_standby_feedback", PGC_SIGHUP, REPLICATION_STANDBY,
    1764             :             gettext_noop("Allows feedback from a hot standby to the primary that will avoid query conflicts."),
    1765             :             NULL
    1766             :         },
    1767             :         &hot_standby_feedback,
    1768             :         false,
    1769             :         NULL, NULL, NULL
    1770             :     },
    1771             : 
    1772             :     {
    1773             :         {"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS,
    1774             :             gettext_noop("Allows modifications of the structure of system tables."),
    1775             :             NULL,
    1776             :             GUC_NOT_IN_SAMPLE
    1777             :         },
    1778             :         &allowSystemTableMods,
    1779             :         false,
    1780             :         NULL, NULL, NULL
    1781             :     },
    1782             : 
    1783             :     {
    1784             :         {"ignore_system_indexes", PGC_BACKEND, DEVELOPER_OPTIONS,
    1785             :             gettext_noop("Disables reading from system indexes."),
    1786             :             gettext_noop("It does not prevent updating the indexes, so it is safe "
    1787             :                          "to use.  The worst consequence is slowness."),
    1788             :             GUC_NOT_IN_SAMPLE
    1789             :         },
    1790             :         &IgnoreSystemIndexes,
    1791             :         false,
    1792             :         NULL, NULL, NULL
    1793             :     },
    1794             : 
    1795             :     {
    1796             :         {"lo_compat_privileges", PGC_SUSET, COMPAT_OPTIONS_PREVIOUS,
    1797             :             gettext_noop("Enables backward compatibility mode for privilege checks on large objects."),
    1798             :             gettext_noop("Skips privilege checks when reading or modifying large objects, "
    1799             :                          "for compatibility with PostgreSQL releases prior to 9.0.")
    1800             :         },
    1801             :         &lo_compat_privileges,
    1802             :         false,
    1803             :         NULL, NULL, NULL
    1804             :     },
    1805             : 
    1806             :     {
    1807             :         {"operator_precedence_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
    1808             :             gettext_noop("Emit a warning for constructs that changed meaning since PostgreSQL 9.4."),
    1809             :             NULL,
    1810             :         },
    1811             :         &operator_precedence_warning,
    1812             :         false,
    1813             :         NULL, NULL, NULL
    1814             :     },
    1815             : 
    1816             :     {
    1817             :         {"quote_all_identifiers", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
    1818             :             gettext_noop("When generating SQL fragments, quote all identifiers."),
    1819             :             NULL,
    1820             :         },
    1821             :         &quote_all_identifiers,
    1822             :         false,
    1823             :         NULL, NULL, NULL
    1824             :     },
    1825             : 
    1826             :     {
    1827             :         {"data_checksums", PGC_INTERNAL, PRESET_OPTIONS,
    1828             :             gettext_noop("Shows whether data checksums are turned on for this cluster."),
    1829             :             NULL,
    1830             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    1831             :         },
    1832             :         &data_checksums,
    1833             :         false,
    1834             :         NULL, NULL, NULL
    1835             :     },
    1836             : 
    1837             :     {
    1838             :         {"syslog_sequence_numbers", PGC_SIGHUP, LOGGING_WHERE,
    1839             :             gettext_noop("Add sequence number to syslog messages to avoid duplicate suppression."),
    1840             :             NULL
    1841             :         },
    1842             :         &syslog_sequence_numbers,
    1843             :         true,
    1844             :         NULL, NULL, NULL
    1845             :     },
    1846             : 
    1847             :     {
    1848             :         {"syslog_split_messages", PGC_SIGHUP, LOGGING_WHERE,
    1849             :             gettext_noop("Split messages sent to syslog by lines and to fit into 1024 bytes."),
    1850             :             NULL
    1851             :         },
    1852             :         &syslog_split_messages,
    1853             :         true,
    1854             :         NULL, NULL, NULL
    1855             :     },
    1856             : 
    1857             :     {
    1858             :         {"parallel_leader_participation", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
    1859             :             gettext_noop("Controls whether Gather and Gather Merge also run subplans."),
    1860             :             gettext_noop("Should gather nodes also run subplans, or just gather tuples?"),
    1861             :             GUC_EXPLAIN
    1862             :         },
    1863             :         &parallel_leader_participation,
    1864             :         true,
    1865             :         NULL, NULL, NULL
    1866             :     },
    1867             : 
    1868             :     {
    1869             :         {"jit", PGC_USERSET, QUERY_TUNING_OTHER,
    1870             :             gettext_noop("Allow JIT compilation."),
    1871             :             NULL,
    1872             :             GUC_EXPLAIN
    1873             :         },
    1874             :         &jit_enabled,
    1875             :         true,
    1876             :         NULL, NULL, NULL
    1877             :     },
    1878             : 
    1879             :     {
    1880             :         {"jit_debugging_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
    1881             :             gettext_noop("Register JIT compiled function with debugger."),
    1882             :             NULL,
    1883             :             GUC_NOT_IN_SAMPLE
    1884             :         },
    1885             :         &jit_debugging_support,
    1886             :         false,
    1887             : 
    1888             :         /*
    1889             :          * This is not guaranteed to be available, but given it's a developer
    1890             :          * oriented option, it doesn't seem worth adding code checking
    1891             :          * availability.
    1892             :          */
    1893             :         NULL, NULL, NULL
    1894             :     },
    1895             : 
    1896             :     {
    1897             :         {"jit_dump_bitcode", PGC_SUSET, DEVELOPER_OPTIONS,
    1898             :             gettext_noop("Write out LLVM bitcode to facilitate JIT debugging."),
    1899             :             NULL,
    1900             :             GUC_NOT_IN_SAMPLE
    1901             :         },
    1902             :         &jit_dump_bitcode,
    1903             :         false,
    1904             :         NULL, NULL, NULL
    1905             :     },
    1906             : 
    1907             :     {
    1908             :         {"jit_expressions", PGC_USERSET, DEVELOPER_OPTIONS,
    1909             :             gettext_noop("Allow JIT compilation of expressions."),
    1910             :             NULL,
    1911             :             GUC_NOT_IN_SAMPLE
    1912             :         },
    1913             :         &jit_expressions,
    1914             :         true,
    1915             :         NULL, NULL, NULL
    1916             :     },
    1917             : 
    1918             :     {
    1919             :         {"jit_profiling_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
    1920             :             gettext_noop("Register JIT compiled function with perf profiler."),
    1921             :             NULL,
    1922             :             GUC_NOT_IN_SAMPLE
    1923             :         },
    1924             :         &jit_profiling_support,
    1925             :         false,
    1926             : 
    1927             :         /*
    1928             :          * This is not guaranteed to be available, but given it's a developer
    1929             :          * oriented option, it doesn't seem worth adding code checking
    1930             :          * availability.
    1931             :          */
    1932             :         NULL, NULL, NULL
    1933             :     },
    1934             : 
    1935             :     {
    1936             :         {"jit_tuple_deforming", PGC_USERSET, DEVELOPER_OPTIONS,
    1937             :             gettext_noop("Allow JIT compilation of tuple deforming."),
    1938             :             NULL,
    1939             :             GUC_NOT_IN_SAMPLE
    1940             :         },
    1941             :         &jit_tuple_deforming,
    1942             :         true,
    1943             :         NULL, NULL, NULL
    1944             :     },
    1945             : 
    1946             :     {
    1947             :         {"data_sync_retry", PGC_POSTMASTER, ERROR_HANDLING_OPTIONS,
    1948             :             gettext_noop("Whether to continue running after a failure to sync data files."),
    1949             :         },
    1950             :         &data_sync_retry,
    1951             :         false,
    1952             :         NULL, NULL, NULL
    1953             :     },
    1954             : 
    1955             :     /* End-of-list marker */
    1956             :     {
    1957             :         {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
    1958             :     }
    1959             : };
    1960             : 
    1961             : 
    1962             : static struct config_int ConfigureNamesInt[] =
    1963             : {
    1964             :     {
    1965             :         {"archive_timeout", PGC_SIGHUP, WAL_ARCHIVING,
    1966             :             gettext_noop("Forces a switch to the next WAL file if a "
    1967             :                          "new file has not been started within N seconds."),
    1968             :             NULL,
    1969             :             GUC_UNIT_S
    1970             :         },
    1971             :         &XLogArchiveTimeout,
    1972             :         0, 0, INT_MAX / 2,
    1973             :         NULL, NULL, NULL
    1974             :     },
    1975             :     {
    1976             :         {"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
    1977             :             gettext_noop("Waits N seconds on connection startup after authentication."),
    1978             :             gettext_noop("This allows attaching a debugger to the process."),
    1979             :             GUC_NOT_IN_SAMPLE | GUC_UNIT_S
    1980             :         },
    1981             :         &PostAuthDelay,
    1982             :         0, 0, INT_MAX / 1000000,
    1983             :         NULL, NULL, NULL
    1984             :     },
    1985             :     {
    1986             :         {"default_statistics_target", PGC_USERSET, QUERY_TUNING_OTHER,
    1987             :             gettext_noop("Sets the default statistics target."),
    1988             :             gettext_noop("This applies to table columns that have not had a "
    1989             :                          "column-specific target set via ALTER TABLE SET STATISTICS.")
    1990             :         },
    1991             :         &default_statistics_target,
    1992             :         100, 1, 10000,
    1993             :         NULL, NULL, NULL
    1994             :     },
    1995             :     {
    1996             :         {"from_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
    1997             :             gettext_noop("Sets the FROM-list size beyond which subqueries "
    1998             :                          "are not collapsed."),
    1999             :             gettext_noop("The planner will merge subqueries into upper "
    2000             :                          "queries if the resulting FROM list would have no more than "
    2001             :                          "this many items."),
    2002             :             GUC_EXPLAIN
    2003             :         },
    2004             :         &from_collapse_limit,
    2005             :         8, 1, INT_MAX,
    2006             :         NULL, NULL, NULL
    2007             :     },
    2008             :     {
    2009             :         {"join_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
    2010             :             gettext_noop("Sets the FROM-list size beyond which JOIN "
    2011             :                          "constructs are not flattened."),
    2012             :             gettext_noop("The planner will flatten explicit JOIN "
    2013             :                          "constructs into lists of FROM items whenever a "
    2014             :                          "list of no more than this many items would result."),
    2015             :             GUC_EXPLAIN
    2016             :         },
    2017             :         &join_collapse_limit,
    2018             :         8, 1, INT_MAX,
    2019             :         NULL, NULL, NULL
    2020             :     },
    2021             :     {
    2022             :         {"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
    2023             :             gettext_noop("Sets the threshold of FROM items beyond which GEQO is used."),
    2024             :             NULL,
    2025             :             GUC_EXPLAIN
    2026             :         },
    2027             :         &geqo_threshold,
    2028             :         12, 2, INT_MAX,
    2029             :         NULL, NULL, NULL
    2030             :     },
    2031             :     {
    2032             :         {"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
    2033             :             gettext_noop("GEQO: effort is used to set the default for other GEQO parameters."),
    2034             :             NULL,
    2035             :             GUC_EXPLAIN
    2036             :         },
    2037             :         &Geqo_effort,
    2038             :         DEFAULT_GEQO_EFFORT, MIN_GEQO_EFFORT, MAX_GEQO_EFFORT,
    2039             :         NULL, NULL, NULL
    2040             :     },
    2041             :     {
    2042             :         {"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
    2043             :             gettext_noop("GEQO: number of individuals in the population."),
    2044             :             gettext_noop("Zero selects a suitable default value."),
    2045             :             GUC_EXPLAIN
    2046             :         },
    2047             :         &Geqo_pool_size,
    2048             :         0, 0, INT_MAX,
    2049             :         NULL, NULL, NULL
    2050             :     },
    2051             :     {
    2052             :         {"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
    2053             :             gettext_noop("GEQO: number of iterations of the algorithm."),
    2054             :             gettext_noop("Zero selects a suitable default value."),
    2055             :             GUC_EXPLAIN
    2056             :         },
    2057             :         &Geqo_generations,
    2058             :         0, 0, INT_MAX,
    2059             :         NULL, NULL, NULL
    2060             :     },
    2061             : 
    2062             :     {
    2063             :         /* This is PGC_SUSET to prevent hiding from log_lock_waits. */
    2064             :         {"deadlock_timeout", PGC_SUSET, LOCK_MANAGEMENT,
    2065             :             gettext_noop("Sets the time to wait on a lock before checking for deadlock."),
    2066             :             NULL,
    2067             :             GUC_UNIT_MS
    2068             :         },
    2069             :         &DeadlockTimeout,
    2070             :         1000, 1, INT_MAX,
    2071             :         NULL, NULL, NULL
    2072             :     },
    2073             : 
    2074             :     {
    2075             :         {"max_standby_archive_delay", PGC_SIGHUP, REPLICATION_STANDBY,
    2076             :             gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data."),
    2077             :             NULL,
    2078             :             GUC_UNIT_MS
    2079             :         },
    2080             :         &max_standby_archive_delay,
    2081             :         30 * 1000, -1, INT_MAX,
    2082             :         NULL, NULL, NULL
    2083             :     },
    2084             : 
    2085             :     {
    2086             :         {"max_standby_streaming_delay", PGC_SIGHUP, REPLICATION_STANDBY,
    2087             :             gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data."),
    2088             :             NULL,
    2089             :             GUC_UNIT_MS
    2090             :         },
    2091             :         &max_standby_streaming_delay,
    2092             :         30 * 1000, -1, INT_MAX,
    2093             :         NULL, NULL, NULL
    2094             :     },
    2095             : 
    2096             :     {
    2097             :         {"recovery_min_apply_delay", PGC_SIGHUP, REPLICATION_STANDBY,
    2098             :             gettext_noop("Sets the minimum delay for applying changes during recovery."),
    2099             :             NULL,
    2100             :             GUC_UNIT_MS
    2101             :         },
    2102             :         &recovery_min_apply_delay,
    2103             :         0, 0, INT_MAX,
    2104             :         NULL, NULL, NULL
    2105             :     },
    2106             : 
    2107             :     {
    2108             :         {"wal_receiver_status_interval", PGC_SIGHUP, REPLICATION_STANDBY,
    2109             :             gettext_noop("Sets the maximum interval between WAL receiver status reports to the sending server."),
    2110             :             NULL,
    2111             :             GUC_UNIT_S
    2112             :         },
    2113             :         &wal_receiver_status_interval,
    2114             :         10, 0, INT_MAX / 1000,
    2115             :         NULL, NULL, NULL
    2116             :     },
    2117             : 
    2118             :     {
    2119             :         {"wal_receiver_timeout", PGC_SIGHUP, REPLICATION_STANDBY,
    2120             :             gettext_noop("Sets the maximum wait time to receive data from the sending server."),
    2121             :             NULL,
    2122             :             GUC_UNIT_MS
    2123             :         },
    2124             :         &wal_receiver_timeout,
    2125             :         60 * 1000, 0, INT_MAX,
    2126             :         NULL, NULL, NULL
    2127             :     },
    2128             : 
    2129             :     {
    2130             :         {"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    2131             :             gettext_noop("Sets the maximum number of concurrent connections."),
    2132             :             NULL
    2133             :         },
    2134             :         &MaxConnections,
    2135             :         100, 1, MAX_BACKENDS,
    2136             :         check_maxconnections, NULL, NULL
    2137             :     },
    2138             : 
    2139             :     {
    2140             :         /* see max_connections */
    2141             :         {"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    2142             :             gettext_noop("Sets the number of connection slots reserved for superusers."),
    2143             :             NULL
    2144             :         },
    2145             :         &ReservedBackends,
    2146             :         3, 0, MAX_BACKENDS,
    2147             :         NULL, NULL, NULL
    2148             :     },
    2149             : 
    2150             :     /*
    2151             :      * We sometimes multiply the number of shared buffers by two without
    2152             :      * checking for overflow, so we mustn't allow more than INT_MAX / 2.
    2153             :      */
    2154             :     {
    2155             :         {"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
    2156             :             gettext_noop("Sets the number of shared memory buffers used by the server."),
    2157             :             NULL,
    2158             :             GUC_UNIT_BLOCKS
    2159             :         },
    2160             :         &NBuffers,
    2161             :         1024, 16, INT_MAX / 2,
    2162             :         NULL, NULL, NULL
    2163             :     },
    2164             : 
    2165             :     {
    2166             :         {"temp_buffers", PGC_USERSET, RESOURCES_MEM,
    2167             :             gettext_noop("Sets the maximum number of temporary buffers used by each session."),
    2168             :             NULL,
    2169             :             GUC_UNIT_BLOCKS | GUC_EXPLAIN
    2170             :         },
    2171             :         &num_temp_buffers,
    2172             :         1024, 100, INT_MAX / 2,
    2173             :         check_temp_buffers, NULL, NULL
    2174             :     },
    2175             : 
    2176             :     {
    2177             :         {"port", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    2178             :             gettext_noop("Sets the TCP port the server listens on."),
    2179             :             NULL
    2180             :         },
    2181             :         &PostPortNumber,
    2182             :         DEF_PGPORT, 1, 65535,
    2183             :         NULL, NULL, NULL
    2184             :     },
    2185             : 
    2186             :     {
    2187             :         {"unix_socket_permissions", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    2188             :             gettext_noop("Sets the access permissions of the Unix-domain socket."),
    2189             :             gettext_noop("Unix-domain sockets use the usual Unix file system "
    2190             :                          "permission set. The parameter value is expected "
    2191             :                          "to be a numeric mode specification in the form "
    2192             :                          "accepted by the chmod and umask system calls. "
    2193             :                          "(To use the customary octal format the number must "
    2194             :                          "start with a 0 (zero).)")
    2195             :         },
    2196             :         &Unix_socket_permissions,
    2197             :         0777, 0000, 0777,
    2198             :         NULL, NULL, show_unix_socket_permissions
    2199             :     },
    2200             : 
    2201             :     {
    2202             :         {"log_file_mode", PGC_SIGHUP, LOGGING_WHERE,
    2203             :             gettext_noop("Sets the file permissions for log files."),
    2204             :             gettext_noop("The parameter value is expected "
    2205             :                          "to be a numeric mode specification in the form "
    2206             :                          "accepted by the chmod and umask system calls. "
    2207             :                          "(To use the customary octal format the number must "
    2208             :                          "start with a 0 (zero).)")
    2209             :         },
    2210             :         &Log_file_mode,
    2211             :         0600, 0000, 0777,
    2212             :         NULL, NULL, show_log_file_mode
    2213             :     },
    2214             : 
    2215             : 
    2216             :     {
    2217             :         {"data_directory_mode", PGC_INTERNAL, PRESET_OPTIONS,
    2218             :             gettext_noop("Mode of the data directory."),
    2219             :             gettext_noop("The parameter value is a numeric mode specification "
    2220             :                          "in the form accepted by the chmod and umask system "
    2221             :                          "calls. (To use the customary octal format the number "
    2222             :                          "must start with a 0 (zero).)"),
    2223             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    2224             :         },
    2225             :         &data_directory_mode,
    2226             :         0700, 0000, 0777,
    2227             :         NULL, NULL, show_data_directory_mode
    2228             :     },
    2229             : 
    2230             :     {
    2231             :         {"work_mem", PGC_USERSET, RESOURCES_MEM,
    2232             :             gettext_noop("Sets the maximum memory to be used for query workspaces."),
    2233             :             gettext_noop("This much memory can be used by each internal "
    2234             :                          "sort operation and hash table before switching to "
    2235             :                          "temporary disk files."),
    2236             :             GUC_UNIT_KB | GUC_EXPLAIN
    2237             :         },
    2238             :         &work_mem,
    2239             :         4096, 64, MAX_KILOBYTES,
    2240             :         NULL, NULL, NULL
    2241             :     },
    2242             : 
    2243             :     {
    2244             :         {"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
    2245             :             gettext_noop("Sets the maximum memory to be used for maintenance operations."),
    2246             :             gettext_noop("This includes operations such as VACUUM and CREATE INDEX."),
    2247             :             GUC_UNIT_KB
    2248             :         },
    2249             :         &maintenance_work_mem,
    2250             :         65536, 1024, MAX_KILOBYTES,
    2251             :         NULL, NULL, NULL
    2252             :     },
    2253             : 
    2254             :     /*
    2255             :      * We use the hopefully-safely-small value of 100kB as the compiled-in
    2256             :      * default for max_stack_depth.  InitializeGUCOptions will increase it if
    2257             :      * possible, depending on the actual platform-specific stack limit.
    2258             :      */
    2259             :     {
    2260             :         {"max_stack_depth", PGC_SUSET, RESOURCES_MEM,
    2261             :             gettext_noop("Sets the maximum stack depth, in kilobytes."),
    2262             :             NULL,
    2263             :             GUC_UNIT_KB
    2264             :         },
    2265             :         &max_stack_depth,
    2266             :         100, 100, MAX_KILOBYTES,
    2267             :         check_max_stack_depth, assign_max_stack_depth, NULL
    2268             :     },
    2269             : 
    2270             :     {
    2271             :         {"temp_file_limit", PGC_SUSET, RESOURCES_DISK,
    2272             :             gettext_noop("Limits the total size of all temporary files used by each process."),
    2273             :             gettext_noop("-1 means no limit."),
    2274             :             GUC_UNIT_KB
    2275             :         },
    2276             :         &temp_file_limit,
    2277             :         -1, -1, INT_MAX,
    2278             :         NULL, NULL, NULL
    2279             :     },
    2280             : 
    2281             :     {
    2282             :         {"vacuum_cost_page_hit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
    2283             :             gettext_noop("Vacuum cost for a page found in the buffer cache."),
    2284             :             NULL
    2285             :         },
    2286             :         &VacuumCostPageHit,
    2287             :         1, 0, 10000,
    2288             :         NULL, NULL, NULL
    2289             :     },
    2290             : 
    2291             :     {
    2292             :         {"vacuum_cost_page_miss", PGC_USERSET, RESOURCES_VACUUM_DELAY,
    2293             :             gettext_noop("Vacuum cost for a page not found in the buffer cache."),
    2294             :             NULL
    2295             :         },
    2296             :         &VacuumCostPageMiss,
    2297             :         10, 0, 10000,
    2298             :         NULL, NULL, NULL
    2299             :     },
    2300             : 
    2301             :     {
    2302             :         {"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES_VACUUM_DELAY,
    2303             :             gettext_noop("Vacuum cost for a page dirtied by vacuum."),
    2304             :             NULL
    2305             :         },
    2306             :         &VacuumCostPageDirty,
    2307             :         20, 0, 10000,
    2308             :         NULL, NULL, NULL
    2309             :     },
    2310             : 
    2311             :     {
    2312             :         {"vacuum_cost_limit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
    2313             :             gettext_noop("Vacuum cost amount available before napping."),
    2314             :             NULL
    2315             :         },
    2316             :         &VacuumCostLimit,
    2317             :         200, 1, 10000,
    2318             :         NULL, NULL, NULL
    2319             :     },
    2320             : 
    2321             :     {
    2322             :         {"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
    2323             :             gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
    2324             :             NULL
    2325             :         },
    2326             :         &autovacuum_vac_cost_limit,
    2327             :         -1, -1, 10000,
    2328             :         NULL, NULL, NULL
    2329             :     },
    2330             : 
    2331             :     {
    2332             :         {"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
    2333             :             gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
    2334             :             NULL
    2335             :         },
    2336             :         &max_files_per_process,
    2337             :         1000, 25, INT_MAX,
    2338             :         NULL, NULL, NULL
    2339             :     },
    2340             : 
    2341             :     /*
    2342             :      * See also CheckRequiredParameterValues() if this parameter changes
    2343             :      */
    2344             :     {
    2345             :         {"max_prepared_transactions", PGC_POSTMASTER, RESOURCES_MEM,
    2346             :             gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
    2347             :             NULL
    2348             :         },
    2349             :         &max_prepared_xacts,
    2350             :         0, 0, MAX_BACKENDS,
    2351             :         NULL, NULL, NULL
    2352             :     },
    2353             : 
    2354             : #ifdef LOCK_DEBUG
    2355             :     {
    2356             :         {"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
    2357             :             gettext_noop("Sets the minimum OID of tables for tracking locks."),
    2358             :             gettext_noop("Is used to avoid output on system tables."),
    2359             :             GUC_NOT_IN_SAMPLE
    2360             :         },
    2361             :         &Trace_lock_oidmin,
    2362             :         FirstNormalObjectId, 0, INT_MAX,
    2363             :         NULL, NULL, NULL
    2364             :     },
    2365             :     {
    2366             :         {"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
    2367             :             gettext_noop("Sets the OID of the table with unconditionally lock tracing."),
    2368             :             NULL,
    2369             :             GUC_NOT_IN_SAMPLE
    2370             :         },
    2371             :         &Trace_lock_table,
    2372             :         0, 0, INT_MAX,
    2373             :         NULL, NULL, NULL
    2374             :     },
    2375             : #endif
    2376             : 
    2377             :     {
    2378             :         {"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
    2379             :             gettext_noop("Sets the maximum allowed duration of any statement."),
    2380             :             gettext_noop("A value of 0 turns off the timeout."),
    2381             :             GUC_UNIT_MS
    2382             :         },
    2383             :         &StatementTimeout,
    2384             :         0, 0, INT_MAX,
    2385             :         NULL, NULL, NULL
    2386             :     },
    2387             : 
    2388             :     {
    2389             :         {"lock_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
    2390             :             gettext_noop("Sets the maximum allowed duration of any wait for a lock."),
    2391             :             gettext_noop("A value of 0 turns off the timeout."),
    2392             :             GUC_UNIT_MS
    2393             :         },
    2394             :         &LockTimeout,
    2395             :         0, 0, INT_MAX,
    2396             :         NULL, NULL, NULL
    2397             :     },
    2398             : 
    2399             :     {
    2400             :         {"idle_in_transaction_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
    2401             :             gettext_noop("Sets the maximum allowed duration of any idling transaction."),
    2402             :             gettext_noop("A value of 0 turns off the timeout."),
    2403             :             GUC_UNIT_MS
    2404             :         },
    2405             :         &IdleInTransactionSessionTimeout,
    2406             :         0, 0, INT_MAX,
    2407             :         NULL, NULL, NULL
    2408             :     },
    2409             : 
    2410             :     {
    2411             :         {"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
    2412             :             gettext_noop("Minimum age at which VACUUM should freeze a table row."),
    2413             :             NULL
    2414             :         },
    2415             :         &vacuum_freeze_min_age,
    2416             :         50000000, 0, 1000000000,
    2417             :         NULL, NULL, NULL
    2418             :     },
    2419             : 
    2420             :     {
    2421             :         {"vacuum_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
    2422             :             gettext_noop("Age at which VACUUM should scan whole table to freeze tuples."),
    2423             :             NULL
    2424             :         },
    2425             :         &vacuum_freeze_table_age,
    2426             :         150000000, 0, 2000000000,
    2427             :         NULL, NULL, NULL
    2428             :     },
    2429             : 
    2430             :     {
    2431             :         {"vacuum_multixact_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
    2432             :             gettext_noop("Minimum age at which VACUUM should freeze a MultiXactId in a table row."),
    2433             :             NULL
    2434             :         },
    2435             :         &vacuum_multixact_freeze_min_age,
    2436             :         5000000, 0, 1000000000,
    2437             :         NULL, NULL, NULL
    2438             :     },
    2439             : 
    2440             :     {
    2441             :         {"vacuum_multixact_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
    2442             :             gettext_noop("Multixact age at which VACUUM should scan whole table to freeze tuples."),
    2443             :             NULL
    2444             :         },
    2445             :         &vacuum_multixact_freeze_table_age,
    2446             :         150000000, 0, 2000000000,
    2447             :         NULL, NULL, NULL
    2448             :     },
    2449             : 
    2450             :     {
    2451             :         {"vacuum_defer_cleanup_age", PGC_SIGHUP, REPLICATION_MASTER,
    2452             :             gettext_noop("Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."),
    2453             :             NULL
    2454             :         },
    2455             :         &vacuum_defer_cleanup_age,
    2456             :         0, 0, 1000000,
    2457             :         NULL, NULL, NULL
    2458             :     },
    2459             : 
    2460             :     /*
    2461             :      * See also CheckRequiredParameterValues() if this parameter changes
    2462             :      */
    2463             :     {
    2464             :         {"max_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
    2465             :             gettext_noop("Sets the maximum number of locks per transaction."),
    2466             :             gettext_noop("The shared lock table is sized on the assumption that "
    2467             :                          "at most max_locks_per_transaction * max_connections distinct "
    2468             :                          "objects will need to be locked at any one time.")
    2469             :         },
    2470             :         &max_locks_per_xact,
    2471             :         64, 10, INT_MAX,
    2472             :         NULL, NULL, NULL
    2473             :     },
    2474             : 
    2475             :     {
    2476             :         {"max_pred_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
    2477             :             gettext_noop("Sets the maximum number of predicate locks per transaction."),
    2478             :             gettext_noop("The shared predicate lock table is sized on the assumption that "
    2479             :                          "at most max_pred_locks_per_transaction * max_connections distinct "
    2480             :                          "objects will need to be locked at any one time.")
    2481             :         },
    2482             :         &max_predicate_locks_per_xact,
    2483             :         64, 10, INT_MAX,
    2484             :         NULL, NULL, NULL
    2485             :     },
    2486             : 
    2487             :     {
    2488             :         {"max_pred_locks_per_relation", PGC_SIGHUP, LOCK_MANAGEMENT,
    2489             :             gettext_noop("Sets the maximum number of predicate-locked pages and tuples per relation."),
    2490             :             gettext_noop("If more than this total of pages and tuples in the same relation are locked "
    2491             :                          "by a connection, those locks are replaced by a relation-level lock.")
    2492             :         },
    2493             :         &max_predicate_locks_per_relation,
    2494             :         -2, INT_MIN, INT_MAX,
    2495             :         NULL, NULL, NULL
    2496             :     },
    2497             : 
    2498             :     {
    2499             :         {"max_pred_locks_per_page", PGC_SIGHUP, LOCK_MANAGEMENT,
    2500             :             gettext_noop("Sets the maximum number of predicate-locked tuples per page."),
    2501             :             gettext_noop("If more than this number of tuples on the same page are locked "
    2502             :                          "by a connection, those locks are replaced by a page-level lock.")
    2503             :         },
    2504             :         &max_predicate_locks_per_page,
    2505             :         2, 0, INT_MAX,
    2506             :         NULL, NULL, NULL
    2507             :     },
    2508             : 
    2509             :     {
    2510             :         {"authentication_timeout", PGC_SIGHUP, CONN_AUTH_AUTH,
    2511             :             gettext_noop("Sets the maximum allowed time to complete client authentication."),
    2512             :             NULL,
    2513             :             GUC_UNIT_S
    2514             :         },
    2515             :         &AuthenticationTimeout,
    2516             :         60, 1, 600,
    2517             :         NULL, NULL, NULL
    2518             :     },
    2519             : 
    2520             :     {
    2521             :         /* Not for general use */
    2522             :         {"pre_auth_delay", PGC_SIGHUP, DEVELOPER_OPTIONS,
    2523             :             gettext_noop("Waits N seconds on connection startup before authentication."),
    2524             :             gettext_noop("This allows attaching a debugger to the process."),
    2525             :             GUC_NOT_IN_SAMPLE | GUC_UNIT_S
    2526             :         },
    2527             :         &PreAuthDelay,
    2528             :         0, 0, 60,
    2529             :         NULL, NULL, NULL
    2530             :     },
    2531             : 
    2532             :     {
    2533             :         {"wal_keep_segments", PGC_SIGHUP, REPLICATION_SENDING,
    2534             :             gettext_noop("Sets the number of WAL files held for standby servers."),
    2535             :             NULL
    2536             :         },
    2537             :         &wal_keep_segments,
    2538             :         0, 0, INT_MAX,
    2539             :         NULL, NULL, NULL
    2540             :     },
    2541             : 
    2542             :     {
    2543             :         {"min_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
    2544             :             gettext_noop("Sets the minimum size to shrink the WAL to."),
    2545             :             NULL,
    2546             :             GUC_UNIT_MB
    2547             :         },
    2548             :         &min_wal_size_mb,
    2549             :         DEFAULT_MIN_WAL_SEGS * (DEFAULT_XLOG_SEG_SIZE / (1024 * 1024)),
    2550             :         2, MAX_KILOBYTES,
    2551             :         NULL, NULL, NULL
    2552             :     },
    2553             : 
    2554             :     {
    2555             :         {"max_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
    2556             :             gettext_noop("Sets the WAL size that triggers a checkpoint."),
    2557             :             NULL,
    2558             :             GUC_UNIT_MB
    2559             :         },
    2560             :         &max_wal_size_mb,
    2561             :         DEFAULT_MAX_WAL_SEGS * (DEFAULT_XLOG_SEG_SIZE / (1024 * 1024)),
    2562             :         2, MAX_KILOBYTES,
    2563             :         NULL, assign_max_wal_size, NULL
    2564             :     },
    2565             : 
    2566             :     {
    2567             :         {"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS,
    2568             :             gettext_noop("Sets the maximum time between automatic WAL checkpoints."),
    2569             :             NULL,
    2570             :             GUC_UNIT_S
    2571             :         },
    2572             :         &CheckPointTimeout,
    2573             :         300, 30, 86400,
    2574             :         NULL, NULL, NULL
    2575             :     },
    2576             : 
    2577             :     {
    2578             :         {"checkpoint_warning", PGC_SIGHUP, WAL_CHECKPOINTS,
    2579             :             gettext_noop("Enables warnings if checkpoint segments are filled more "
    2580             :                          "frequently than this."),
    2581             :             gettext_noop("Write a message to the server log if checkpoints "
    2582             :                          "caused by the filling of checkpoint segment files happens more "
    2583             :                          "frequently than this number of seconds. Zero turns off the warning."),
    2584             :             GUC_UNIT_S
    2585             :         },
    2586             :         &CheckPointWarning,
    2587             :         30, 0, INT_MAX,
    2588             :         NULL, NULL, NULL
    2589             :     },
    2590             : 
    2591             :     {
    2592             :         {"checkpoint_flush_after", PGC_SIGHUP, WAL_CHECKPOINTS,
    2593             :             gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
    2594             :             NULL,
    2595             :             GUC_UNIT_BLOCKS
    2596             :         },
    2597             :         &checkpoint_flush_after,
    2598             :         DEFAULT_CHECKPOINT_FLUSH_AFTER, 0, WRITEBACK_MAX_PENDING_FLUSHES,
    2599             :         NULL, NULL, NULL
    2600             :     },
    2601             : 
    2602             :     {
    2603             :         {"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
    2604             :             gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
    2605             :             NULL,
    2606             :             GUC_UNIT_XBLOCKS
    2607             :         },
    2608             :         &XLOGbuffers,
    2609             :         -1, -1, (INT_MAX / XLOG_BLCKSZ),
    2610             :         check_wal_buffers, NULL, NULL
    2611             :     },
    2612             : 
    2613             :     {
    2614             :         {"wal_writer_delay", PGC_SIGHUP, WAL_SETTINGS,
    2615             :             gettext_noop("Time between WAL flushes performed in the WAL writer."),
    2616             :             NULL,
    2617             :             GUC_UNIT_MS
    2618             :         },
    2619             :         &WalWriterDelay,
    2620             :         200, 1, 10000,
    2621             :         NULL, NULL, NULL
    2622             :     },
    2623             : 
    2624             :     {
    2625             :         {"wal_writer_flush_after", PGC_SIGHUP, WAL_SETTINGS,
    2626             :             gettext_noop("Amount of WAL written out by WAL writer that triggers a flush."),
    2627             :             NULL,
    2628             :             GUC_UNIT_XBLOCKS
    2629             :         },
    2630             :         &WalWriterFlushAfter,
    2631             :         (1024 * 1024) / XLOG_BLCKSZ, 0, INT_MAX,
    2632             :         NULL, NULL, NULL
    2633             :     },
    2634             : 
    2635             :     {
    2636             :         {"max_wal_senders", PGC_POSTMASTER, REPLICATION_SENDING,
    2637             :             gettext_noop("Sets the maximum number of simultaneously running WAL sender processes."),
    2638             :             NULL
    2639             :         },
    2640             :         &max_wal_senders,
    2641             :         10, 0, MAX_BACKENDS,
    2642             :         check_max_wal_senders, NULL, NULL
    2643             :     },
    2644             : 
    2645             :     {
    2646             :         /* see max_wal_senders */
    2647             :         {"max_replication_slots", PGC_POSTMASTER, REPLICATION_SENDING,
    2648             :             gettext_noop("Sets the maximum number of simultaneously defined replication slots."),
    2649             :             NULL
    2650             :         },
    2651             :         &max_replication_slots,
    2652             :         10, 0, MAX_BACKENDS /* XXX? */ ,
    2653             :         NULL, NULL, NULL
    2654             :     },
    2655             : 
    2656             :     {
    2657             :         {"wal_sender_timeout", PGC_USERSET, REPLICATION_SENDING,
    2658             :             gettext_noop("Sets the maximum time to wait for WAL replication."),
    2659             :             NULL,
    2660             :             GUC_UNIT_MS
    2661             :         },
    2662             :         &wal_sender_timeout,
    2663             :         60 * 1000, 0, INT_MAX,
    2664             :         NULL, NULL, NULL
    2665             :     },
    2666             : 
    2667             :     {
    2668             :         {"commit_delay", PGC_SUSET, WAL_SETTINGS,
    2669             :             gettext_noop("Sets the delay in microseconds between transaction commit and "
    2670             :                          "flushing WAL to disk."),
    2671             :             NULL
    2672             :             /* we have no microseconds designation, so can't supply units here */
    2673             :         },
    2674             :         &CommitDelay,
    2675             :         0, 0, 100000,
    2676             :         NULL, NULL, NULL
    2677             :     },
    2678             : 
    2679             :     {
    2680             :         {"commit_siblings", PGC_USERSET, WAL_SETTINGS,
    2681             :             gettext_noop("Sets the minimum concurrent open transactions before performing "
    2682             :                          "commit_delay."),
    2683             :             NULL
    2684             :         },
    2685             :         &CommitSiblings,
    2686             :         5, 0, 1000,
    2687             :         NULL, NULL, NULL
    2688             :     },
    2689             : 
    2690             :     {
    2691             :         {"extra_float_digits", PGC_USERSET, CLIENT_CONN_LOCALE,
    2692             :             gettext_noop("Sets the number of digits displayed for floating-point values."),
    2693             :             gettext_noop("This affects real, double precision, and geometric data types. "
    2694             :                          "A zero or negative parameter value is added to the standard "
    2695             :                          "number of digits (FLT_DIG or DBL_DIG as appropriate). "
    2696             :                          "Any value greater than zero selects precise output mode.")
    2697             :         },
    2698             :         &extra_float_digits,
    2699             :         1, -15, 3,
    2700             :         NULL, NULL, NULL
    2701             :     },
    2702             : 
    2703             :     {
    2704             :         {"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN,
    2705             :             gettext_noop("Sets the minimum execution time above which "
    2706             :                          "statements will be logged."),
    2707             :             gettext_noop("Zero prints all queries. -1 turns this feature off."),
    2708             :             GUC_UNIT_MS
    2709             :         },
    2710             :         &log_min_duration_statement,
    2711             :         -1, -1, INT_MAX,
    2712             :         NULL, NULL, NULL
    2713             :     },
    2714             : 
    2715             :     {
    2716             :         {"log_autovacuum_min_duration", PGC_SIGHUP, LOGGING_WHAT,
    2717             :             gettext_noop("Sets the minimum execution time above which "
    2718             :                          "autovacuum actions will be logged."),
    2719             :             gettext_noop("Zero prints all actions. -1 turns autovacuum logging off."),
    2720             :             GUC_UNIT_MS
    2721             :         },
    2722             :         &Log_autovacuum_min_duration,
    2723             :         -1, -1, INT_MAX,
    2724             :         NULL, NULL, NULL
    2725             :     },
    2726             : 
    2727             :     {
    2728             :         {"bgwriter_delay", PGC_SIGHUP, RESOURCES_BGWRITER,
    2729             :             gettext_noop("Background writer sleep time between rounds."),
    2730             :             NULL,
    2731             :             GUC_UNIT_MS
    2732             :         },
    2733             :         &BgWriterDelay,
    2734             :         200, 10, 10000,
    2735             :         NULL, NULL, NULL
    2736             :     },
    2737             : 
    2738             :     {
    2739             :         {"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES_BGWRITER,
    2740             :             gettext_noop("Background writer maximum number of LRU pages to flush per round."),
    2741             :             NULL
    2742             :         },
    2743             :         &bgwriter_lru_maxpages,
    2744             :         100, 0, INT_MAX / 2,    /* Same upper limit as shared_buffers */
    2745             :         NULL, NULL, NULL
    2746             :     },
    2747             : 
    2748             :     {
    2749             :         {"bgwriter_flush_after", PGC_SIGHUP, RESOURCES_BGWRITER,
    2750             :             gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
    2751             :             NULL,
    2752             :             GUC_UNIT_BLOCKS
    2753             :         },
    2754             :         &bgwriter_flush_after,
    2755             :         DEFAULT_BGWRITER_FLUSH_AFTER, 0, WRITEBACK_MAX_PENDING_FLUSHES,
    2756             :         NULL, NULL, NULL
    2757             :     },
    2758             : 
    2759             :     {
    2760             :         {"effective_io_concurrency",
    2761             :             PGC_USERSET,
    2762             :             RESOURCES_ASYNCHRONOUS,
    2763             :             gettext_noop("Number of simultaneous requests that can be handled efficiently by the disk subsystem."),
    2764             :             gettext_noop("For RAID arrays, this should be approximately the number of drive spindles in the array."),
    2765             :             GUC_EXPLAIN
    2766             :         },
    2767             :         &effective_io_concurrency,
    2768             : #ifdef USE_PREFETCH
    2769             :         1,
    2770             : #else
    2771             :         0,
    2772             : #endif
    2773             :         0, MAX_IO_CONCURRENCY,
    2774             :         check_effective_io_concurrency, assign_effective_io_concurrency, NULL
    2775             :     },
    2776             : 
    2777             :     {
    2778             :         {"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
    2779             :             gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
    2780             :             NULL,
    2781             :             GUC_UNIT_BLOCKS
    2782             :         },
    2783             :         &backend_flush_after,
    2784             :         DEFAULT_BACKEND_FLUSH_AFTER, 0, WRITEBACK_MAX_PENDING_FLUSHES,
    2785             :         NULL, NULL, NULL
    2786             :     },
    2787             : 
    2788             :     {
    2789             :         {"max_worker_processes",
    2790             :             PGC_POSTMASTER,
    2791             :             RESOURCES_ASYNCHRONOUS,
    2792             :             gettext_noop("Maximum number of concurrent worker processes."),
    2793             :             NULL,
    2794             :         },
    2795             :         &max_worker_processes,
    2796             :         8, 0, MAX_BACKENDS,
    2797             :         check_max_worker_processes, NULL, NULL
    2798             :     },
    2799             : 
    2800             :     {
    2801             :         {"max_logical_replication_workers",
    2802             :             PGC_POSTMASTER,
    2803             :             REPLICATION_SUBSCRIBERS,
    2804             :             gettext_noop("Maximum number of logical replication worker processes."),
    2805             :             NULL,
    2806             :         },
    2807             :         &max_logical_replication_workers,
    2808             :         4, 0, MAX_BACKENDS,
    2809             :         NULL, NULL, NULL
    2810             :     },
    2811             : 
    2812             :     {
    2813             :         {"max_sync_workers_per_subscription",
    2814             :             PGC_SIGHUP,
    2815             :             REPLICATION_SUBSCRIBERS,
    2816             :             gettext_noop("Maximum number of table synchronization workers per subscription."),
    2817             :             NULL,
    2818             :         },
    2819             :         &max_sync_workers_per_subscription,
    2820             :         2, 0, MAX_BACKENDS,
    2821             :         NULL, NULL, NULL
    2822             :     },
    2823             : 
    2824             :     {
    2825             :         {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
    2826             :             gettext_noop("Automatic log file rotation will occur after N minutes."),
    2827             :             NULL,
    2828             :             GUC_UNIT_MIN
    2829             :         },
    2830             :         &Log_RotationAge,
    2831             :         HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / SECS_PER_MINUTE,
    2832             :         NULL, NULL, NULL
    2833             :     },
    2834             : 
    2835             :     {
    2836             :         {"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
    2837             :             gettext_noop("Automatic log file rotation will occur after N kilobytes."),
    2838             :             NULL,
    2839             :             GUC_UNIT_KB
    2840             :         },
    2841             :         &Log_RotationSize,
    2842             :         10 * 1024, 0, INT_MAX / 1024,
    2843             :         NULL, NULL, NULL
    2844             :     },
    2845             : 
    2846             :     {
    2847             :         {"max_function_args", PGC_INTERNAL, PRESET_OPTIONS,
    2848             :             gettext_noop("Shows the maximum number of function arguments."),
    2849             :             NULL,
    2850             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    2851             :         },
    2852             :         &max_function_args,
    2853             :         FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS,
    2854             :         NULL, NULL, NULL
    2855             :     },
    2856             : 
    2857             :     {
    2858             :         {"max_index_keys", PGC_INTERNAL, PRESET_OPTIONS,
    2859             :             gettext_noop("Shows the maximum number of index keys."),
    2860             :             NULL,
    2861             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    2862             :         },
    2863             :         &max_index_keys,
    2864             :         INDEX_MAX_KEYS, INDEX_MAX_KEYS, INDEX_MAX_KEYS,
    2865             :         NULL, NULL, NULL
    2866             :     },
    2867             : 
    2868             :     {
    2869             :         {"max_identifier_length", PGC_INTERNAL, PRESET_OPTIONS,
    2870             :             gettext_noop("Shows the maximum identifier length."),
    2871             :             NULL,
    2872             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    2873             :         },
    2874             :         &max_identifier_length,
    2875             :         NAMEDATALEN - 1, NAMEDATALEN - 1, NAMEDATALEN - 1,
    2876             :         NULL, NULL, NULL
    2877             :     },
    2878             : 
    2879             :     {
    2880             :         {"block_size", PGC_INTERNAL, PRESET_OPTIONS,
    2881             :             gettext_noop("Shows the size of a disk block."),
    2882             :             NULL,
    2883             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    2884             :         },
    2885             :         &block_size,
    2886             :         BLCKSZ, BLCKSZ, BLCKSZ,
    2887             :         NULL, NULL, NULL
    2888             :     },
    2889             : 
    2890             :     {
    2891             :         {"segment_size", PGC_INTERNAL, PRESET_OPTIONS,
    2892             :             gettext_noop("Shows the number of pages per disk file."),
    2893             :             NULL,
    2894             :             GUC_UNIT_BLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    2895             :         },
    2896             :         &segment_size,
    2897             :         RELSEG_SIZE, RELSEG_SIZE, RELSEG_SIZE,
    2898             :         NULL, NULL, NULL
    2899             :     },
    2900             : 
    2901             :     {
    2902             :         {"wal_block_size", PGC_INTERNAL, PRESET_OPTIONS,
    2903             :             gettext_noop("Shows the block size in the write ahead log."),
    2904             :             NULL,
    2905             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    2906             :         },
    2907             :         &wal_block_size,
    2908             :         XLOG_BLCKSZ, XLOG_BLCKSZ, XLOG_BLCKSZ,
    2909             :         NULL, NULL, NULL
    2910             :     },
    2911             : 
    2912             :     {
    2913             :         {"wal_retrieve_retry_interval", PGC_SIGHUP, REPLICATION_STANDBY,
    2914             :             gettext_noop("Sets the time to wait before retrying to retrieve WAL "
    2915             :                          "after a failed attempt."),
    2916             :             NULL,
    2917             :             GUC_UNIT_MS
    2918             :         },
    2919             :         &wal_retrieve_retry_interval,
    2920             :         5000, 1, INT_MAX,
    2921             :         NULL, NULL, NULL
    2922             :     },
    2923             : 
    2924             :     {
    2925             :         {"wal_segment_size", PGC_INTERNAL, PRESET_OPTIONS,
    2926             :             gettext_noop("Shows the size of write ahead log segments."),
    2927             :             NULL,
    2928             :             GUC_UNIT_BYTE | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    2929             :         },
    2930             :         &wal_segment_size,
    2931             :         DEFAULT_XLOG_SEG_SIZE,
    2932             :         WalSegMinSize,
    2933             :         WalSegMaxSize,
    2934             :         NULL, NULL, NULL
    2935             :     },
    2936             : 
    2937             :     {
    2938             :         {"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
    2939             :             gettext_noop("Time to sleep between autovacuum runs."),
    2940             :             NULL,
    2941             :             GUC_UNIT_S
    2942             :         },
    2943             :         &autovacuum_naptime,
    2944             :         60, 1, INT_MAX / 1000,
    2945             :         NULL, NULL, NULL
    2946             :     },
    2947             :     {
    2948             :         {"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
    2949             :             gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
    2950             :             NULL
    2951             :         },
    2952             :         &autovacuum_vac_thresh,
    2953             :         50, 0, INT_MAX,
    2954             :         NULL, NULL, NULL
    2955             :     },
    2956             :     {
    2957             :         {"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
    2958             :             gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."),
    2959             :             NULL
    2960             :         },
    2961             :         &autovacuum_anl_thresh,
    2962             :         50, 0, INT_MAX,
    2963             :         NULL, NULL, NULL
    2964             :     },
    2965             :     {
    2966             :         /* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
    2967             :         {"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
    2968             :             gettext_noop("Age at which to autovacuum a table to prevent transaction ID wraparound."),
    2969             :             NULL
    2970             :         },
    2971             :         &autovacuum_freeze_max_age,
    2972             :         /* see pg_resetwal if you change the upper-limit value */
    2973             :         200000000, 100000, 2000000000,
    2974             :         NULL, NULL, NULL
    2975             :     },
    2976             :     {
    2977             :         /* see multixact.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
    2978             :         {"autovacuum_multixact_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
    2979             :             gettext_noop("Multixact age at which to autovacuum a table to prevent multixact wraparound."),
    2980             :             NULL
    2981             :         },
    2982             :         &autovacuum_multixact_freeze_max_age,
    2983             :         400000000, 10000, 2000000000,
    2984             :         NULL, NULL, NULL
    2985             :     },
    2986             :     {
    2987             :         /* see max_connections */
    2988             :         {"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
    2989             :             gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
    2990             :             NULL
    2991             :         },
    2992             :         &autovacuum_max_workers,
    2993             :         3, 1, MAX_BACKENDS,
    2994             :         check_autovacuum_max_workers, NULL, NULL
    2995             :     },
    2996             : 
    2997             :     {
    2998             :         {"max_parallel_maintenance_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
    2999             :             gettext_noop("Sets the maximum number of parallel processes per maintenance operation."),
    3000             :             NULL
    3001             :         },
    3002             :         &max_parallel_maintenance_workers,
    3003             :         2, 0, 1024,
    3004             :         NULL, NULL, NULL
    3005             :     },
    3006             : 
    3007             :     {
    3008             :         {"max_parallel_workers_per_gather", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
    3009             :             gettext_noop("Sets the maximum number of parallel processes per executor node."),
    3010             :             NULL,
    3011             :             GUC_EXPLAIN
    3012             :         },
    3013             :         &max_parallel_workers_per_gather,
    3014             :         2, 0, MAX_PARALLEL_WORKER_LIMIT,
    3015             :         NULL, NULL, NULL
    3016             :     },
    3017             : 
    3018             :     {
    3019             :         {"max_parallel_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
    3020             :             gettext_noop("Sets the maximum number of parallel workers that can be active at one time."),
    3021             :             NULL,
    3022             :             GUC_EXPLAIN
    3023             :         },
    3024             :         &max_parallel_workers,
    3025             :         8, 0, MAX_PARALLEL_WORKER_LIMIT,
    3026             :         NULL, NULL, NULL
    3027             :     },
    3028             : 
    3029             :     {
    3030             :         {"autovacuum_work_mem", PGC_SIGHUP, RESOURCES_MEM,
    3031             :             gettext_noop("Sets the maximum memory to be used by each autovacuum worker process."),
    3032             :             NULL,
    3033             :             GUC_UNIT_KB
    3034             :         },
    3035             :         &autovacuum_work_mem,
    3036             :         -1, -1, MAX_KILOBYTES,
    3037             :         check_autovacuum_work_mem, NULL, NULL
    3038             :     },
    3039             : 
    3040             :     {
    3041             :         {"old_snapshot_threshold", PGC_POSTMASTER, RESOURCES_ASYNCHRONOUS,
    3042             :             gettext_noop("Time before a snapshot is too old to read pages changed after the snapshot was taken."),
    3043             :             gettext_noop("A value of -1 disables this feature."),
    3044             :             GUC_UNIT_MIN
    3045             :         },
    3046             :         &old_snapshot_threshold,
    3047             :         -1, -1, MINS_PER_HOUR * HOURS_PER_DAY * 60,
    3048             :         NULL, NULL, NULL
    3049             :     },
    3050             : 
    3051             :     {
    3052             :         {"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER,
    3053             :             gettext_noop("Time between issuing TCP keepalives."),
    3054             :             gettext_noop("A value of 0 uses the system default."),
    3055             :             GUC_UNIT_S
    3056             :         },
    3057             :         &tcp_keepalives_idle,
    3058             :         0, 0, INT_MAX,
    3059             :         NULL, assign_tcp_keepalives_idle, show_tcp_keepalives_idle
    3060             :     },
    3061             : 
    3062             :     {
    3063             :         {"tcp_keepalives_interval", PGC_USERSET, CLIENT_CONN_OTHER,
    3064             :             gettext_noop("Time between TCP keepalive retransmits."),
    3065             :             gettext_noop("A value of 0 uses the system default."),
    3066             :             GUC_UNIT_S
    3067             :         },
    3068             :         &tcp_keepalives_interval,
    3069             :         0, 0, INT_MAX,
    3070             :         NULL, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
    3071             :     },
    3072             : 
    3073             :     {
    3074             :         {"ssl_renegotiation_limit", PGC_USERSET, CONN_AUTH_SSL,
    3075             :             gettext_noop("SSL renegotiation is no longer supported; this can only be 0."),
    3076             :             NULL,
    3077             :             GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE,
    3078             :         },
    3079             :         &ssl_renegotiation_limit,
    3080             :         0, 0, 0,
    3081             :         NULL, NULL, NULL
    3082             :     },
    3083             : 
    3084             :     {
    3085             :         {"tcp_keepalives_count", PGC_USERSET, CLIENT_CONN_OTHER,
    3086             :             gettext_noop("Maximum number of TCP keepalive retransmits."),
    3087             :             gettext_noop("This controls the number of consecutive keepalive retransmits that can be "
    3088             :                          "lost before a connection is considered dead. A value of 0 uses the "
    3089             :                          "system default."),
    3090             :         },
    3091             :         &tcp_keepalives_count,
    3092             :         0, 0, INT_MAX,
    3093             :         NULL, assign_tcp_keepalives_count, show_tcp_keepalives_count
    3094             :     },
    3095             : 
    3096             :     {
    3097             :         {"gin_fuzzy_search_limit", PGC_USERSET, CLIENT_CONN_OTHER,
    3098             :             gettext_noop("Sets the maximum allowed result for exact search by GIN."),
    3099             :             NULL,
    3100             :             0
    3101             :         },
    3102             :         &GinFuzzySearchLimit,
    3103             :         0, 0, INT_MAX,
    3104             :         NULL, NULL, NULL
    3105             :     },
    3106             : 
    3107             :     {
    3108             :         {"effective_cache_size", PGC_USERSET, QUERY_TUNING_COST,
    3109             :             gettext_noop("Sets the planner's assumption about the total size of the data caches."),
    3110             :             gettext_noop("That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. "
    3111             :                          "This is measured in disk pages, which are normally 8 kB each."),
    3112             :             GUC_UNIT_BLOCKS | GUC_EXPLAIN,
    3113             :         },
    3114             :         &effective_cache_size,
    3115             :         DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX,
    3116             :         NULL, NULL, NULL
    3117             :     },
    3118             : 
    3119             :     {
    3120             :         {"min_parallel_table_scan_size", PGC_USERSET, QUERY_TUNING_COST,
    3121             :             gettext_noop("Sets the minimum amount of table data for a parallel scan."),
    3122             :             gettext_noop("If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered."),
    3123             :             GUC_UNIT_BLOCKS | GUC_EXPLAIN,
    3124             :         },
    3125             :         &min_parallel_table_scan_size,
    3126             :         (8 * 1024 * 1024) / BLCKSZ, 0, INT_MAX / 3,
    3127             :         NULL, NULL, NULL
    3128             :     },
    3129             : 
    3130             :     {
    3131             :         {"min_parallel_index_scan_size", PGC_USERSET, QUERY_TUNING_COST,
    3132             :             gettext_noop("Sets the minimum amount of index data for a parallel scan."),
    3133             :             gettext_noop("If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered."),
    3134             :             GUC_UNIT_BLOCKS | GUC_EXPLAIN,
    3135             :         },
    3136             :         &min_parallel_index_scan_size,
    3137             :         (512 * 1024) / BLCKSZ, 0, INT_MAX / 3,
    3138             :         NULL, NULL, NULL
    3139             :     },
    3140             : 
    3141             :     {
    3142             :         /* Can't be set in postgresql.conf */
    3143             :         {"server_version_num", PGC_INTERNAL, PRESET_OPTIONS,
    3144             :             gettext_noop("Shows the server version as an integer."),
    3145             :             NULL,
    3146             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    3147             :         },
    3148             :         &server_version_num,
    3149             :         PG_VERSION_NUM, PG_VERSION_NUM, PG_VERSION_NUM,
    3150             :         NULL, NULL, NULL
    3151             :     },
    3152             : 
    3153             :     {
    3154             :         {"log_temp_files", PGC_SUSET, LOGGING_WHAT,
    3155             :             gettext_noop("Log the use of temporary files larger than this number of kilobytes."),
    3156             :             gettext_noop("Zero logs all files. The default is -1 (turning this feature off)."),
    3157             :             GUC_UNIT_KB
    3158             :         },
    3159             :         &log_temp_files,
    3160             :         -1, -1, INT_MAX,
    3161             :         NULL, NULL, NULL
    3162             :     },
    3163             : 
    3164             :     {
    3165             :         {"track_activity_query_size", PGC_POSTMASTER, RESOURCES_MEM,
    3166             :             gettext_noop("Sets the size reserved for pg_stat_activity.query, in bytes."),
    3167             :             NULL,
    3168             :             GUC_UNIT_BYTE
    3169             :         },
    3170             :         &pgstat_track_activity_query_size,
    3171             :         1024, 100, 102400,
    3172             :         NULL, NULL, NULL
    3173             :     },
    3174             : 
    3175             :     {
    3176             :         {"gin_pending_list_limit", PGC_USERSET, CLIENT_CONN_STATEMENT,
    3177             :             gettext_noop("Sets the maximum size of the pending list for GIN index."),
    3178             :             NULL,
    3179             :             GUC_UNIT_KB
    3180             :         },
    3181             :         &gin_pending_list_limit,
    3182             :         4096, 64, MAX_KILOBYTES,
    3183             :         NULL, NULL, NULL
    3184             :     },
    3185             : 
    3186             :     {
    3187             :         {"tcp_user_timeout", PGC_USERSET, CLIENT_CONN_OTHER,
    3188             :             gettext_noop("TCP user timeout."),
    3189             :             gettext_noop("A value of 0 uses the system default."),
    3190             :             GUC_UNIT_MS
    3191             :         },
    3192             :         &tcp_user_timeout,
    3193             :         0, 0, INT_MAX,
    3194             :         NULL, assign_tcp_user_timeout, show_tcp_user_timeout
    3195             :     },
    3196             : 
    3197             :     /* End-of-list marker */
    3198             :     {
    3199             :         {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
    3200             :     }
    3201             : };
    3202             : 
    3203             : 
    3204             : static struct config_real ConfigureNamesReal[] =
    3205             : {
    3206             :     {
    3207             :         {"seq_page_cost", PGC_USERSET, QUERY_TUNING_COST,
    3208             :             gettext_noop("Sets the planner's estimate of the cost of a "
    3209             :                          "sequentially fetched disk page."),
    3210             :             NULL,
    3211             :             GUC_EXPLAIN
    3212             :         },
    3213             :         &seq_page_cost,
    3214             :         DEFAULT_SEQ_PAGE_COST, 0, DBL_MAX,
    3215             :         NULL, NULL, NULL
    3216             :     },
    3217             :     {
    3218             :         {"random_page_cost", PGC_USERSET, QUERY_TUNING_COST,
    3219             :             gettext_noop("Sets the planner's estimate of the cost of a "
    3220             :                          "nonsequentially fetched disk page."),
    3221             :             NULL,
    3222             :             GUC_EXPLAIN
    3223             :         },
    3224             :         &random_page_cost,
    3225             :         DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX,
    3226             :         NULL, NULL, NULL
    3227             :     },
    3228             :     {
    3229             :         {"cpu_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
    3230             :             gettext_noop("Sets the planner's estimate of the cost of "
    3231             :                          "processing each tuple (row)."),
    3232             :             NULL,
    3233             :             GUC_EXPLAIN
    3234             :         },
    3235             :         &cpu_tuple_cost,
    3236             :         DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX,
    3237             :         NULL, NULL, NULL
    3238             :     },
    3239             :     {
    3240             :         {"cpu_index_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
    3241             :             gettext_noop("Sets the planner's estimate of the cost of "
    3242             :                          "processing each index entry during an index scan."),
    3243             :             NULL,
    3244             :             GUC_EXPLAIN
    3245             :         },
    3246             :         &cpu_index_tuple_cost,
    3247             :         DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX,
    3248             :         NULL, NULL, NULL
    3249             :     },
    3250             :     {
    3251             :         {"cpu_operator_cost", PGC_USERSET, QUERY_TUNING_COST,
    3252             :             gettext_noop("Sets the planner's estimate of the cost of "
    3253             :                          "processing each operator or function call."),
    3254             :             NULL,
    3255             :             GUC_EXPLAIN
    3256             :         },
    3257             :         &cpu_operator_cost,
    3258             :         DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX,
    3259             :         NULL, NULL, NULL
    3260             :     },
    3261             :     {
    3262             :         {"parallel_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
    3263             :             gettext_noop("Sets the planner's estimate of the cost of "
    3264             :                          "passing each tuple (row) from worker to master backend."),
    3265             :             NULL,
    3266             :             GUC_EXPLAIN
    3267             :         },
    3268             :         &parallel_tuple_cost,
    3269             :         DEFAULT_PARALLEL_TUPLE_COST, 0, DBL_MAX,
    3270             :         NULL, NULL, NULL
    3271             :     },
    3272             :     {
    3273             :         {"parallel_setup_cost", PGC_USERSET, QUERY_TUNING_COST,
    3274             :             gettext_noop("Sets the planner's estimate of the cost of "
    3275             :                          "starting up worker processes for parallel query."),
    3276             :             NULL,
    3277             :             GUC_EXPLAIN
    3278             :         },
    3279             :         &parallel_setup_cost,
    3280             :         DEFAULT_PARALLEL_SETUP_COST, 0, DBL_MAX,
    3281             :         NULL, NULL, NULL
    3282             :     },
    3283             : 
    3284             :     {
    3285             :         {"jit_above_cost", PGC_USERSET, QUERY_TUNING_COST,
    3286             :             gettext_noop("Perform JIT compilation if query is more expensive."),
    3287             :             gettext_noop("-1 disables JIT compilation."),
    3288             :             GUC_EXPLAIN
    3289             :         },
    3290             :         &jit_above_cost,
    3291             :         100000, -1, DBL_MAX,
    3292             :         NULL, NULL, NULL
    3293             :     },
    3294             : 
    3295             :     {
    3296             :         {"jit_optimize_above_cost", PGC_USERSET, QUERY_TUNING_COST,
    3297             :             gettext_noop("Optimize JITed functions if query is more expensive."),
    3298             :             gettext_noop("-1 disables optimization."),
    3299             :             GUC_EXPLAIN
    3300             :         },
    3301             :         &jit_optimize_above_cost,
    3302             :         500000, -1, DBL_MAX,
    3303             :         NULL, NULL, NULL
    3304             :     },
    3305             : 
    3306             :     {
    3307             :         {"jit_inline_above_cost", PGC_USERSET, QUERY_TUNING_COST,
    3308             :             gettext_noop("Perform JIT inlining if query is more expensive."),
    3309             :             gettext_noop("-1 disables inlining."),
    3310             :             GUC_EXPLAIN
    3311             :         },
    3312             :         &jit_inline_above_cost,
    3313             :         500000, -1, DBL_MAX,
    3314             :         NULL, NULL, NULL
    3315             :     },
    3316             : 
    3317             :     {
    3318             :         {"cursor_tuple_fraction", PGC_USERSET, QUERY_TUNING_OTHER,
    3319             :             gettext_noop("Sets the planner's estimate of the fraction of "
    3320             :                          "a cursor's rows that will be retrieved."),
    3321             :             NULL,
    3322             :             GUC_EXPLAIN
    3323             :         },
    3324             :         &cursor_tuple_fraction,
    3325             :         DEFAULT_CURSOR_TUPLE_FRACTION, 0.0, 1.0,
    3326             :         NULL, NULL, NULL
    3327             :     },
    3328             : 
    3329             :     {
    3330             :         {"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO,
    3331             :             gettext_noop("GEQO: selective pressure within the population."),
    3332             :             NULL,
    3333             :             GUC_EXPLAIN
    3334             :         },
    3335             :         &Geqo_selection_bias,
    3336             :         DEFAULT_GEQO_SELECTION_BIAS,
    3337             :         MIN_GEQO_SELECTION_BIAS, MAX_GEQO_SELECTION_BIAS,
    3338             :         NULL, NULL, NULL
    3339             :     },
    3340             :     {
    3341             :         {"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
    3342             :             gettext_noop("GEQO: seed for random path selection."),
    3343             :             NULL,
    3344             :             GUC_EXPLAIN
    3345             :         },
    3346             :         &Geqo_seed,
    3347             :         0.0, 0.0, 1.0,
    3348             :         NULL, NULL, NULL
    3349             :     },
    3350             : 
    3351             :     {
    3352             :         {"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES_BGWRITER,
    3353             :             gettext_noop("Multiple of the average buffer usage to free per round."),
    3354             :             NULL
    3355             :         },
    3356             :         &bgwriter_lru_multiplier,
    3357             :         2.0, 0.0, 10.0,
    3358             :         NULL, NULL, NULL
    3359             :     },
    3360             : 
    3361             :     {
    3362             :         {"seed", PGC_USERSET, UNGROUPED,
    3363             :             gettext_noop("Sets the seed for random-number generation."),
    3364             :             NULL,
    3365             :             GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    3366             :         },
    3367             :         &phony_random_seed,
    3368             :         0.0, -1.0, 1.0,
    3369             :         check_random_seed, assign_random_seed, show_random_seed
    3370             :     },
    3371             : 
    3372             :     {
    3373             :         {"vacuum_cost_delay", PGC_USERSET, RESOURCES_VACUUM_DELAY,
    3374             :             gettext_noop("Vacuum cost delay in milliseconds."),
    3375             :             NULL,
    3376             :             GUC_UNIT_MS
    3377             :         },
    3378             :         &VacuumCostDelay,
    3379             :         0, 0, 100,
    3380             :         NULL, NULL, NULL
    3381             :     },
    3382             : 
    3383             :     {
    3384             :         {"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
    3385             :             gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
    3386             :             NULL,
    3387             :             GUC_UNIT_MS
    3388             :         },
    3389             :         &autovacuum_vac_cost_delay,
    3390             :         2, -1, 100,
    3391             :         NULL, NULL, NULL
    3392             :     },
    3393             : 
    3394             :     {
    3395             :         {"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
    3396             :             gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
    3397             :             NULL
    3398             :         },
    3399             :         &autovacuum_vac_scale,
    3400             :         0.2, 0.0, 100.0,
    3401             :         NULL, NULL, NULL
    3402             :     },
    3403             :     {
    3404             :         {"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
    3405             :             gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."),
    3406             :             NULL
    3407             :         },
    3408             :         &autovacuum_anl_scale,
    3409             :         0.1, 0.0, 100.0,
    3410             :         NULL, NULL, NULL
    3411             :     },
    3412             : 
    3413             :     {
    3414             :         {"checkpoint_completion_target", PGC_SIGHUP, WAL_CHECKPOINTS,
    3415             :             gettext_noop("Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."),
    3416             :             NULL
    3417             :         },
    3418             :         &CheckPointCompletionTarget,
    3419             :         0.5, 0.0, 1.0,
    3420             :         NULL, NULL, NULL
    3421             :     },
    3422             : 
    3423             :     {
    3424             :         {"vacuum_cleanup_index_scale_factor", PGC_USERSET, CLIENT_CONN_STATEMENT,
    3425             :             gettext_noop("Number of tuple inserts prior to index cleanup as a fraction of reltuples."),
    3426             :             NULL
    3427             :         },
    3428             :         &vacuum_cleanup_index_scale_factor,
    3429             :         0.1, 0.0, 1e10,
    3430             :         NULL, NULL, NULL
    3431             :     },
    3432             : 
    3433             :     {
    3434             :         {"log_transaction_sample_rate", PGC_SUSET, LOGGING_WHEN,
    3435             :             gettext_noop("Set the fraction of transactions to log for new transactions."),
    3436             :             gettext_noop("Logs all statements from a fraction of transactions. "
    3437             :                          "Use a value between 0.0 (never log) and 1.0 (log all "
    3438             :                          "statements for all transactions).")
    3439             :         },
    3440             :         &log_xact_sample_rate,
    3441             :         0.0, 0.0, 1.0,
    3442             :         NULL, NULL, NULL
    3443             :     },
    3444             : 
    3445             :     /* End-of-list marker */
    3446             :     {
    3447             :         {NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL, NULL
    3448             :     }
    3449             : };
    3450             : 
    3451             : 
    3452             : static struct config_string ConfigureNamesString[] =
    3453             : {
    3454             :     {
    3455             :         {"archive_command", PGC_SIGHUP, WAL_ARCHIVING,
    3456             :             gettext_noop("Sets the shell command that will be called to archive a WAL file."),
    3457             :             NULL
    3458             :         },
    3459             :         &XLogArchiveCommand,
    3460             :         "",
    3461             :         NULL, NULL, show_archive_command
    3462             :     },
    3463             : 
    3464             :     {
    3465             :         {"restore_command", PGC_POSTMASTER, WAL_ARCHIVE_RECOVERY,
    3466             :             gettext_noop("Sets the shell command that will retrieve an archived WAL file."),
    3467             :             NULL
    3468             :         },
    3469             :         &recoveryRestoreCommand,
    3470             :         "",
    3471             :         NULL, NULL, NULL
    3472             :     },
    3473             : 
    3474             :     {
    3475             :         {"archive_cleanup_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
    3476             :             gettext_noop("Sets the shell command that will be executed at every restart point."),
    3477             :             NULL
    3478             :         },
    3479             :         &archiveCleanupCommand,
    3480             :         "",
    3481             :         NULL, NULL, NULL
    3482             :     },
    3483             : 
    3484             :     {
    3485             :         {"recovery_end_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
    3486             :             gettext_noop("Sets the shell command that will be executed once at the end of recovery."),
    3487             :             NULL
    3488             :         },
    3489             :         &recoveryEndCommand,
    3490             :         "",
    3491             :         NULL, NULL, NULL
    3492             :     },
    3493             : 
    3494             :     {
    3495             :         {"recovery_target_timeline", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
    3496             :             gettext_noop("Specifies the timeline to recovery into."),
    3497             :             NULL
    3498             :         },
    3499             :         &recovery_target_timeline_string,
    3500             :         "latest",
    3501             :         check_recovery_target_timeline, assign_recovery_target_timeline, NULL
    3502             :     },
    3503             : 
    3504             :     {
    3505             :         {"recovery_target", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
    3506             :             gettext_noop("Set to 'immediate' to end recovery as soon as a consistent state is reached."),
    3507             :             NULL
    3508             :         },
    3509             :         &recovery_target_string,
    3510             :         "",
    3511             :         check_recovery_target, assign_recovery_target, NULL
    3512             :     },
    3513             :     {
    3514             :         {"recovery_target_xid", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
    3515             :             gettext_noop("Sets the transaction ID up to which recovery will proceed."),
    3516             :             NULL
    3517             :         },
    3518             :         &recovery_target_xid_string,
    3519             :         "",
    3520             :         check_recovery_target_xid, assign_recovery_target_xid, NULL
    3521             :     },
    3522             :     {
    3523             :         {"recovery_target_time", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
    3524             :             gettext_noop("Sets the time stamp up to which recovery will proceed."),
    3525             :             NULL
    3526             :         },
    3527             :         &recovery_target_time_string,
    3528             :         "",
    3529             :         check_recovery_target_time, assign_recovery_target_time, NULL
    3530             :     },
    3531             :     {
    3532             :         {"recovery_target_name", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
    3533             :             gettext_noop("Sets the named restore point up to which recovery will proceed."),
    3534             :             NULL
    3535             :         },
    3536             :         &recovery_target_name_string,
    3537             :         "",
    3538             :         check_recovery_target_name, assign_recovery_target_name, NULL
    3539             :     },
    3540             :     {
    3541             :         {"recovery_target_lsn", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
    3542             :             gettext_noop("Sets the LSN of the write-ahead log location up to which recovery will proceed."),
    3543             :             NULL
    3544             :         },
    3545             :         &recovery_target_lsn_string,
    3546             :         "",
    3547             :         check_recovery_target_lsn, assign_recovery_target_lsn, NULL
    3548             :     },
    3549             : 
    3550             :     {
    3551             :         {"promote_trigger_file", PGC_SIGHUP, REPLICATION_STANDBY,
    3552             :             gettext_noop("Specifies a file name whose presence ends recovery in the standby."),
    3553             :             NULL
    3554             :         },
    3555             :         &PromoteTriggerFile,
    3556             :         "",
    3557             :         NULL, NULL, NULL
    3558             :     },
    3559             : 
    3560             :     {
    3561             :         {"primary_conninfo", PGC_POSTMASTER, REPLICATION_STANDBY,
    3562             :             gettext_noop("Sets the connection string to be used to connect to the sending server."),
    3563             :             NULL,
    3564             :             GUC_SUPERUSER_ONLY
    3565             :         },
    3566             :         &PrimaryConnInfo,
    3567             :         "",
    3568             :         NULL, NULL, NULL
    3569             :     },
    3570             : 
    3571             :     {
    3572             :         {"primary_slot_name", PGC_POSTMASTER, REPLICATION_STANDBY,
    3573             :             gettext_noop("Sets the name of the replication slot to use on the sending server."),
    3574             :             NULL
    3575             :         },
    3576             :         &PrimarySlotName,
    3577             :         "",
    3578             :         check_primary_slot_name, NULL, NULL
    3579             :     },
    3580             : 
    3581             :     {
    3582             :         {"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
    3583             :             gettext_noop("Sets the client's character set encoding."),
    3584             :             NULL,
    3585             :             GUC_IS_NAME | GUC_REPORT
    3586             :         },
    3587             :         &client_encoding_string,
    3588             :         "SQL_ASCII",
    3589             :         check_client_encoding, assign_client_encoding, NULL
    3590             :     },
    3591             : 
    3592             :     {
    3593             :         {"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
    3594             :             gettext_noop("Controls information prefixed to each log line."),
    3595             :             gettext_noop("If blank, no prefix is used.")
    3596             :         },
    3597             :         &Log_line_prefix,
    3598             :         "%m [%p] ",
    3599             :         NULL, NULL, NULL
    3600             :     },
    3601             : 
    3602             :     {
    3603             :         {"log_timezone", PGC_SIGHUP, LOGGING_WHAT,
    3604             :             gettext_noop("Sets the time zone to use in log messages."),
    3605             :             NULL
    3606             :         },
    3607             :         &log_timezone_string,
    3608             :         "GMT",
    3609             :         check_log_timezone, assign_log_timezone, show_log_timezone
    3610             :     },
    3611             : 
    3612             :     {
    3613             :         {"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
    3614             :             gettext_noop("Sets the display format for date and time values."),
    3615             :             gettext_noop("Also controls interpretation of ambiguous "
    3616             :                          "date inputs."),
    3617             :             GUC_LIST_INPUT | GUC_REPORT
    3618             :         },
    3619             :         &datestyle_string,
    3620             :         "ISO, MDY",
    3621             :         check_datestyle, assign_datestyle, NULL
    3622             :     },
    3623             : 
    3624             :     {
    3625             :         {"default_table_access_method", PGC_USERSET, CLIENT_CONN_STATEMENT,
    3626             :             gettext_noop("Sets the default table access method for new tables."),
    3627             :             NULL,
    3628             :             GUC_IS_NAME
    3629             :         },
    3630             :         &default_table_access_method,
    3631             :         DEFAULT_TABLE_ACCESS_METHOD,
    3632             :         check_default_table_access_method, NULL, NULL
    3633             :     },
    3634             : 
    3635             :     {
    3636             :         {"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT,
    3637             :             gettext_noop("Sets the default tablespace to create tables and indexes in."),
    3638             :             gettext_noop("An empty string selects the database's default tablespace."),
    3639             :             GUC_IS_NAME
    3640             :         },
    3641             :         &default_tablespace,
    3642             :         "",
    3643             :         check_default_tablespace, NULL, NULL
    3644             :     },
    3645             : 
    3646             :     {
    3647             :         {"temp_tablespaces", PGC_USERSET, CLIENT_CONN_STATEMENT,
    3648             :             gettext_noop("Sets the tablespace(s) to use for temporary tables and sort files."),
    3649             :             NULL,
    3650             :             GUC_LIST_INPUT | GUC_LIST_QUOTE
    3651             :         },
    3652             :         &temp_tablespaces,
    3653             :         "",
    3654             :         check_temp_tablespaces, assign_temp_tablespaces, NULL
    3655             :     },
    3656             : 
    3657             :     {
    3658             :         {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
    3659             :             gettext_noop("Sets the path for dynamically loadable modules."),
    3660             :             gettext_noop("If a dynamically loadable module needs to be opened and "
    3661             :                          "the specified name does not have a directory component (i.e., the "
    3662             :                          "name does not contain a slash), the system will search this path for "
    3663             :                          "the specified file."),
    3664             :             GUC_SUPERUSER_ONLY
    3665             :         },
    3666             :         &Dynamic_library_path,
    3667             :         "$libdir",
    3668             :         NULL, NULL, NULL
    3669             :     },
    3670             : 
    3671             :     {
    3672             :         {"krb_server_keyfile", PGC_SIGHUP, CONN_AUTH_AUTH,
    3673             :             gettext_noop("Sets the location of the Kerberos server key file."),
    3674             :             NULL,
    3675             :             GUC_SUPERUSER_ONLY
    3676             :         },
    3677             :         &pg_krb_server_keyfile,
    3678             :         PG_KRB_SRVTAB,
    3679             :         NULL, NULL, NULL
    3680             :     },
    3681             : 
    3682             :     {
    3683             :         {"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    3684             :             gettext_noop("Sets the Bonjour service name."),
    3685             :             NULL
    3686             :         },
    3687             :         &bonjour_name,
    3688             :         "",
    3689             :         NULL, NULL, NULL
    3690             :     },
    3691             : 
    3692             :     /* See main.c about why defaults for LC_foo are not all alike */
    3693             : 
    3694             :     {
    3695             :         {"lc_collate", PGC_INTERNAL, CLIENT_CONN_LOCALE,
    3696             :             gettext_noop("Shows the collation order locale."),
    3697             :             NULL,
    3698             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    3699             :         },
    3700             :         &locale_collate,
    3701             :         "C",
    3702             :         NULL, NULL, NULL
    3703             :     },
    3704             : 
    3705             :     {
    3706             :         {"lc_ctype", PGC_INTERNAL, CLIENT_CONN_LOCALE,
    3707             :             gettext_noop("Shows the character classification and case conversion locale."),
    3708             :             NULL,
    3709             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    3710             :         },
    3711             :         &locale_ctype,
    3712             :         "C",
    3713             :         NULL, NULL, NULL
    3714             :     },
    3715             : 
    3716             :     {
    3717             :         {"lc_messages", PGC_SUSET, CLIENT_CONN_LOCALE,
    3718             :             gettext_noop("Sets the language in which messages are displayed."),
    3719             :             NULL
    3720             :         },
    3721             :         &locale_messages,
    3722             :         "",
    3723             :         check_locale_messages, assign_locale_messages, NULL
    3724             :     },
    3725             : 
    3726             :     {
    3727             :         {"lc_monetary", PGC_USERSET, CLIENT_CONN_LOCALE,
    3728             :             gettext_noop("Sets the locale for formatting monetary amounts."),
    3729             :             NULL
    3730             :         },
    3731             :         &locale_monetary,
    3732             :         "C",
    3733             :         check_locale_monetary, assign_locale_monetary, NULL
    3734             :     },
    3735             : 
    3736             :     {
    3737             :         {"lc_numeric", PGC_USERSET, CLIENT_CONN_LOCALE,
    3738             :             gettext_noop("Sets the locale for formatting numbers."),
    3739             :             NULL
    3740             :         },
    3741             :         &locale_numeric,
    3742             :         "C",
    3743             :         check_locale_numeric, assign_locale_numeric, NULL
    3744             :     },
    3745             : 
    3746             :     {
    3747             :         {"lc_time", PGC_USERSET, CLIENT_CONN_LOCALE,
    3748             :             gettext_noop("Sets the locale for formatting date and time values."),
    3749             :             NULL
    3750             :         },
    3751             :         &locale_time,
    3752             :         "C",
    3753             :         check_locale_time, assign_locale_time, NULL
    3754             :     },
    3755             : 
    3756             :     {
    3757             :         {"session_preload_libraries", PGC_SUSET, CLIENT_CONN_PRELOAD,
    3758             :             gettext_noop("Lists shared libraries to preload into each backend."),
    3759             :             NULL,
    3760             :             GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
    3761             :         },
    3762             :         &session_preload_libraries_string,
    3763             :         "",
    3764             :         NULL, NULL, NULL
    3765             :     },
    3766             : 
    3767             :     {
    3768             :         {"shared_preload_libraries", PGC_POSTMASTER, CLIENT_CONN_PRELOAD,
    3769             :             gettext_noop("Lists shared libraries to preload into server."),
    3770             :             NULL,
    3771             :             GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
    3772             :         },
    3773             :         &shared_preload_libraries_string,
    3774             :         "",
    3775             :         NULL, NULL, NULL
    3776             :     },
    3777             : 
    3778             :     {
    3779             :         {"local_preload_libraries", PGC_USERSET, CLIENT_CONN_PRELOAD,
    3780             :             gettext_noop("Lists unprivileged shared libraries to preload into each backend."),
    3781             :             NULL,
    3782             :             GUC_LIST_INPUT | GUC_LIST_QUOTE
    3783             :         },
    3784             :         &local_preload_libraries_string,
    3785             :         "",
    3786             :         NULL, NULL, NULL
    3787             :     },
    3788             : 
    3789             :     {
    3790             :         {"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT,
    3791             :             gettext_noop("Sets the schema search order for names that are not schema-qualified."),
    3792             :             NULL,
    3793             :             GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_EXPLAIN
    3794             :         },
    3795             :         &namespace_search_path,
    3796             :         "\"$user\", public",
    3797             :         check_search_path, assign_search_path, NULL
    3798             :     },
    3799             : 
    3800             :     {
    3801             :         /* Can't be set in postgresql.conf */
    3802             :         {"server_encoding", PGC_INTERNAL, CLIENT_CONN_LOCALE,
    3803             :             gettext_noop("Sets the server (database) character set encoding."),
    3804             :             NULL,
    3805             :             GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    3806             :         },
    3807             :         &server_encoding_string,
    3808             :         "SQL_ASCII",
    3809             :         NULL, NULL, NULL
    3810             :     },
    3811             : 
    3812             :     {
    3813             :         /* Can't be set in postgresql.conf */
    3814             :         {"server_version", PGC_INTERNAL, PRESET_OPTIONS,
    3815             :             gettext_noop("Shows the server version."),
    3816             :             NULL,
    3817             :             GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    3818             :         },
    3819             :         &server_version_string,
    3820             :         PG_VERSION,
    3821             :         NULL, NULL, NULL
    3822             :     },
    3823             : 
    3824             :     {
    3825             :         /* Not for general use --- used by SET ROLE */
    3826             :         {"role", PGC_USERSET, UNGROUPED,
    3827             :             gettext_noop("Sets the current role."),
    3828             :             NULL,
    3829             :             GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
    3830             :         },
    3831             :         &role_string,
    3832             :         "none",
    3833             :         check_role, assign_role, show_role
    3834             :     },
    3835             : 
    3836             :     {
    3837             :         /* Not for general use --- used by SET SESSION AUTHORIZATION */
    3838             :         {"session_authorization", PGC_USERSET, UNGROUPED,
    3839             :             gettext_noop("Sets the session user name."),
    3840             :             NULL,
    3841             :             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
    3842             :         },
    3843             :         &session_authorization_string,
    3844             :         NULL,
    3845             :         check_session_authorization, assign_session_authorization, NULL
    3846             :     },
    3847             : 
    3848             :     {
    3849             :         {"log_destination", PGC_SIGHUP, LOGGING_WHERE,
    3850             :             gettext_noop("Sets the destination for server log output."),
    3851             :             gettext_noop("Valid values are combinations of \"stderr\", "
    3852             :                          "\"syslog\", \"csvlog\", and \"eventlog\", "
    3853             :                          "depending on the platform."),
    3854             :             GUC_LIST_INPUT
    3855             :         },
    3856             :         &Log_destination_string,
    3857             :         "stderr",
    3858             :         check_log_destination, assign_log_destination, NULL
    3859             :     },
    3860             :     {
    3861             :         {"log_directory", PGC_SIGHUP, LOGGING_WHERE,
    3862             :             gettext_noop("Sets the destination directory for log files."),
    3863             :             gettext_noop("Can be specified as relative to the data directory "
    3864             :                          "or as absolute path."),
    3865             :             GUC_SUPERUSER_ONLY
    3866             :         },
    3867             :         &Log_directory,
    3868             :         "log",
    3869             :         check_canonical_path, NULL, NULL
    3870             :     },
    3871             :     {
    3872             :         {"log_filename", PGC_SIGHUP, LOGGING_WHERE,
    3873             :             gettext_noop("Sets the file name pattern for log files."),
    3874             :             NULL,
    3875             :             GUC_SUPERUSER_ONLY
    3876             :         },
    3877             :         &Log_filename,
    3878             :         "postgresql-%Y-%m-%d_%H%M%S.log",
    3879             :         NULL, NULL, NULL
    3880             :     },
    3881             : 
    3882             :     {
    3883             :         {"syslog_ident", PGC_SIGHUP, LOGGING_WHERE,
    3884             :             gettext_noop("Sets the program name used to identify PostgreSQL "
    3885             :                          "messages in syslog."),
    3886             :             NULL
    3887             :         },
    3888             :         &syslog_ident_str,
    3889             :         "postgres",
    3890             :         NULL, assign_syslog_ident, NULL
    3891             :     },
    3892             : 
    3893             :     {
    3894             :         {"event_source", PGC_POSTMASTER, LOGGING_WHERE,
    3895             :             gettext_noop("Sets the application name used to identify "
    3896             :                          "PostgreSQL messages in the event log."),
    3897             :             NULL
    3898             :         },
    3899             :         &event_source,
    3900             :         DEFAULT_EVENT_SOURCE,
    3901             :         NULL, NULL, NULL
    3902             :     },
    3903             : 
    3904             :     {
    3905             :         {"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
    3906             :             gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
    3907             :             NULL,
    3908             :             GUC_REPORT
    3909             :         },
    3910             :         &timezone_string,
    3911             :         "GMT",
    3912             :         check_timezone, assign_timezone, show_timezone
    3913             :     },
    3914             :     {
    3915             :         {"timezone_abbreviations", PGC_USERSET, CLIENT_CONN_LOCALE,
    3916             :             gettext_noop("Selects a file of time zone abbreviations."),
    3917             :             NULL
    3918             :         },
    3919             :         &timezone_abbreviations_string,
    3920             :         NULL,
    3921             :         check_timezone_abbreviations, assign_timezone_abbreviations, NULL
    3922             :     },
    3923             : 
    3924             :     {
    3925             :         {"unix_socket_group", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    3926             :             gettext_noop("Sets the owning group of the Unix-domain socket."),
    3927             :             gettext_noop("The owning user of the socket is always the user "
    3928             :                          "that starts the server.")
    3929             :         },
    3930             :         &Unix_socket_group,
    3931             :         "",
    3932             :         NULL, NULL, NULL
    3933             :     },
    3934             : 
    3935             :     {
    3936             :         {"unix_socket_directories", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    3937             :             gettext_noop("Sets the directories where Unix-domain sockets will be created."),
    3938             :             NULL,
    3939             :             GUC_SUPERUSER_ONLY
    3940             :         },
    3941             :         &Unix_socket_directories,
    3942             : #ifdef HAVE_UNIX_SOCKETS
    3943             :         DEFAULT_PGSOCKET_DIR,
    3944             : #else
    3945             :         "",
    3946             : #endif
    3947             :         NULL, NULL, NULL
    3948             :     },
    3949             : 
    3950             :     {
    3951             :         {"listen_addresses", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
    3952             :             gettext_noop("Sets the host name or IP address(es) to listen to."),
    3953             :             NULL,
    3954             :             GUC_LIST_INPUT
    3955             :         },
    3956             :         &ListenAddresses,
    3957             :         "localhost",
    3958             :         NULL, NULL, NULL
    3959             :     },
    3960             : 
    3961             :     {
    3962             :         /*
    3963             :          * Can't be set by ALTER SYSTEM as it can lead to recursive definition
    3964             :          * of data_directory.
    3965             :          */
    3966             :         {"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
    3967             :             gettext_noop("Sets the server's data directory."),
    3968             :             NULL,
    3969             :             GUC_SUPERUSER_ONLY | GUC_DISALLOW_IN_AUTO_FILE
    3970             :         },
    3971             :         &data_directory,
    3972             :         NULL,
    3973             :         NULL, NULL, NULL
    3974             :     },
    3975             : 
    3976             :     {
    3977             :         {"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
    3978             :             gettext_noop("Sets the server's main configuration file."),
    3979             :             NULL,
    3980             :             GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
    3981             :         },
    3982             :         &ConfigFileName,
    3983             :         NULL,
    3984             :         NULL, NULL, NULL
    3985             :     },
    3986             : 
    3987             :     {
    3988             :         {"hba_file", PGC_POSTMASTER, FILE_LOCATIONS,
    3989             :             gettext_noop("Sets the server's \"hba\" configuration file."),
    3990             :             NULL,
    3991             :             GUC_SUPERUSER_ONLY
    3992             :         },
    3993             :         &HbaFileName,
    3994             :         NULL,
    3995             :         NULL, NULL, NULL
    3996             :     },
    3997             : 
    3998             :     {
    3999             :         {"ident_file", PGC_POSTMASTER, FILE_LOCATIONS,
    4000             :             gettext_noop("Sets the server's \"ident\" configuration file."),
    4001             :             NULL,
    4002             :             GUC_SUPERUSER_ONLY
    4003             :         },
    4004             :         &IdentFileName,
    4005             :         NULL,
    4006             :         NULL, NULL, NULL
    4007             :     },
    4008             : 
    4009             :     {
    4010             :         {"external_pid_file", PGC_POSTMASTER, FILE_LOCATIONS,
    4011             :             gettext_noop("Writes the postmaster PID to the specified file."),
    4012             :             NULL,
    4013             :             GUC_SUPERUSER_ONLY
    4014             :         },
    4015             :         &external_pid_file,
    4016             :         NULL,
    4017             :         check_canonical_path, NULL, NULL
    4018             :     },
    4019             : 
    4020             :     {
    4021             :         {"ssl_library", PGC_INTERNAL, PRESET_OPTIONS,
    4022             :             gettext_noop("Name of the SSL library."),
    4023             :             NULL,
    4024             :             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    4025             :         },
    4026             :         &ssl_library,
    4027             : #ifdef USE_SSL
    4028             :         "OpenSSL",
    4029             : #else
    4030             :         "",
    4031             : #endif
    4032             :         NULL, NULL, NULL
    4033             :     },
    4034             : 
    4035             :     {
    4036             :         {"ssl_cert_file", PGC_SIGHUP, CONN_AUTH_SSL,
    4037             :             gettext_noop("Location of the SSL server certificate file."),
    4038             :             NULL
    4039             :         },
    4040             :         &ssl_cert_file,
    4041             :         "server.crt",
    4042             :         NULL, NULL, NULL
    4043             :     },
    4044             : 
    4045             :     {
    4046             :         {"ssl_key_file", PGC_SIGHUP, CONN_AUTH_SSL,
    4047             :             gettext_noop("Location of the SSL server private key file."),
    4048             :             NULL
    4049             :         },
    4050             :         &ssl_key_file,
    4051             :         "server.key",
    4052             :         NULL, NULL, NULL
    4053             :     },
    4054             : 
    4055             :     {
    4056             :         {"ssl_ca_file", PGC_SIGHUP, CONN_AUTH_SSL,
    4057             :             gettext_noop("Location of the SSL certificate authority file."),
    4058             :             NULL
    4059             :         },
    4060             :         &ssl_ca_file,
    4061             :         "",
    4062             :         NULL, NULL, NULL
    4063             :     },
    4064             : 
    4065             :     {
    4066             :         {"ssl_crl_file", PGC_SIGHUP, CONN_AUTH_SSL,
    4067             :             gettext_noop("Location of the SSL certificate revocation list file."),
    4068             :             NULL
    4069             :         },
    4070             :         &ssl_crl_file,
    4071             :         "",
    4072             :         NULL, NULL, NULL
    4073             :     },
    4074             : 
    4075             :     {
    4076             :         {"stats_temp_directory", PGC_SIGHUP, STATS_COLLECTOR,
    4077             :             gettext_noop("Writes temporary statistics files to the specified directory."),
    4078             :             NULL,
    4079             :             GUC_SUPERUSER_ONLY
    4080             :         },
    4081             :         &pgstat_temp_directory,
    4082             :         PG_STAT_TMP_DIR,
    4083             :         check_canonical_path, assign_pgstat_temp_directory, NULL
    4084             :     },
    4085             : 
    4086             :     {
    4087             :         {"synchronous_standby_names", PGC_SIGHUP, REPLICATION_MASTER,
    4088             :             gettext_noop("Number of synchronous standbys and list of names of potential synchronous ones."),
    4089             :             NULL,
    4090             :             GUC_LIST_INPUT
    4091             :         },
    4092             :         &SyncRepStandbyNames,
    4093             :         "",
    4094             :         check_synchronous_standby_names, assign_synchronous_standby_names, NULL
    4095             :     },
    4096             : 
    4097             :     {
    4098             :         {"default_text_search_config", PGC_USERSET, CLIENT_CONN_LOCALE,
    4099             :             gettext_noop("Sets default text search configuration."),
    4100             :             NULL
    4101             :         },
    4102             :         &TSCurrentConfig,
    4103             :         "pg_catalog.simple",
    4104             :         check_TSCurrentConfig, assign_TSCurrentConfig, NULL
    4105             :     },
    4106             : 
    4107             :     {
    4108             :         {"ssl_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
    4109             :             gettext_noop("Sets the list of allowed SSL ciphers."),
    4110             :             NULL,
    4111             :             GUC_SUPERUSER_ONLY
    4112             :         },
    4113             :         &SSLCipherSuites,
    4114             : #ifdef USE_OPENSSL
    4115             :         "HIGH:MEDIUM:+3DES:!aNULL",
    4116             : #else
    4117             :         "none",
    4118             : #endif
    4119             :         NULL, NULL, NULL
    4120             :     },
    4121             : 
    4122             :     {
    4123             :         {"ssl_ecdh_curve", PGC_SIGHUP, CONN_AUTH_SSL,
    4124             :             gettext_noop("Sets the curve to use for ECDH."),
    4125             :             NULL,
    4126             :             GUC_SUPERUSER_ONLY
    4127             :         },
    4128             :         &SSLECDHCurve,
    4129             : #ifdef USE_SSL
    4130             :         "prime256v1",
    4131             : #else
    4132             :         "none",
    4133             : #endif
    4134             :         NULL, NULL, NULL
    4135             :     },
    4136             : 
    4137             :     {
    4138             :         {"ssl_dh_params_file", PGC_SIGHUP, CONN_AUTH_SSL,
    4139             :             gettext_noop("Location of the SSL DH parameters file."),
    4140             :             NULL,
    4141             :             GUC_SUPERUSER_ONLY
    4142             :         },
    4143             :         &ssl_dh_params_file,
    4144             :         "",
    4145             :         NULL, NULL, NULL
    4146             :     },
    4147             : 
    4148             :     {
    4149             :         {"ssl_passphrase_command", PGC_SIGHUP, CONN_AUTH_SSL,
    4150             :             gettext_noop("Command to obtain passphrases for SSL."),
    4151             :             NULL
    4152             :         },
    4153             :         &ssl_passphrase_command,
    4154             :         "",
    4155             :         NULL, NULL, NULL
    4156             :     },
    4157             : 
    4158             :     {
    4159             :         {"application_name", PGC_USERSET, LOGGING_WHAT,
    4160             :             gettext_noop("Sets the application name to be reported in statistics and logs."),
    4161             :             NULL,
    4162             :             GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE
    4163             :         },
    4164             :         &application_name,
    4165             :         "",
    4166             :         check_application_name, assign_application_name, NULL
    4167             :     },
    4168             : 
    4169             :     {
    4170             :         {"cluster_name", PGC_POSTMASTER, PROCESS_TITLE,
    4171             :             gettext_noop("Sets the name of the cluster, which is included in the process title."),
    4172             :             NULL,
    4173             :             GUC_IS_NAME
    4174             :         },
    4175             :         &cluster_name,
    4176             :         "",
    4177             :         check_cluster_name, NULL, NULL
    4178             :     },
    4179             : 
    4180             :     {
    4181             :         {"wal_consistency_checking", PGC_SUSET, DEVELOPER_OPTIONS,
    4182             :             gettext_noop("Sets the WAL resource managers for which WAL consistency checks are done."),
    4183             :             gettext_noop("Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay."),
    4184             :             GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE
    4185             :         },
    4186             :         &wal_consistency_checking_string,
    4187             :         "",
    4188             :         check_wal_consistency_checking, assign_wal_consistency_checking, NULL
    4189             :     },
    4190             : 
    4191             :     {
    4192             :         {"jit_provider", PGC_POSTMASTER, CLIENT_CONN_PRELOAD,
    4193             :             gettext_noop("JIT provider to use."),
    4194             :             NULL,
    4195             :             GUC_SUPERUSER_ONLY
    4196             :         },
    4197             :         &jit_provider,
    4198             :         "llvmjit",
    4199             :         NULL, NULL, NULL
    4200             :     },
    4201             : 
    4202             :     /* End-of-list marker */
    4203             :     {
    4204             :         {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
    4205             :     }
    4206             : };
    4207             : 
    4208             : 
    4209             : static struct config_enum ConfigureNamesEnum[] =
    4210             : {
    4211             :     {
    4212             :         {"backslash_quote", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
    4213             :             gettext_noop("Sets whether \"\\'\" is allowed in string literals."),
    4214             :             NULL
    4215             :         },
    4216             :         &backslash_quote,
    4217             :         BACKSLASH_QUOTE_SAFE_ENCODING, backslash_quote_options,
    4218             :         NULL, NULL, NULL
    4219             :     },
    4220             : 
    4221             :     {
    4222             :         {"bytea_output", PGC_USERSET, CLIENT_CONN_STATEMENT,
    4223             :             gettext_noop("Sets the output format for bytea."),
    4224             :             NULL
    4225             :         },
    4226             :         &bytea_output,
    4227             :         BYTEA_OUTPUT_HEX, bytea_output_options,
    4228             :         NULL, NULL, NULL
    4229             :     },
    4230             : 
    4231             :     {
    4232             :         {"client_min_messages", PGC_USERSET, CLIENT_CONN_STATEMENT,
    4233             :             gettext_noop("Sets the message levels that are sent to the client."),
    4234             :             gettext_noop("Each level includes all the levels that follow it. The later"
    4235             :                          " the level, the fewer messages are sent.")
    4236             :         },
    4237             :         &client_min_messages,
    4238             :         NOTICE, client_message_level_options,
    4239             :         NULL, NULL, NULL
    4240             :     },
    4241             : 
    4242             :     {
    4243             :         {"constraint_exclusion", PGC_USERSET, QUERY_TUNING_OTHER,
    4244             :             gettext_noop("Enables the planner to use constraints to optimize queries."),
    4245             :             gettext_noop("Table scans will be skipped if their constraints"
    4246             :                          " guarantee that no rows match the query."),
    4247             :             GUC_EXPLAIN
    4248             :         },
    4249             :         &constraint_exclusion,
    4250             :         CONSTRAINT_EXCLUSION_PARTITION, constraint_exclusion_options,
    4251             :         NULL, NULL, NULL
    4252             :     },
    4253             : 
    4254             :     {
    4255             :         {"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
    4256             :             gettext_noop("Sets the transaction isolation level of each new transaction."),
    4257             :             NULL
    4258             :         },
    4259             :         &DefaultXactIsoLevel,
    4260             :         XACT_READ_COMMITTED, isolation_level_options,
    4261             :         NULL, NULL, NULL
    4262             :     },
    4263             : 
    4264             :     {
    4265             :         {"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
    4266             :             gettext_noop("Sets the current transaction's isolation level."),
    4267             :             NULL,
    4268             :             GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
    4269             :         },
    4270             :         &XactIsoLevel,
    4271             :         XACT_READ_COMMITTED, isolation_level_options,
    4272             :         check_XactIsoLevel, NULL, NULL
    4273             :     },
    4274             : 
    4275             :     {
    4276             :         {"IntervalStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
    4277             :             gettext_noop("Sets the display format for interval values."),
    4278             :             NULL,
    4279             :             GUC_REPORT
    4280             :         },
    4281             :         &IntervalStyle,
    4282             :         INTSTYLE_POSTGRES, intervalstyle_options,
    4283             :         NULL, NULL, NULL
    4284             :     },
    4285             : 
    4286             :     {
    4287             :         {"log_error_verbosity", PGC_SUSET, LOGGING_WHAT,
    4288             :             gettext_noop("Sets the verbosity of logged messages."),
    4289             :             NULL
    4290             :         },
    4291             :         &Log_error_verbosity,
    4292             :         PGERROR_DEFAULT, log_error_verbosity_options,
    4293             :         NULL, NULL, NULL
    4294             :     },
    4295             : 
    4296             :     {
    4297             :         {"log_min_messages", PGC_SUSET, LOGGING_WHEN,
    4298             :             gettext_noop("Sets the message levels that are logged."),
    4299             :             gettext_noop("Each level includes all the levels that follow it. The later"
    4300             :                          " the level, the fewer messages are sent.")
    4301             :         },
    4302             :         &log_min_messages,
    4303             :         WARNING, server_message_level_options,
    4304             :         NULL, NULL, NULL
    4305             :     },
    4306             : 
    4307             :     {
    4308             :         {"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
    4309             :             gettext_noop("Causes all statements generating error at or above this level to be logged."),
    4310             :             gettext_noop("Each level includes all the levels that follow it. The later"
    4311             :                          " the level, the fewer messages are sent.")
    4312             :         },
    4313             :         &log_min_error_statement,
    4314             :         ERROR, server_message_level_options,
    4315             :         NULL, NULL, NULL
    4316             :     },
    4317             : 
    4318             :     {
    4319             :         {"log_statement", PGC_SUSET, LOGGING_WHAT,
    4320             :             gettext_noop("Sets the type of statements logged."),
    4321             :             NULL
    4322             :         },
    4323             :         &log_statement,
    4324             :         LOGSTMT_NONE, log_statement_options,
    4325             :         NULL, NULL, NULL
    4326             :     },
    4327             : 
    4328             :     {
    4329             :         {"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
    4330             :             gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
    4331             :             NULL
    4332             :         },
    4333             :         &syslog_facility,
    4334             : #ifdef HAVE_SYSLOG
    4335             :         LOG_LOCAL0,
    4336             : #else
    4337             :         0,
    4338             : #endif
    4339             :         syslog_facility_options,
    4340             :         NULL, assign_syslog_facility, NULL
    4341             :     },
    4342             : 
    4343             :     {
    4344             :         {"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
    4345             :             gettext_noop("Sets the session's behavior for triggers and rewrite rules."),
    4346             :             NULL
    4347             :         },
    4348             :         &SessionReplicationRole,
    4349             :         SESSION_REPLICATION_ROLE_ORIGIN, session_replication_role_options,
    4350             :         NULL, assign_session_replication_role, NULL
    4351             :     },
    4352             : 
    4353             :     {
    4354             :         {"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
    4355             :             gettext_noop("Sets the current transaction's synchronization level."),
    4356             :             NULL
    4357             :         },
    4358             :         &synchronous_commit,
    4359             :         SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
    4360             :         NULL, assign_synchronous_commit, NULL
    4361             :     },
    4362             : 
    4363             :     {
    4364             :         {"archive_mode", PGC_POSTMASTER, WAL_ARCHIVING,
    4365             :             gettext_noop("Allows archiving of WAL files using archive_command."),
    4366             :             NULL
    4367             :         },
    4368             :         &XLogArchiveMode,
    4369             :         ARCHIVE_MODE_OFF, archive_mode_options,
    4370             :         NULL, NULL, NULL
    4371             :     },
    4372             : 
    4373             :     {
    4374             :         {"recovery_target_action", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
    4375             :             gettext_noop("Sets the action to perform upon reaching the recovery target."),
    4376             :             NULL
    4377             :         },
    4378             :         &recoveryTargetAction,
    4379             :         RECOVERY_TARGET_ACTION_PAUSE, recovery_target_action_options,
    4380             :         NULL, NULL, NULL
    4381             :     },
    4382             : 
    4383             :     {
    4384             :         {"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS,
    4385             :             gettext_noop("Enables logging of recovery-related debugging information."),
    4386             :             gettext_noop("Each level includes all the levels that follow it. The later"
    4387             :                          " the level, the fewer messages are sent.")
    4388             :         },
    4389             :         &trace_recovery_messages,
    4390             : 
    4391             :         /*
    4392             :          * client_message_level_options allows too many values, really, but
    4393             :          * it's not worth having a separate options array for this.
    4394             :          */
    4395             :         LOG, client_message_level_options,
    4396             :         NULL, NULL, NULL
    4397             :     },
    4398             : 
    4399             :     {
    4400             :         {"track_functions", PGC_SUSET, STATS_COLLECTOR,
    4401             :             gettext_noop("Collects function-level statistics on database activity."),
    4402             :             NULL
    4403             :         },
    4404             :         &pgstat_track_functions,
    4405             :         TRACK_FUNC_OFF, track_function_options,
    4406             :         NULL, NULL, NULL
    4407             :     },
    4408             : 
    4409             :     {
    4410             :         {"wal_level", PGC_POSTMASTER, WAL_SETTINGS,
    4411             :             gettext_noop("Set the level of information written to the WAL."),
    4412             :             NULL
    4413             :         },
    4414             :         &wal_level,
    4415             :         WAL_LEVEL_REPLICA, wal_level_options,
    4416             :         NULL, NULL, NULL
    4417             :     },
    4418             : 
    4419             :     {
    4420             :         {"dynamic_shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
    4421             :             gettext_noop("Selects the dynamic shared memory implementation used."),
    4422             :             NULL
    4423             :         },
    4424             :         &dynamic_shared_memory_type,
    4425             :         DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE, dynamic_shared_memory_options,
    4426             :         NULL, NULL, NULL
    4427             :     },
    4428             : 
    4429             :     {
    4430             :         {"shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
    4431             :             gettext_noop("Selects the shared memory implementation used for the main shared memory region."),
    4432             :             NULL
    4433             :         },
    4434             :         &shared_memory_type,
    4435             :         DEFAULT_SHARED_MEMORY_TYPE, shared_memory_options,
    4436             :         NULL, NULL, NULL
    4437             :     },
    4438             : 
    4439             :     {
    4440             :         {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
    4441             :             gettext_noop("Selects the method used for forcing WAL updates to disk."),
    4442             :             NULL
    4443             :         },
    4444             :         &sync_method,
    4445             :         DEFAULT_SYNC_METHOD, sync_method_options,
    4446             :         NULL, assign_xlog_sync_method, NULL
    4447             :     },
    4448             : 
    4449             :     {
    4450             :         {"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
    4451             :             gettext_noop("Sets how binary values are to be encoded in XML."),
    4452             :             NULL
    4453             :         },
    4454             :         &xmlbinary,
    4455             :         XMLBINARY_BASE64, xmlbinary_options,
    4456             :         NULL, NULL, NULL
    4457             :     },
    4458             : 
    4459             :     {
    4460             :         {"xmloption", PGC_USERSET, CLIENT_CONN_STATEMENT,
    4461             :             gettext_noop("Sets whether XML data in implicit parsing and serialization "
    4462             :                          "operations is to be considered as documents or content fragments."),
    4463             :             NULL
    4464             :         },
    4465             :         &xmloption,
    4466             :         XMLOPTION_CONTENT, xmloption_options,
    4467             :         NULL, NULL, NULL
    4468             :     },
    4469             : 
    4470             :     {
    4471             :         {"huge_pages", PGC_POSTMASTER, RESOURCES_MEM,
    4472             :             gettext_noop("Use of huge pages on Linux or Windows."),
    4473             :             NULL
    4474             :         },
    4475             :         &huge_pages,
    4476             :         HUGE_PAGES_TRY, huge_pages_options,
    4477             :         NULL, NULL, NULL
    4478             :     },
    4479             : 
    4480             :     {
    4481             :         {"force_parallel_mode", PGC_USERSET, QUERY_TUNING_OTHER,
    4482             :             gettext_noop("Forces use of parallel query facilities."),
    4483             :             gettext_noop("If possible, run query using a parallel worker and with parallel restrictions."),
    4484             :             GUC_EXPLAIN
    4485             :         },
    4486             :         &force_parallel_mode,
    4487             :         FORCE_PARALLEL_OFF, force_parallel_mode_options,
    4488             :         NULL, NULL, NULL
    4489             :     },
    4490             : 
    4491             :     {
    4492             :         {"password_encryption", PGC_USERSET, CONN_AUTH_AUTH,
    4493             :             gettext_noop("Encrypt passwords."),
    4494             :             gettext_noop("When a password is specified in CREATE USER or "
    4495             :                          "ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
    4496             :                          "this parameter determines whether the password is to be encrypted.")
    4497             :         },
    4498             :         &Password_encryption,
    4499             :         PASSWORD_TYPE_MD5, password_encryption_options,
    4500             :         NULL, NULL, NULL
    4501             :     },
    4502             : 
    4503             :     {
    4504             :         {"plan_cache_mode", PGC_USERSET, QUERY_TUNING_OTHER,
    4505             :             gettext_noop("Controls the planner's selection of custom or generic plan."),
    4506             :             gettext_noop("Prepared statements can have custom and generic plans, and the planner "
    4507             :                          "will attempt to choose which is better.  This can be set to override "
    4508             :                          "the default behavior."),
    4509             :             GUC_EXPLAIN
    4510             :         },
    4511             :         &plan_cache_mode,
    4512             :         PLAN_CACHE_MODE_AUTO, plan_cache_mode_options,
    4513             :         NULL, NULL, NULL
    4514             :     },
    4515             : 
    4516             :     {
    4517             :         {"ssl_min_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
    4518             :             gettext_noop("Sets the minimum SSL/TLS protocol version to use."),
    4519             :             NULL,
    4520             :             GUC_SUPERUSER_ONLY
    4521             :         },
    4522             :         &ssl_min_protocol_version,
    4523             :         PG_TLS1_VERSION,
    4524             :         ssl_protocol_versions_info + 1, /* don't allow PG_TLS_ANY */
    4525             :         NULL, NULL, NULL
    4526             :     },
    4527             : 
    4528             :     {
    4529             :         {"ssl_max_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
    4530             :             gettext_noop("Sets the maximum SSL/TLS protocol version to use."),
    4531             :             NULL,
    4532             :             GUC_SUPERUSER_ONLY
    4533             :         },
    4534             :         &ssl_max_protocol_version,
    4535             :         PG_TLS_ANY,
    4536             :         ssl_protocol_versions_info,
    4537             :         NULL, NULL, NULL
    4538             :     },
    4539             : 
    4540             :     /* End-of-list marker */
    4541             :     {
    4542             :         {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
    4543             :     }
    4544             : };
    4545             : 
    4546             : /******** end of options list ********/
    4547             : 
    4548             : 
    4549             : /*
    4550             :  * To allow continued support of obsolete names for GUC variables, we apply
    4551             :  * the following mappings to any unrecognized name.  Note that an old name
    4552             :  * should be mapped to a new one only if the new variable has very similar
    4553             :  * semantics to the old.
    4554             :  */
    4555             : static const char *const map_old_guc_names[] = {
    4556             :     "sort_mem", "work_mem",
    4557             :     "vacuum_mem", "maintenance_work_mem",
    4558             :     NULL
    4559             : };
    4560             : 
    4561             : 
    4562             : /*
    4563             :  * Actual lookup of variables is done through this single, sorted array.
    4564             :  */
    4565             : static struct config_generic **guc_variables;
    4566             : 
    4567             : /* Current number of variables contained in the vector */
    4568             : static int  num_guc_variables;
    4569             : 
    4570             : /* Current number of variables marked with GUC_EXPLAIN */
    4571             : static int  num_guc_explain_variables;
    4572             : 
    4573             : /* Vector capacity */
    4574             : static int  size_guc_variables;
    4575             : 
    4576             : 
    4577             : static bool guc_dirty;          /* true if need to do commit/abort work */
    4578             : 
    4579             : static bool reporting_enabled;  /* true to enable GUC_REPORT */
    4580             : 
    4581             : static int  GUCNestLevel = 0;   /* 1 when in main transaction */
    4582             : 
    4583             : 
    4584             : static int  guc_var_compare(const void *a, const void *b);
    4585             : static int  guc_name_compare(const char *namea, const char *nameb);
    4586             : static void InitializeGUCOptionsFromEnvironment(void);
    4587             : static void InitializeOneGUCOption(struct config_generic *gconf);
    4588             : static void push_old_value(struct config_generic *gconf, GucAction action);
    4589             : static void ReportGUCOption(struct config_generic *record);
    4590             : static void reapply_stacked_values(struct config_generic *variable,
    4591             :                                    struct config_string *pHolder,
    4592             :                                    GucStack *stack,
    4593             :                                    const char *curvalue,
    4594             :                                    GucContext curscontext, GucSource cursource);
    4595             : static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
    4596             : static void ShowAllGUCConfig(DestReceiver *dest);
    4597             : static char *_ShowOption(struct config_generic *record, bool use_units);
    4598             : static bool validate_option_array_item(const char *name, const char *value,
    4599             :                                        bool skipIfNoPermissions);
    4600             : static void write_auto_conf_file(int fd, const char *filename, ConfigVariable *head_p);
    4601             : static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
    4602             :                                       const char *name, const char *value);
    4603             : 
    4604             : 
    4605             : /*
    4606             :  * Some infrastructure for checking malloc/strdup/realloc calls
    4607             :  */
    4608             : static void *
    4609       65868 : guc_malloc(int elevel, size_t size)
    4610             : {
    4611             :     void       *data;
    4612             : 
    4613             :     /* Avoid unportable behavior of malloc(0) */
    4614       65868 :     if (size == 0)
    4615           0 :         size = 1;
    4616       65868 :     data = malloc(size);
    4617       65868 :     if (data == NULL)
    4618           0 :         ereport(elevel,
    4619             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    4620             :                  errmsg("out of memory")));
    4621       65868 :     return data;
    4622             : }
    4623             : 
    4624             : static void *
    4625           0 : guc_realloc(int elevel, void *old, size_t size)
    4626             : {
    4627             :     void       *data;
    4628             : 
    4629             :     /* Avoid unportable behavior of realloc(NULL, 0) */
    4630           0 :     if (old == NULL && size == 0)
    4631           0 :         size = 1;
    4632           0 :     data = realloc(old, size);
    4633           0 :     if (data == NULL)
    4634           0 :         ereport(elevel,
    4635             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    4636             :                  errmsg("out of memory")));
    4637           0 :     return data;
    4638             : }
    4639             : 
    4640             : static char *
    4641      360784 : guc_strdup(int elevel, const char *src)
    4642             : {
    4643             :     char       *data;
    4644             : 
    4645      360784 :     data = strdup(src);
    4646      360784 :     if (data == NULL)
    4647           0 :         ereport(elevel,
    4648             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    4649             :                  errmsg("out of memory")));
    4650      360784 :     return data;
    4651             : }
    4652             : 
    4653             : 
    4654             : /*
    4655             :  * Detect whether strval is referenced anywhere in a GUC string item
    4656             :  */
    4657             : static bool
    4658      366024 : string_field_used(struct config_string *conf, char *strval)
    4659             : {
    4660             :     GucStack   *stack;
    4661             : 
    4662      592586 :     if (strval == *(conf->variable) ||
    4663      341148 :         strval == conf->reset_val ||
    4664      114586 :         strval == conf->boot_val)
    4665      251438 :         return true;
    4666      122890 :     for (stack = conf->gen.stack; stack; stack = stack->prev)
    4667             :     {
    4668       19632 :         if (strval == stack->prior.val.stringval ||
    4669        8308 :             strval == stack->masked.val.stringval)
    4670        3020 :             return true;
    4671             :     }
    4672      111566 :     return false;
    4673             : }
    4674             : 
    4675             : /*
    4676             :  * Support for assigning to a field of a string GUC item.  Free the prior
    4677             :  * value if it's not referenced anywhere else in the item (including stacked
    4678             :  * states).
    4679             :  */
    4680             : static void
    4681      289490 : set_string_field(struct config_string *conf, char **field, char *newval)
    4682             : {
    4683      289490 :     char       *oldval = *field;
    4684             : 
    4685             :     /* Do the assignment */
    4686      289490 :     *field = newval;
    4687             : 
    4688             :     /* Free old value if it's not NULL and isn't referenced anymore */
    4689      289490 :     if (oldval && !string_field_used(conf, oldval))
    4690      110022 :         free(oldval);
    4691      289490 : }
    4692             : 
    4693             : /*
    4694             :  * Detect whether an "extra" struct is referenced anywhere in a GUC item
    4695             :  */
    4696             : static bool
    4697      136214 : extra_field_used(struct config_generic *gconf, void *extra)
    4698             : {
    4699             :     GucStack   *stack;
    4700             : 
    4701      136214 :     if (extra == gconf->extra)
    4702       57514 :         return true;
    4703       78700 :     switch (gconf->vartype)
    4704             :     {
    4705             :         case PGC_BOOL:
    4706           0 :             if (extra == ((struct config_bool *) gconf)->reset_extra)
    4707           0 :                 return true;
    4708           0 :             break;
    4709             :         case PGC_INT:
    4710         792 :             if (extra == ((struct config_int *) gconf)->reset_extra)
    4711         788 :                 return true;
    4712           4 :             break;
    4713             :         case PGC_REAL:
    4714           0 :             if (extra == ((struct config_real *) gconf)->reset_extra)
    4715           0 :                 return true;
    4716           0 :             break;
    4717             :         case PGC_STRING:
    4718       77908 :             if (extra == ((struct config_string *) gconf)->reset_extra)
    4719       38004 :                 return true;
    4720       39904 :             break;
    4721             :         case PGC_ENUM:
    4722           0 :             if (extra == ((struct config_enum *) gconf)->reset_extra)
    4723           0 :                 return true;
    4724           0 :             break;
    4725             :     }
    4726       46384 :     for (stack = gconf->stack; stack; stack = stack->prev)
    4727             :     {
    4728       14606 :         if (extra == stack->prior.extra ||
    4729        6480 :             extra == stack->masked.extra)
    4730        1650 :             return true;
    4731             :     }
    4732             : 
    4733       38258 :     return false;
    4734             : }
    4735             : 
    4736             : /*
    4737             :  * Support for assigning to an "extra" field of a GUC item.  Free the prior
    4738             :  * value if it's not referenced anywhere else in the item (including stacked
    4739             :  * states).
    4740             :  */
    4741             : static void
    4742      593268 : set_extra_field(struct config_generic *gconf, void **field, void *newval)
    4743             : {
    4744      593268 :     void       *oldval = *field;
    4745             : 
    4746             :     /* Do the assignment */
    4747      593268 :     *field = newval;
    4748             : 
    4749             :     /* Free old value if it's not NULL and isn't referenced anymore */
    4750      593268 :     if (oldval && !extra_field_used(gconf, oldval))
    4751       37348 :         free(oldval);
    4752      593268 : }
    4753             : 
    4754             : /*
    4755             :  * Support for copying a variable's active value into a stack entry.
    4756             :  * The "extra" field associated with the active value is copied, too.
    4757             :  *
    4758             :  * NB: be sure stringval and extra fields of a new stack entry are
    4759             :  * initialized to NULL before this is used, else we'll try to free() them.
    4760             :  */
    4761             : static void
    4762       46404 : set_stack_value(struct config_generic *gconf, config_var_value *val)
    4763             : {
    4764       46404 :     switch (gconf->vartype)
    4765             :     {
    4766             :         case PGC_BOOL:
    4767        8734 :             val->val.boolval =
    4768        8734 :                 *((struct config_bool *) gconf)->variable;
    4769        8734 :             break;
    4770             :         case PGC_INT:
    4771       11294 :             val->val.intval =
    4772       11294 :                 *((struct config_int *) gconf)->variable;
    4773       11294 :             break;
    4774             :         case PGC_REAL:
    4775        3216 :             val->val.realval =
    4776        3216 :                 *((struct config_real *) gconf)->variable;
    4777        3216 :             break;
    4778             :         case PGC_STRING:
    4779       10828 :             set_string_field((struct config_string *) gconf,
    4780             :                              &(val->val.stringval),
    4781       10828 :                              *((struct config_string *) gconf)->variable);
    4782       10828 :             break;
    4783             :         case PGC_ENUM:
    4784       12332 :             val->val.enumval =
    4785       12332 :                 *((struct config_enum *) gconf)->variable;
    4786       12332 :             break;
    4787             :     }
    4788       46404 :     set_extra_field(gconf, &(val->extra), gconf->extra);
    4789       46404 : }
    4790             : 
    4791             : /*
    4792             :  * Support for discarding a no-longer-needed value in a stack entry.
    4793             :  * The "extra" field associated with the stack entry is cleared, too.
    4794             :  */
    4795             : static void
    4796       23358 : discard_stack_value(struct config_generic *gconf, config_var_value *val)
    4797             : {
    4798       23358 :     switch (gconf->vartype)
    4799             :     {
    4800             :         case PGC_BOOL:
    4801             :         case PGC_INT:
    4802             :         case PGC_REAL:
    4803             :         case PGC_ENUM:
    4804             :             /* no need to do anything */
    4805       18314 :             break;
    4806             :         case PGC_STRING:
    4807        5044 :             set_string_field((struct config_string *) gconf,
    4808             :                              &(val->val.stringval),
    4809             :                              NULL);
    4810        5044 :             break;
    4811             :     }
    4812       23358 :     set_extra_field(gconf, &(val->extra), NULL);
    4813       23358 : }
    4814             : 
    4815             : 
    4816             : /*
    4817             :  * Fetch the sorted array pointer (exported for help_config.c's use ONLY)
    4818             :  */
    4819             : struct config_generic **
    4820           0 : get_guc_variables(void)
    4821             : {
    4822           0 :     return guc_variables;
    4823             : }
    4824             : 
    4825             : 
    4826             : /*
    4827             :  * Build the sorted array.  This is split out so that it could be
    4828             :  * re-executed after startup (e.g., we could allow loadable modules to
    4829             :  * add vars, and then we'd need to re-sort).
    4830             :  */
    4831             : void
    4832        1862 : build_guc_variables(void)
    4833             : {
    4834             :     int         size_vars;
    4835        1862 :     int         num_vars = 0;
    4836        1862 :     int         num_explain_vars = 0;
    4837             :     struct config_generic **guc_vars;
    4838             :     int         i;
    4839             : 
    4840      175028 :     for (i = 0; ConfigureNamesBool[i].gen.name; i++)
    4841             :     {
    4842      173166 :         struct config_bool *conf = &ConfigureNamesBool[i];
    4843             : 
    4844             :         /* Rather than requiring vartype to be filled in by hand, do this: */
    4845      173166 :         conf->gen.vartype = PGC_BOOL;
    4846      173166 :         num_vars++;
    4847             : 
    4848      173166 :         if (conf->gen.flags & GUC_EXPLAIN)
    4849       37240 :             num_explain_vars++;
    4850             :     }
    4851             : 
    4852      201096 :     for (i = 0; ConfigureNamesInt[i].gen.name; i++)
    4853             :     {
    4854      199234 :         struct config_int *conf = &ConfigureNamesInt[i];
    4855             : 
    4856      199234 :         conf->gen.vartype = PGC_INT;
    4857      199234 :         num_vars++;
    4858             : 
    4859      199234 :         if (conf->gen.flags & GUC_EXPLAIN)
    4860       26068 :             num_explain_vars++;
    4861             :     }
    4862             : 
    4863       42826 :     for (i = 0; ConfigureNamesReal[i].gen.name; i++)
    4864             :     {
    4865       40964 :         struct config_real *conf = &ConfigureNamesReal[i];
    4866             : 
    4867       40964 :         conf->gen.vartype = PGC_REAL;
    4868       40964 :         num_vars++;
    4869             : 
    4870       40964 :         if (conf->gen.flags & GUC_EXPLAIN)
    4871       24206 :             num_explain_vars++;
    4872             :     }
    4873             : 
    4874      128478 :     for (i = 0; ConfigureNamesString[i].gen.name; i++)
    4875             :     {
    4876      126616 :         struct config_string *conf = &ConfigureNamesString[i];
    4877             : 
    4878      126616 :         conf->gen.vartype = PGC_STRING;
    4879      126616 :         num_vars++;
    4880             : 
    4881      126616 :         if (conf->gen.flags & GUC_EXPLAIN)
    4882        1862 :             num_explain_vars++;
    4883             :     }
    4884             : 
    4885       57722 :     for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
    4886             :     {
    4887       55860 :         struct config_enum *conf = &ConfigureNamesEnum[i];
    4888             : 
    4889       55860 :         conf->gen.vartype = PGC_ENUM;
    4890       55860 :         num_vars++;
    4891             : 
    4892       55860 :         if (conf->gen.flags & GUC_EXPLAIN)
    4893        5586 :             num_explain_vars++;
    4894             :     }
    4895             : 
    4896             :     /*
    4897             :      * Create table with 20% slack
    4898             :      */
    4899        1862 :     size_vars = num_vars + num_vars / 4;
    4900             : 
    4901        1862 :     guc_vars = (struct config_generic **)
    4902        1862 :         guc_malloc(FATAL, size_vars * sizeof(struct config_generic *));
    4903             : 
    4904        1862 :     num_vars = 0;
    4905             : 
    4906      175028 :     for (i = 0; ConfigureNamesBool[i].gen.name; i++)
    4907      173166 :         guc_vars[num_vars++] = &ConfigureNamesBool[i].gen;
    4908             : 
    4909      201096 :     for (i = 0; ConfigureNamesInt[i].gen.name; i++)
    4910      199234 :         guc_vars[num_vars++] = &ConfigureNamesInt[i].gen;
    4911             : 
    4912       42826 :     for (i = 0; ConfigureNamesReal[i].gen.name; i++)
    4913       40964 :         guc_vars[num_vars++] = &ConfigureNamesReal[i].gen;
    4914             : 
    4915      128478 :     for (i = 0; ConfigureNamesString[i].gen.name; i++)
    4916      126616 :         guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
    4917             : 
    4918       57722 :     for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
    4919       55860 :         guc_vars[num_vars++] = &ConfigureNamesEnum[i].gen;
    4920             : 
    4921        1862 :     if (guc_variables)
    4922           0 :         free(guc_variables);
    4923        1862 :     guc_variables = guc_vars;
    4924        1862 :     num_guc_variables = num_vars;
    4925        1862 :     num_guc_explain_variables = num_explain_vars;
    4926        1862 :     size_guc_variables = size_vars;
    4927        1862 :     qsort((void *) guc_variables, num_guc_variables,
    4928             :           sizeof(struct config_generic *), guc_var_compare);
    4929        1862 : }
    4930             : 
    4931             : /*
    4932             :  * Add a new GUC variable to the list of known variables. The
    4933             :  * list is expanded if needed.
    4934             :  */
    4935             : static bool
    4936       10972 : add_guc_variable(struct config_generic *var, int elevel)
    4937             : {
    4938       10972 :     if (num_guc_variables + 1 >= size_guc_variables)
    4939             :     {
    4940             :         /*
    4941             :          * Increase the vector by 25%
    4942             :          */
    4943           0 :         int         size_vars = size_guc_variables + size_guc_variables / 4;
    4944             :         struct config_generic **guc_vars;
    4945             : 
    4946           0 :         if (size_vars == 0)
    4947             :         {
    4948           0 :             size_vars = 100;
    4949           0 :             guc_vars = (struct config_generic **)
    4950           0 :                 guc_malloc(elevel, size_vars * sizeof(struct config_generic *));
    4951             :         }
    4952             :         else
    4953             :         {
    4954           0 :             guc_vars = (struct config_generic **)
    4955           0 :                 guc_realloc(elevel, guc_variables, size_vars * sizeof(struct config_generic *));
    4956             :         }
    4957             : 
    4958           0 :         if (guc_vars == NULL)
    4959           0 :             return false;       /* out of memory */
    4960             : 
    4961           0 :         guc_variables = guc_vars;
    4962           0 :         size_guc_variables = size_vars;
    4963             :     }
    4964       10972 :     guc_variables[num_guc_variables++] = var;
    4965       10972 :     qsort((void *) guc_variables, num_guc_variables,
    4966             :           sizeof(struct config_generic *), guc_var_compare);
    4967       10972 :     return true;
    4968             : }
    4969             : 
    4970             : /*
    4971             :  * Create and add a placeholder variable for a custom variable name.
    4972             :  */
    4973             : static struct config_generic *
    4974          18 : add_placeholder_variable(const char *name, int elevel)
    4975             : {
    4976          18 :     size_t      sz = sizeof(struct config_string) + sizeof(char *);
    4977             :     struct config_string *var;
    4978             :     struct config_generic *gen;
    4979             : 
    4980          18 :     var = (struct config_string *) guc_malloc(elevel, sz);
    4981          18 :     if (var == NULL)
    4982           0 :         return NULL;
    4983          18 :     memset(var, 0, sz);
    4984          18 :     gen = &var->gen;
    4985             : 
    4986          18 :     gen->name = guc_strdup(elevel, name);
    4987          18 :     if (gen->name == NULL)
    4988             :     {
    4989           0 :         free(var);
    4990           0 :         return NULL;
    4991             :     }
    4992             : 
    4993          18 :     gen->context = PGC_USERSET;
    4994          18 :     gen->group = CUSTOM_OPTIONS;
    4995          18 :     gen->short_desc = "GUC placeholder variable";
    4996          18 :     gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER;
    4997          18 :     gen->vartype = PGC_STRING;
    4998             : 
    4999             :     /*
    5000             :      * The char* is allocated at the end of the struct since we have no
    5001             :      * 'static' place to point to.  Note that the current value, as well as
    5002             :      * the boot and reset values, start out NULL.
    5003             :      */
    5004          18 :     var->variable = (char **) (var + 1);
    5005             : 
    5006          18 :     if (!add_guc_variable((struct config_generic *) var, elevel))
    5007             :     {
    5008           0 :         free(unconstify(char *, gen->name));
    5009           0 :         free(var);
    5010           0 :         return NULL;
    5011             :     }
    5012             : 
    5013          18 :     return gen;
    5014             : }
    5015             : 
    5016             : /*
    5017             :  * Look up option NAME.  If it exists, return a pointer to its record,
    5018             :  * else return NULL.  If create_placeholders is true, we'll create a
    5019             :  * placeholder record for a valid-looking custom variable name.
    5020             :  */
    5021             : static struct config_generic *
    5022      363880 : find_option(const char *name, bool create_placeholders, int elevel)
    5023             : {
    5024      363880 :     const char **key = &name;
    5025             :     struct config_generic **res;
    5026             :     int         i;
    5027             : 
    5028             :     Assert(name);
    5029             : 
    5030             :     /*
    5031             :      * By equating const char ** with struct config_generic *, we are assuming
    5032             :      * the name field is first in config_generic.
    5033             :      */
    5034      363880 :     res = (struct config_generic **) bsearch((void *) &key,
    5035             :                                              (void *) guc_variables,
    5036             :                                              num_guc_variables,
    5037             :                                              sizeof(struct config_generic *),
    5038             :                                              guc_var_compare);
    5039      363880 :     if (res)
    5040      363836 :         return *res;
    5041             : 
    5042             :     /*
    5043             :      * See if the name is an obsolete name for a variable.  We assume that the
    5044             :      * set of supported old names is short enough that a brute-force search is
    5045             :      * the best way.
    5046             :      */
    5047         132 :     for (i = 0; map_old_guc_names[i] != NULL; i += 2)
    5048             :     {
    5049          88 :         if (guc_name_compare(name, map_old_guc_names[i]) == 0)
    5050           0 :             return find_option(map_old_guc_names[i + 1], false, elevel);
    5051             :     }
    5052             : 
    5053          44 :     if (create_placeholders)
    5054             :     {
    5055             :         /*
    5056             :          * Check if the name is qualified, and if so, add a placeholder.
    5057             :          */
    5058          18 :         if (strchr(name, GUC_QUALIFIER_SEPARATOR) != NULL)
    5059          18 :             return add_placeholder_variable(name, elevel);
    5060             :     }
    5061             : 
    5062             :     /* Unknown name */
    5063          26 :     return NULL;
    5064             : }
    5065             : 
    5066             : 
    5067             : /*
    5068             :  * comparator for qsorting and bsearching guc_variables array
    5069             :  */
    5070             : static int
    5071    51915226 : guc_var_compare(const void *a, const void *b)
    5072             : {
    5073    51915226 :     const struct config_generic *confa = *(struct config_generic *const *) a;
    5074    51915226 :     const struct config_generic *confb = *(struct config_generic *const *) b;
    5075             : 
    5076    51915226 :     return guc_name_compare(confa->name, confb->name);
    5077             : }
    5078             : 
    5079             : /*
    5080             :  * the bare comparison function for GUC names
    5081             :  */
    5082             : static int
    5083    52099364 : guc_name_compare(const char *namea, const char *nameb)
    5084             : {
    5085             :     /*
    5086             :      * The temptation to use strcasecmp() here must be resisted, because the
    5087             :      * array ordering has to remain stable across setlocale() calls. So, build
    5088             :      * our own with a simple ASCII-only downcasing.
    5089             :      */
    5090   277084880 :     while (*namea && *nameb)
    5091             :     {
    5092   223382408 :         char        cha = *namea++;
    5093   223382408 :         char        chb = *nameb++;
    5094             : 
    5095   223382408 :         if (cha >= 'A' && cha <= 'Z')
    5096      796986 :             cha += 'a' - 'A';
    5097   223382408 :         if (chb >= 'A' && chb <= 'Z')
    5098      414712 :             chb += 'a' - 'A';
    5099   223382408 :         if (cha != chb)
    5100    50496256 :             return cha - chb;
    5101             :     }
    5102     1603108 :     if (*namea)
    5103      128242 :         return 1;               /* a is longer */
    5104     1474866 :     if (*nameb)
    5105     1110952 :         return -1;              /* b is longer */
    5106      363914 :     return 0;
    5107             : }
    5108             : 
    5109             : 
    5110             : /*
    5111             :  * Initialize GUC options during program startup.
    5112             :  *
    5113             :  * Note that we cannot read the config file yet, since we have not yet
    5114             :  * processed command-line switches.
    5115             :  */
    5116             : void
    5117        1862 : InitializeGUCOptions(void)
    5118             : {
    5119             :     int         i;
    5120             : 
    5121             :     /*
    5122             :      * Before log_line_prefix could possibly receive a nonempty setting, make
    5123             :      * sure that timezone processing is minimally alive (see elog.c).
    5124             :      */
    5125        1862 :     pg_timezone_initialize();
    5126             : 
    5127             :     /*
    5128             :      * Build sorted array of all GUC variables.
    5129             :      */
    5130        1862 :     build_guc_variables();
    5131             : 
    5132             :     /*
    5133             :      * Load all variables with their compiled-in defaults, and initialize
    5134             :      * status fields as needed.
    5135             :      */
    5136      597702 :     for (i = 0; i < num_guc_variables; i++)
    5137             :     {
    5138      595840 :         InitializeOneGUCOption(guc_variables[i]);
    5139             :     }
    5140             : 
    5141        1862 :     guc_dirty = false;
    5142             : 
    5143        1862 :     reporting_enabled = false;
    5144             : 
    5145             :     /*
    5146             :      * Prevent any attempt to override the transaction modes from
    5147             :      * non-interactive sources.
    5148             :      */
    5149        1862 :     SetConfigOption("transaction_isolation", "read committed",
    5150             :                     PGC_POSTMASTER, PGC_S_OVERRIDE);
    5151        1862 :     SetConfigOption("transaction_read_only", "no",
    5152             :                     PGC_POSTMASTER, PGC_S_OVERRIDE);
    5153        1862 :     SetConfigOption("transaction_deferrable", "no",
    5154             :                     PGC_POSTMASTER, PGC_S_OVERRIDE);
    5155             : 
    5156             :     /*
    5157             :      * For historical reasons, some GUC parameters can receive defaults from
    5158             :      * environment variables.  Process those settings.
    5159             :      */
    5160        1862 :     InitializeGUCOptionsFromEnvironment();
    5161        1862 : }
    5162             : 
    5163             : /*
    5164             :  * Assign any GUC values that can come from the server's environment.
    5165             :  *
    5166             :  * This is called from InitializeGUCOptions, and also from ProcessConfigFile
    5167             :  * to deal with the possibility that a setting has been removed from
    5168             :  * postgresql.conf and should now get a value from the environment.
    5169             :  * (The latter is a kludge that should probably go away someday; if so,
    5170             :  * fold this back into InitializeGUCOptions.)
    5171             :  */
    5172             : static void
    5173        2046 : InitializeGUCOptionsFromEnvironment(void)
    5174             : {
    5175             :     char       *env;
    5176             :     long        stack_rlimit;
    5177             : 
    5178        2046 :     env = getenv("PGPORT");
    5179        2046 :     if (env != NULL)
    5180         714 :         SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
    5181             : 
    5182        2046 :     env = getenv("PGDATESTYLE");
    5183        2046 :     if (env != NULL)
    5184         658 :         SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
    5185             : 
    5186        2046 :     env = getenv("PGCLIENTENCODING");
    5187        2046 :     if (env != NULL)
    5188          42 :         SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
    5189             : 
    5190             :     /*
    5191             :      * rlimit isn't exactly an "environment variable", but it behaves about
    5192             :      * the same.  If we can identify the platform stack depth rlimit, increase
    5193             :      * default stack depth setting up to whatever is safe (but at most 2MB).
    5194             :      */
    5195        2046 :     stack_rlimit = get_stack_depth_rlimit();
    5196        2046 :     if (stack_rlimit > 0)
    5197             :     {
    5198        2046 :         long        new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;
    5199             : 
    5200        2046 :         if (new_limit > 100)
    5201             :         {
    5202             :             char        limbuf[16];
    5203             : 
    5204        2046 :             new_limit = Min(new_limit, 2048);
    5205        2046 :             sprintf(limbuf, "%ld", new_limit);
    5206        2046 :             SetConfigOption("max_stack_depth", limbuf,
    5207             :                             PGC_POSTMASTER, PGC_S_ENV_VAR);
    5208             :         }
    5209             :     }
    5210        2046 : }
    5211             : 
    5212             : /*
    5213             :  * Initialize one GUC option variable to its compiled-in default.
    5214             :  *
    5215             :  * Note: the reason for calling check_hooks is not that we think the boot_val
    5216             :  * might fail, but that the hooks might wish to compute an "extra" struct.
    5217             :  */
    5218             : static void
    5219      642408 : InitializeOneGUCOption(struct config_generic *gconf)
    5220             : {
    5221      642408 :     gconf->status = 0;
    5222      642408 :     gconf->source = PGC_S_DEFAULT;
    5223      642408 :     gconf->reset_source = PGC_S_DEFAULT;
    5224      642408 :     gconf->scontext = PGC_INTERNAL;
    5225      642408 :     gconf->reset_scontext = PGC_INTERNAL;
    5226      642408 :     gconf->stack = NULL;
    5227      642408 :     gconf->extra = NULL;
    5228      642408 :     gconf->sourcefile = NULL;
    5229      642408 :     gconf->sourceline = 0;
    5230             : 
    5231      642408 :     switch (gconf->vartype)
    5232             :     {
    5233             :         case PGC_BOOL:
    5234             :             {
    5235      183996 :                 struct config_bool *conf = (struct config_bool *) gconf;
    5236      183996 :                 bool        newval = conf->boot_val;
    5237      183996 :                 void       *extra = NULL;
    5238             : 
    5239      183996 :                 if (!call_bool_check_hook(conf, &newval, &extra,
    5240             :                                           PGC_S_DEFAULT, LOG))
    5241           0 :                     elog(FATAL, "failed to initialize %s to %d",
    5242             :                          conf->gen.name, (int) newval);
    5243      183996 :                 if (conf->assign_hook)
    5244           0 :                     conf->assign_hook(newval, extra);
    5245      183996 :                 *conf->variable = conf->reset_val = newval;
    5246      183996 :                 conf->gen.extra = conf->reset_extra = extra;
    5247      183996 :                 break;
    5248             :             }
    5249             :         case PGC_INT:
    5250             :             {
    5251      206524 :                 struct config_int *conf = (struct config_int *) gconf;
    5252      206524 :                 int         newval = conf->boot_val;
    5253      206524 :                 void       *extra = NULL;
    5254             : 
    5255             :                 Assert(newval >= conf->min);
    5256             :                 Assert(newval <= conf->max);
    5257      206524 :                 if (!call_int_check_hook(conf, &newval, &extra,
    5258             :                                          PGC_S_DEFAULT, LOG))
    5259           0 :                     elog(FATAL, "failed to initialize %s to %d",
    5260             :                          conf->gen.name, newval);
    5261      206524 :                 if (conf->assign_hook)
    5262       16266 :                     conf->assign_hook(newval, extra);
    5263      206524 :                 *conf->variable = conf->reset_val = newval;
    5264      206524 :                 conf->gen.extra = conf->reset_extra = extra;
    5265      206524 :                 break;
    5266             :             }
    5267             :         case PGC_REAL:
    5268             :             {
    5269       40982 :                 struct config_real *conf = (struct config_real *) gconf;
    5270       40982 :                 double      newval = conf->boot_val;
    5271       40982 :                 void       *extra = NULL;
    5272             : 
    5273             :                 Assert(newval >= conf->min);
    5274             :                 Assert(newval <= conf->max);
    5275       40982 :                 if (!call_real_check_hook(conf, &newval, &extra,
    5276             :                                           PGC_S_DEFAULT, LOG))
    5277           0 :                     elog(FATAL, "failed to initialize %s to %g",
    5278             :                          conf->gen.name, newval);
    5279       40982 :                 if (conf->assign_hook)
    5280        1862 :                     conf->assign_hook(newval, extra);
    5281       40982 :                 *conf->variable = conf->reset_val = newval;
    5282       40982 :                 conf->gen.extra = conf->reset_extra = extra;
    5283       40982 :                 break;
    5284             :             }
    5285             :         case PGC_STRING:
    5286             :             {
    5287      149664 :                 struct config_string *conf = (struct config_string *) gconf;
    5288             :                 char       *newval;
    5289      149664 :                 void       *extra = NULL;
    5290             : 
    5291             :                 /* non-NULL boot_val must always get strdup'd */
    5292      149664 :                 if (conf->boot_val != NULL)
    5293      133248 :                     newval = guc_strdup(FATAL, conf->boot_val);
    5294             :                 else
    5295       16416 :                     newval = NULL;
    5296             : 
    5297      149664 :                 if (!call_string_check_hook(conf, &newval, &extra,
    5298             :                                             PGC_S_DEFAULT, LOG))
    5299           0 :                     elog(FATAL, "failed to initialize %s to \"%s\"",
    5300             :                          conf->gen.name, newval ? newval : "");
    5301      149664 :                 if (conf->assign_hook)
    5302       70486 :                     conf->assign_hook(newval, extra);
    5303      149664 :                 *conf->variable = conf->reset_val = newval;
    5304      149664 :                 conf->gen.extra = conf->reset_extra = extra;
    5305      149664 :                 break;
    5306             :             }
    5307             :         case PGC_ENUM:
    5308             :             {
    5309       61242 :                 struct config_enum *conf = (struct config_enum *) gconf;
    5310       61242 :                 int         newval = conf->boot_val;
    5311       61242 :                 void       *extra = NULL;
    5312             : 
    5313       61242 :                 if (!call_enum_check_hook(conf, &newval, &extra,
    5314             :                                           PGC_S_DEFAULT, LOG))
    5315           0 :                     elog(FATAL, "failed to initialize %s to %d",
    5316             :                          conf->gen.name, newval);
    5317       61242 :                 if (conf->assign_hook)
    5318        7448 :                     conf->assign_hook(newval, extra);
    5319       61242 :                 *conf->variable = conf->reset_val = newval;
    5320       61242 :                 conf->gen.extra = conf->reset_extra = extra;
    5321       61242 :                 break;
    5322             :             }
    5323             :     }
    5324      642408 : }
    5325             : 
    5326             : 
    5327             : /*
    5328             :  * Select the configuration files and data directory to be used, and
    5329             :  * do the initial read of postgresql.conf.
    5330             :  *
    5331             :  * This is called after processing command-line switches.
    5332             :  *      userDoption is the -D switch value if any (NULL if unspecified).
    5333             :  *      progname is just for use in error messages.
    5334             :  *
    5335             :  * Returns true on success; on failure, prints a suitable error message
    5336             :  * to stderr and returns false.
    5337             :  */
    5338             : bool
    5339        1862 : SelectConfigFiles(const char *userDoption, const char *progname)
    5340             : {
    5341             :     char       *configdir;
    5342             :     char       *fname;
    5343             :     struct stat stat_buf;
    5344             : 
    5345             :     /* configdir is -D option, or $PGDATA if no -D */
    5346        1862 :     if (userDoption)
    5347         578 :         configdir = make_absolute_path(userDoption);
    5348             :     else
    5349        1284 :         configdir = make_absolute_path(getenv("PGDATA"));
    5350             : 
    5351        1862 :     if (configdir && stat(configdir, &stat_buf) != 0)
    5352             :     {
    5353           0 :         write_stderr("%s: could not access directory \"%s\": %s\n",
    5354             :                      progname,
    5355             :                      configdir,
    5356           0 :                      strerror(errno));
    5357           0 :         if (errno == ENOENT)
    5358           0 :             write_stderr("Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n");
    5359           0 :         return false;
    5360             :     }
    5361             : 
    5362             :     /*
    5363             :      * Find the configuration file: if config_file was specified on the
    5364             :      * command line, use it, else use configdir/postgresql.conf.  In any case
    5365             :      * ensure the result is an absolute path, so that it will be interpreted
    5366             :      * the same way by future backends.
    5367             :      */
    5368        1862 :     if (ConfigFileName)
    5369           0 :         fname = make_absolute_path(ConfigFileName);
    5370        1862 :     else if (configdir)
    5371             :     {
    5372        1862 :         fname = guc_malloc(FATAL,
    5373        1862 :                            strlen(configdir) + strlen(CONFIG_FILENAME) + 2);
    5374        1862 :         sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);
    5375             :     }
    5376             :     else
    5377             :     {
    5378           0 :         write_stderr("%s does not know where to find the server configuration file.\n"
    5379             :                      "You must specify the --config-file or -D invocation "
    5380             :                      "option or set the PGDATA environment variable.\n",
    5381             :                      progname);
    5382           0 :         return false;
    5383             :     }
    5384             : 
    5385             :     /*
    5386             :      * Set the ConfigFileName GUC variable to its final value, ensuring that
    5387             :      * it can't be overridden later.
    5388             :      */
    5389        1862 :     SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
    5390        1862 :     free(fname);
    5391             : 
    5392             :     /*
    5393             :      * Now read the config file for the first time.
    5394             :      */
    5395        1862 :     if (stat(ConfigFileName, &stat_buf) != 0)
    5396             :     {
    5397           0 :         write_stderr("%s: could not access the server configuration file \"%s\": %s\n",
    5398           0 :                      progname, ConfigFileName, strerror(errno));
    5399           0 :         free(configdir);
    5400           0 :         return false;
    5401             :     }
    5402             : 
    5403             :     /*
    5404             :      * Read the configuration file for the first time.  This time only the
    5405             :      * data_directory parameter is picked up to determine the data directory,
    5406             :      * so that we can read the PG_AUTOCONF_FILENAME file next time.
    5407             :      */
    5408        1862 :     ProcessConfigFile(PGC_POSTMASTER);
    5409             : 
    5410             :     /*
    5411             :      * If the data_directory GUC variable has been set, use that as DataDir;
    5412             :      * otherwise use configdir if set; else punt.
    5413             :      *
    5414             :      * Note: SetDataDir will copy and absolute-ize its argument, so we don't
    5415             :      * have to.
    5416             :      */
    5417        1862 :     if (data_directory)
    5418           0 :         SetDataDir(data_directory);
    5419        1862 :     else if (configdir)
    5420        1862 :         SetDataDir(configdir);
    5421             :     else
    5422             :     {
    5423           0 :         write_stderr("%s does not know where to find the database system data.\n"
    5424             :                      "This can be specified as \"data_directory\" in \"%s\", "
    5425             :                      "or by the -D invocation option, or by the "
    5426             :                      "PGDATA environment variable.\n",
    5427             :                      progname, ConfigFileName);
    5428           0 :         return false;
    5429             :     }
    5430             : 
    5431             :     /*
    5432             :      * Reflect the final DataDir value back into the data_directory GUC var.
    5433             :      * (If you are wondering why we don't just make them a single variable,
    5434             :      * it's because the EXEC_BACKEND case needs DataDir to be transmitted to
    5435             :      * child backends specially.  XXX is that still true?  Given that we now
    5436             :      * chdir to DataDir, EXEC_BACKEND can read the config file without knowing
    5437             :      * DataDir in advance.)
    5438             :      */
    5439        1862 :     SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
    5440             : 
    5441             :     /*
    5442             :      * Now read the config file a second time, allowing any settings in the
    5443             :      * PG_AUTOCONF_FILENAME file to take effect.  (This is pretty ugly, but
    5444             :      * since we have to determine the DataDir before we can find the autoconf
    5445             :      * file, the alternatives seem worse.)
    5446             :      */
    5447        1862 :     ProcessConfigFile(PGC_POSTMASTER);
    5448             : 
    5449             :     /*
    5450             :      * If timezone_abbreviations wasn't set in the configuration file, install
    5451             :      * the default value.  We do it this way because we can't safely install a
    5452             :      * "real" value until my_exec_path is set, which may not have happened
    5453             :      * when InitializeGUCOptions runs, so the bootstrap default value cannot
    5454             :      * be the real desired default.
    5455             :      */
    5456        1860 :     pg_timezone_abbrev_initialize();
    5457             : 
    5458             :     /*
    5459             :      * Figure out where pg_hba.conf is, and make sure the path is absolute.
    5460             :      */
    5461        1860 :     if (HbaFileName)
    5462           0 :         fname = make_absolute_path(HbaFileName);
    5463        1860 :     else if (configdir)
    5464             :     {
    5465        1860 :         fname = guc_malloc(FATAL,
    5466        1860 :                            strlen(configdir) + strlen(HBA_FILENAME) + 2);
    5467        1860 :         sprintf(fname, "%s/%s", configdir, HBA_FILENAME);
    5468             :     }
    5469             :     else
    5470             :     {
    5471           0 :         write_stderr("%s does not know where to find the \"hba\" configuration file.\n"
    5472             :                      "This can be specified as \"hba_file\" in \"%s\", "
    5473             :                      "or by the -D invocation option, or by the "
    5474             :                      "PGDATA environment variable.\n",
    5475             :                      progname, ConfigFileName);
    5476           0 :         return false;
    5477             :     }
    5478        1860 :     SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
    5479        1860 :     free(fname);
    5480             : 
    5481             :     /*
    5482             :      * Likewise for pg_ident.conf.
    5483             :      */
    5484        1860 :     if (IdentFileName)
    5485           0 :         fname = make_absolute_path(IdentFileName);
    5486        1860 :     else if (configdir)
    5487             :     {
    5488        1860 :         fname = guc_malloc(FATAL,
    5489        1860 :                            strlen(configdir) + strlen(IDENT_FILENAME) + 2);
    5490        1860 :         sprintf(fname, "%s/%s", configdir, IDENT_FILENAME);
    5491             :     }
    5492             :     else
    5493             :     {
    5494           0 :         write_stderr("%s does not know where to find the \"ident\" configuration file.\n"
    5495             :                      "This can be specified as \"ident_file\" in \"%s\", "
    5496             :                      "or by the -D invocation option, or by the "
    5497             :                      "PGDATA environment variable.\n",
    5498             :                      progname, ConfigFileName);
    5499           0 :         return false;
    5500             :     }
    5501        1860 :     SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
    5502        1860 :     free(fname);
    5503             : 
    5504        1860 :     free(configdir);
    5505             : 
    5506        1860 :     return true;
    5507             : }
    5508             : 
    5509             : 
    5510             : /*
    5511             :  * Reset all options to their saved default values (implements RESET ALL)
    5512             :  */
    5513             : void
    5514           4 : ResetAllOptions(void)
    5515             : {
    5516             :     int         i;
    5517             : 
    5518        1284 :     for (i = 0; i < num_guc_variables; i++)
    5519             :     {
    5520        1280 :         struct config_generic *gconf = guc_variables[i];
    5521             : 
    5522             :         /* Don't reset non-SET-able values */
    5523        2420 :         if (gconf->context != PGC_SUSET &&
    5524        1140 :             gconf->context != PGC_USERSET)
    5525         632 :             continue;
    5526             :         /* Don't reset if special exclusion from RESET ALL */
    5527         648 :         if (gconf->flags & GUC_NO_RESET_ALL)
    5528          24 :             continue;
    5529             :         /* No need to reset if wasn't SET */
    5530         624 :         if (gconf->source <= PGC_S_OVERRIDE)
    5531         620 :             continue;
    5532             : 
    5533             :         /* Save old value to support transaction abort */
    5534           4 :         push_old_value(gconf, GUC_ACTION_SET);
    5535             : 
    5536           4 :         switch (gconf->vartype)
    5537             :         {
    5538             :             case PGC_BOOL:
    5539             :                 {
    5540           0 :                     struct config_bool *conf = (struct config_bool *) gconf;
    5541             : 
    5542           0 :                     if (conf->assign_hook)
    5543           0 :                         conf->assign_hook(conf->reset_val,
    5544             :                                           conf->reset_extra);
    5545           0 :                     *conf->variable = conf->reset_val;
    5546           0 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    5547             :                                     conf->reset_extra);
    5548           0 :                     break;
    5549             :                 }
    5550             :             case PGC_INT:
    5551             :                 {
    5552           0 :                     struct config_int *conf = (struct config_int *) gconf;
    5553             : 
    5554           0 :                     if (conf->assign_hook)
    5555           0 :                         conf->assign_hook(conf->reset_val,
    5556             :                                           conf->reset_extra);
    5557           0 :                     *conf->variable = conf->reset_val;
    5558           0 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    5559             :                                     conf->reset_extra);
    5560           0 :                     break;
    5561             :                 }
    5562             :             case PGC_REAL:
    5563             :                 {
    5564           4 :                     struct config_real *conf = (struct config_real *) gconf;
    5565             : 
    5566           4 :                     if (conf->assign_hook)
    5567           0 :                         conf->assign_hook(conf->reset_val,
    5568             :                                           conf->reset_extra);
    5569           4 :                     *conf->variable = conf->reset_val;
    5570           4 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    5571             :                                     conf->reset_extra);
    5572           4 :                     break;
    5573             :                 }
    5574             :             case PGC_STRING:
    5575             :                 {
    5576           0 :                     struct config_string *conf = (struct config_string *) gconf;
    5577             : 
    5578           0 :                     if (conf->assign_hook)
    5579           0 :                         conf->assign_hook(conf->reset_val,
    5580             :                                           conf->reset_extra);
    5581           0 :                     set_string_field(conf, conf->variable, conf->reset_val);
    5582           0 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    5583             :                                     conf->reset_extra);
    5584           0 :                     break;
    5585             :                 }
    5586             :             case PGC_ENUM:
    5587             :                 {
    5588           0 :                     struct config_enum *conf = (struct config_enum *) gconf;
    5589             : 
    5590           0 :                     if (conf->assign_hook)
    5591           0 :                         conf->assign_hook(conf->reset_val,
    5592             :                                           conf->reset_extra);
    5593           0 :                     *conf->variable = conf->reset_val;
    5594           0 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    5595             :                                     conf->reset_extra);
    5596           0 :                     break;
    5597             :                 }
    5598             :         }
    5599             : 
    5600           4 :         gconf->source = gconf->reset_source;
    5601           4 :         gconf->scontext = gconf->reset_scontext;
    5602             : 
    5603           4 :         if (gconf->flags & GUC_REPORT)
    5604           0 :             ReportGUCOption(gconf);
    5605             :     }
    5606           4 : }
    5607             : 
    5608             : 
    5609             : /*
    5610             :  * push_old_value
    5611             :  *      Push previous state during transactional assignment to a GUC variable.
    5612             :  */
    5613             : static void
    5614       50592 : push_old_value(struct config_generic *gconf, GucAction action)
    5615             : {
    5616             :     GucStack   *stack;
    5617             : 
    5618             :     /* If we're not inside a nest level, do nothing */
    5619       50592 :     if (GUCNestLevel == 0)
    5620           0 :         return;
    5621             : 
    5622             :     /* Do we already have a stack entry of the current nest level? */
    5623       50592 :     stack = gconf->stack;
    5624       50592 :     if (stack && stack->nest_level >= GUCNestLevel)
    5625             :     {
    5626             :         /* Yes, so adjust its state if necessary */
    5627             :         Assert(stack->nest_level == GUCNestLevel);
    5628        4196 :         switch (action)
    5629             :         {
    5630             :             case GUC_ACTION_SET:
    5631             :                 /* SET overrides any prior action at same nest level */
    5632        4172 :                 if (stack->state == GUC_SET_LOCAL)
    5633             :                 {
    5634             :                     /* must discard old masked value */
    5635           0 :                     discard_stack_value(gconf, &stack->masked);
    5636             :                 }
    5637        4172 :                 stack->state = GUC_SET;
    5638        4172 :                 break;
    5639             :             case GUC_ACTION_LOCAL:
    5640          24 :                 if (stack->state == GUC_SET)
    5641             :                 {
    5642             :                     /* SET followed by SET LOCAL, remember SET's value */
    5643           8 :                     stack->masked_scontext = gconf->scontext;
    5644           8 :                     set_stack_value(gconf, &stack->masked);
    5645           8 :                     stack->state = GUC_SET_LOCAL;
    5646             :                 }
    5647             :                 /* in all other cases, no change to stack entry */
    5648          24 :                 break;
    5649             :             case GUC_ACTION_SAVE:
    5650             :                 /* Could only have a prior SAVE of same variable */
    5651             :                 Assert(stack->state == GUC_SAVE);
    5652           0 :                 break;
    5653             :         }
    5654             :         Assert(guc_dirty);      /* must be set already */
    5655        4196 :         return;
    5656             :     }
    5657             : 
    5658             :     /*
    5659             :      * Push a new stack entry
    5660             :      *
    5661             :      * We keep all the stack entries in TopTransactionContext for simplicity.
    5662             :      */
    5663       46396 :     stack = (GucStack *) MemoryContextAllocZero(TopTransactionContext,
    5664             :                                                 sizeof(GucStack));
    5665             : 
    5666       46396 :     stack->prev = gconf->stack;
    5667       46396 :     stack->nest_level = GUCNestLevel;
    5668       46396 :     switch (action)
    5669             :     {
    5670             :         case GUC_ACTION_SET:
    5671       24506 :             stack->state = GUC_SET;
    5672       24506 :             break;
    5673             :         case GUC_ACTION_LOCAL:
    5674        5634 :             stack->state = GUC_LOCAL;
    5675        5634 :             break;
    5676             :         case GUC_ACTION_SAVE:
    5677       16256 :             stack->state = GUC_SAVE;
    5678       16256 :             break;
    5679             :     }
    5680       46396 :     stack->source = gconf->source;
    5681       46396 :     stack->scontext = gconf->scontext;
    5682       46396 :     set_stack_value(gconf, &stack->prior);
    5683             : 
    5684       46396 :     gconf->stack = stack;
    5685             : 
    5686             :     /* Ensure we remember to pop at end of xact */
    5687       46396 :     guc_dirty = true;
    5688             : }
    5689             : 
    5690             : 
    5691             : /*
    5692             :  * Do GUC processing at main transaction start.
    5693             :  */
    5694             : void
    5695      460102 : AtStart_GUC(void)
    5696             : {
    5697             :     /*
    5698             :      * The nest level should be 0 between transactions; if it isn't, somebody
    5699             :      * didn't call AtEOXact_GUC, or called it with the wrong nestLevel.  We
    5700             :      * throw a warning but make no other effort to clean up.
    5701             :      */
    5702      460102 :     if (GUCNestLevel != 0)
    5703           0 :         elog(WARNING, "GUC nest level = %d at transaction start",
    5704             :              GUCNestLevel);
    5705      460102 :     GUCNestLevel = 1;
    5706      460102 : }
    5707             : 
    5708             : /*
    5709             :  * Enter a new nesting level for GUC values.  This is called at subtransaction
    5710             :  * start, and when entering a function that has proconfig settings, and in
    5711             :  * some other places where we want to set GUC variables transiently.
    5712             :  * NOTE we must not risk error here, else subtransaction start will be unhappy.
    5713             :  */
    5714             : int
    5715      160642 : NewGUCNestLevel(void)
    5716             : {
    5717      160642 :     return ++GUCNestLevel;
    5718             : }
    5719             : 
    5720             : /*
    5721             :  * Do GUC processing at transaction or subtransaction commit or abort, or
    5722             :  * when exiting a function that has proconfig settings, or when undoing a
    5723             :  * transient assignment to some GUC variables.  (The name is thus a bit of
    5724             :  * a misnomer; perhaps it should be ExitGUCNestLevel or some such.)
    5725             :  * During abort, we discard all GUC settings that were applied at nesting
    5726             :  * levels >= nestLevel.  nestLevel == 1 corresponds to the main transaction.
    5727             :  */
    5728             : void
    5729      620538 : AtEOXact_GUC(bool isCommit, int nestLevel)
    5730             : {
    5731             :     bool        still_dirty;
    5732             :     int         i;
    5733             : 
    5734             :     /*
    5735             :      * Note: it's possible to get here with GUCNestLevel == nestLevel-1 during
    5736             :      * abort, if there is a failure during transaction start before
    5737             :      * AtStart_GUC is called.
    5738             :      */
    5739             :     Assert(nestLevel > 0 &&
    5740             :            (nestLevel <= GUCNestLevel ||
    5741             :             (nestLevel == GUCNestLevel + 1 && !isCommit)));
    5742             : 
    5743             :     /* Quick exit if nothing's changed in this transaction */
    5744      620538 :     if (!guc_dirty)
    5745             :     {
    5746      596912 :         GUCNestLevel = nestLevel - 1;
    5747      596912 :         return;
    5748             :     }
    5749             : 
    5750       23626 :     still_dirty = false;
    5751     7632248 :     for (i = 0; i < num_guc_variables; i++)
    5752             :     {
    5753     7608622 :         struct config_generic *gconf = guc_variables[i];
    5754             :         GucStack   *stack;
    5755             : 
    5756             :         /*
    5757             :          * Process and pop each stack entry within the nest level. To simplify
    5758             :          * fmgr_security_definer() and other places that use GUC_ACTION_SAVE,
    5759             :          * we allow failure exit from code that uses a local nest level to be
    5760             :          * recovered at the surrounding transaction or subtransaction abort;
    5761             :          * so there could be more than one stack entry to pop.
    5762             :          */
    5763    15312116 :         while ((stack = gconf->stack) != NULL &&
    5764       48456 :                stack->nest_level >= nestLevel)
    5765             :         {
    5766       46416 :             GucStack   *prev = stack->prev;
    5767       46416 :             bool        restorePrior = false;
    5768       46416 :             bool        restoreMasked = false;
    5769             :             bool        changed;
    5770             : 
    5771             :             /*
    5772             :              * In this next bit, if we don't set either restorePrior or
    5773             :              * restoreMasked, we must "discard" any unwanted fields of the
    5774             :              * stack entries to avoid leaking memory.  If we do set one of
    5775             :              * those flags, unused fields will be cleaned up after restoring.
    5776             :              */
    5777       46416 :             if (!isCommit)      /* if abort, always restore prior value */
    5778        2264 :                 restorePrior = true;
    5779       44152 :             else if (stack->state == GUC_SAVE)
    5780       16176 :                 restorePrior = true;
    5781       27976 :             else if (stack->nest_level == 1)
    5782             :             {
    5783             :                 /* transaction commit */
    5784       27948 :                 if (stack->state == GUC_SET_LOCAL)
    5785           8 :                     restoreMasked = true;
    5786       27940 :                 else if (stack->state == GUC_SET)
    5787             :                 {
    5788             :                     /* we keep the current active value */
    5789       23354 :                     discard_stack_value(gconf, &stack->prior);
    5790             :                 }
    5791             :                 else            /* must be GUC_LOCAL */
    5792        4586 :                     restorePrior = true;
    5793             :             }
    5794          36 :             else if (prev == NULL ||
    5795           8 :                      prev->nest_level < stack->nest_level - 1)
    5796             :             {
    5797             :                 /* decrement entry's level and do not pop it */
    5798          24 :                 stack->nest_level--;
    5799          24 :                 continue;
    5800             :             }
    5801             :             else
    5802             :             {
    5803             :                 /*
    5804             :                  * We have to merge this stack entry into prev. See README for
    5805             :                  * discussion of this bit.
    5806             :                  */
    5807           4 :                 switch (stack->state)
    5808             :                 {
    5809             :                     case GUC_SAVE:
    5810             :                         Assert(false);  /* can't get here */
    5811           0 :                         break;
    5812             : 
    5813             :                     case GUC_SET:
    5814             :                         /* next level always becomes SET */
    5815           4 :                         discard_stack_value(gconf, &stack->prior);
    5816           4 :                         if (prev->state == GUC_SET_LOCAL)
    5817           0 :                             discard_stack_value(gconf, &prev->masked);
    5818           4 :                         prev->state = GUC_SET;
    5819           4 :                         break;
    5820             : 
    5821             :                     case GUC_LOCAL:
    5822           0 :                         if (prev->state == GUC_SET)
    5823             :                         {
    5824             :                             /* LOCAL migrates down */
    5825           0 :                             prev->masked_scontext = stack->scontext;
    5826           0 :                             prev->masked = stack->prior;
    5827           0 :                             prev->state = GUC_SET_LOCAL;
    5828             :                         }
    5829             :                         else
    5830             :                         {
    5831             :                             /* else just forget this stack level */
    5832           0 :                             discard_stack_value(gconf, &stack->prior);
    5833             :                         }
    5834           0 :                         break;
    5835             : 
    5836             :                     case GUC_SET_LOCAL:
    5837             :                         /* prior state at this level no longer wanted */
    5838           0 :                         discard_stack_value(gconf, &stack->prior);
    5839             :                         /* copy down the masked state */
    5840           0 :                         prev->masked_scontext = stack->masked_scontext;
    5841           0 :                         if (prev->state == GUC_SET_LOCAL)
    5842           0 :                             discard_stack_value(gconf, &prev->masked);
    5843           0 :                         prev->masked = stack->masked;
    5844           0 :                         prev->state = GUC_SET_LOCAL;
    5845           0 :                         break;
    5846             :                 }
    5847             :             }
    5848             : 
    5849       46392 :             changed = false;
    5850             : 
    5851       46392 :             if (restorePrior || restoreMasked)
    5852             :             {
    5853             :                 /* Perform appropriate restoration of the stacked value */
    5854             :                 config_var_value newvalue;
    5855             :                 GucSource   newsource;
    5856             :                 GucContext  newscontext;
    5857             : 
    5858       23034 :                 if (restoreMasked)
    5859             :                 {
    5860           8 :                     newvalue = stack->masked;
    5861           8 :                     newsource = PGC_S_SESSION;
    5862           8 :                     newscontext = stack->masked_scontext;
    5863             :                 }
    5864             :                 else
    5865             :                 {
    5866       23026 :                     newvalue = stack->prior;
    5867       23026 :                     newsource = stack->source;
    5868       23026 :                     newscontext = stack->scontext;
    5869             :                 }
    5870             : 
    5871       23034 :                 switch (gconf->vartype)
    5872             :                 {
    5873             :                     case PGC_BOOL:
    5874             :                         {
    5875        1232 :                             struct config_bool *conf = (struct config_bool *) gconf;
    5876        1232 :                             bool        newval = newvalue.val.boolval;
    5877        1232 :                             void       *newextra = newvalue.extra;
    5878             : 
    5879        1566 :                             if (*conf->variable != newval ||
    5880         334 :                                 conf->gen.extra != newextra)
    5881             :                             {
    5882         898 :                                 if (conf->assign_hook)
    5883           0 :                                     conf->assign_hook(newval, newextra);
    5884         898 :                                 *conf->variable = newval;
    5885         898 :                                 set_extra_field(&conf->gen, &conf->gen.extra,
    5886             :                                                 newextra);
    5887         898 :                                 changed = true;
    5888             :                             }
    5889        1232 :                             break;
    5890             :                         }
    5891             :                     case PGC_INT:
    5892             :                         {
    5893        5624 :                             struct config_int *conf = (struct config_int *) gconf;
    5894        5624 :                             int         newval = newvalue.val.intval;
    5895        5624 :                             void       *newextra = newvalue.extra;
    5896             : 
    5897        5738 :                             if (*conf->variable != newval ||
    5898         114 :                                 conf->gen.extra != newextra)
    5899             :                             {
    5900        5510 :                                 if (conf->assign_hook)
    5901           0 :                                     conf->assign_hook(newval, newextra);
    5902        5510 :                                 *conf->variable = newval;
    5903        5510 :                                 set_extra_field(&conf->gen, &conf->gen.extra,
    5904             :                                                 newextra);
    5905        5510 :                                 changed = true;
    5906             :                             }
    5907        5624 :                             break;
    5908             :                         }
    5909             :                     case PGC_REAL:
    5910             :                         {
    5911         180 :                             struct config_real *conf = (struct config_real *) gconf;
    5912         180 :                             double      newval = newvalue.val.realval;
    5913         180 :                             void       *newextra = newvalue.extra;
    5914             : 
    5915         196 :                             if (*conf->variable != newval ||
    5916          16 :                                 conf->gen.extra != newextra)
    5917             :                             {
    5918         164 :                                 if (conf->assign_hook)
    5919           0 :                                     conf->assign_hook(newval, newextra);
    5920         164 :                                 *conf->variable = newval;
    5921         164 :                                 set_extra_field(&conf->gen, &conf->gen.extra,
    5922             :                                                 newextra);
    5923         164 :                                 changed = true;
    5924             :                             }
    5925         180 :                             break;
    5926             :                         }
    5927             :                     case PGC_STRING:
    5928             :                         {
    5929        5776 :                             struct config_string *conf = (struct config_string *) gconf;
    5930        5776 :                             char       *newval = newvalue.val.stringval;
    5931        5776 :                             void       *newextra = newvalue.extra;
    5932             : 
    5933        5784 :                             if (*conf->variable != newval ||
    5934           8 :                                 conf->gen.extra != newextra)
    5935             :                             {
    5936        5768 :                                 if (conf->assign_hook)
    5937        5486 :                                     conf->assign_hook(newval, newextra);
    5938        5768 :                                 set_string_field(conf, conf->variable, newval);
    5939        5768 :                                 set_extra_field(&conf->gen, &conf->gen.extra,
    5940             :                                                 newextra);
    5941        5768 :                                 changed = true;
    5942             :                             }
    5943             : 
    5944             :                             /*
    5945             :                              * Release stacked values if not used anymore. We
    5946             :                              * could use discard_stack_value() here, but since
    5947             :                              * we have type-specific code anyway, might as
    5948             :                              * well inline it.
    5949             :                              */
    5950        5776 :                             set_string_field(conf, &stack->prior.val.stringval, NULL);
    5951        5776 :                             set_string_field(conf, &stack->masked.val.stringval, NULL);
    5952        5776 :                             break;
    5953             :                         }
    5954             :                     case PGC_ENUM:
    5955             :                         {
    5956       10222 :                             struct config_enum *conf = (struct config_enum *) gconf;
    5957       10222 :                             int         newval = newvalue.val.enumval;
    5958       10222 :                             void       *newextra = newvalue.extra;
    5959             : 
    5960       10686 :                             if (*conf->variable != newval ||
    5961         464 :                                 conf->gen.extra != newextra)
    5962             :                             {
    5963        9758 :                                 if (conf->assign_hook)
    5964           0 :                                     conf->assign_hook(newval, newextra);
    5965        9758 :                                 *conf->variable = newval;
    5966        9758 :                                 set_extra_field(&conf->gen, &conf->gen.extra,
    5967             :                                                 newextra);
    5968        9758 :                                 changed = true;
    5969             :                             }
    5970       10222 :                             break;
    5971             :                         }
    5972             :                 }
    5973             : 
    5974             :                 /*
    5975             :                  * Release stacked extra values if not used anymore.
    5976             :                  */
    5977       23034 :                 set_extra_field(gconf, &(stack->prior.extra), NULL);
    5978       23034 :                 set_extra_field(gconf, &(stack->masked.extra), NULL);
    5979             : 
    5980             :                 /* And restore source information */
    5981       23034 :                 gconf->source = newsource;
    5982       23034 :                 gconf->scontext = newscontext;
    5983             :             }
    5984             : 
    5985             :             /* Finish popping the state stack */
    5986       46392 :             gconf->stack = prev;
    5987       46392 :             pfree(stack);
    5988             : 
    5989             :             /* Report new value if we changed it */
    5990       46392 :             if (changed && (gconf->flags & GUC_REPORT))
    5991        9504 :                 ReportGUCOption(gconf);
    5992             :         }                       /* end of stack-popping loop */
    5993             : 
    5994     7608622 :         if (stack != NULL)
    5995        2040 :             still_dirty = true;
    5996             :     }
    5997             : 
    5998             :     /* If there are no remaining stack entries, we can reset guc_dirty */
    5999       23626 :     guc_dirty = still_dirty;
    6000             : 
    6001             :     /* Update nesting level */
    6002       23626 :     GUCNestLevel = nestLevel - 1;
    6003             : }
    6004             : 
    6005             : 
    6006             : /*
    6007             :  * Start up automatic reporting of changes to variables marked GUC_REPORT.
    6008             :  * This is executed at completion of backend startup.
    6009             :  */
    6010             : void
    6011        7002 : BeginReportingGUCOptions(void)
    6012             : {
    6013             :     int         i;
    6014             : 
    6015             :     /*
    6016             :      * Don't do anything unless talking to an interactive frontend of protocol
    6017             :      * 3.0 or later.
    6018             :      */
    6019       13684 :     if (whereToSendOutput != DestRemote ||
    6020        6682 :         PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
    6021         320 :         return;
    6022             : 
    6023        6682 :     reporting_enabled = true;
    6024             : 
    6025             :     /* Transmit initial values of interesting variables */
    6026     2144978 :     for (i = 0; i < num_guc_variables; i++)
    6027             :     {
    6028     2138296 :         struct config_generic *conf = guc_variables[i];
    6029             : 
    6030     2138296 :         if (conf->flags & GUC_REPORT)
    6031       73502 :             ReportGUCOption(conf);
    6032             :     }
    6033             : }
    6034             : 
    6035             : /*
    6036             :  * ReportGUCOption: if appropriate, transmit option value to frontend
    6037             :  */
    6038             : static void
    6039      172136 : ReportGUCOption(struct config_generic *record)
    6040             : {
    6041      172136 :     if (reporting_enabled && (record->flags & GUC_REPORT))
    6042             :     {
    6043       97288 :         char       *val = _ShowOption(record, false);
    6044             :         StringInfoData msgbuf;
    6045             : 
    6046       97288 :         pq_beginmessage(&msgbuf, 'S');
    6047       97288 :         pq_sendstring(&msgbuf, record->name);
    6048       97288 :         pq_sendstring(&msgbuf, val);
    6049       97288 :         pq_endmessage(&msgbuf);
    6050             : 
    6051       97288 :         pfree(val);
    6052             :     }
    6053      172136 : }
    6054             : 
    6055             : /*
    6056             :  * Convert a value from one of the human-friendly units ("kB", "min" etc.)
    6057             :  * to the given base unit.  'value' and 'unit' are the input value and unit
    6058             :  * to convert from (there can be trailing spaces in the unit string).
    6059             :  * The converted value is stored in *base_value.
    6060             :  * It's caller's responsibility to round off the converted value as necessary
    6061             :  * and check for out-of-range.
    6062             :  *
    6063             :  * Returns true on success, false if the input unit is not recognized.
    6064             :  */
    6065             : static bool
    6066        5348 : convert_to_base_unit(double value, const char *unit,
    6067             :                      int base_unit, double *base_value)
    6068             : {
    6069             :     char        unitstr[MAX_UNIT_LEN + 1];
    6070             :     int         unitlen;
    6071             :     const unit_conversion *table;
    6072             :     int         i;
    6073             : 
    6074             :     /* extract unit string to compare to table entries */
    6075        5348 :     unitlen = 0;
    6076       21294 :     while (*unit != '\0' && !isspace((unsigned char) *unit) &&
    6077             :            unitlen < MAX_UNIT_LEN)
    6078       10598 :         unitstr[unitlen++] = *(unit++);
    6079        5348 :     unitstr[unitlen] = '\0';
    6080             :     /* allow whitespace after unit */
    6081       10696 :     while (isspace((unsigned char) *unit))
    6082           0 :         unit++;
    6083        5348 :     if (*unit != '\0')
    6084           0 :         return false;           /* unit too long, or garbage after it */
    6085             : 
    6086             :     /* now search the appropriate table */
    6087        5348 :     if (base_unit & GUC_UNIT_MEMORY)
    6088        4594 :         table = memory_unit_conversion_table;
    6089             :     else
    6090         754 :         table = time_unit_conversion_table;
    6091             : 
    6092       67952 :     for (i = 0; *table[i].unit; i++)
    6093             :     {
    6094       84658 :         if (base_unit == table[i].base_unit &&
    6095       16706 :             strcmp(unitstr, table[i].unit) == 0)
    6096             :         {
    6097        5348 :             double      cvalue = value * table[i].multiplier;
    6098             : 
    6099             :             /*
    6100             :              * If the user gave a fractional value such as "30.1GB", round it
    6101             :              * off to the nearest multiple of the next smaller unit, if there
    6102             :              * is one.
    6103             :              */
    6104       10696 :             if (*table[i + 1].unit &&
    6105        5348 :                 base_unit == table[i + 1].base_unit)
    6106       10688 :                 cvalue = rint(cvalue / table[i + 1].multiplier) *
    6107        5344 :                     table[i + 1].multiplier;
    6108             : 
    6109        5348 :             *base_value = cvalue;
    6110        5348 :             return true;
    6111             :         }
    6112             :     }
    6113           0 :     return false;
    6114             : }
    6115             : 
    6116             : /*
    6117             :  * Convert an integer value in some base unit to a human-friendly unit.
    6118             :  *
    6119             :  * The output unit is chosen so that it's the greatest unit that can represent
    6120             :  * the value without loss.  For example, if the base unit is GUC_UNIT_KB, 1024
    6121             :  * is converted to 1 MB, but 1025 is represented as 1025 kB.
    6122             :  */
    6123             : static void
    6124         300 : convert_int_from_base_unit(int64 base_value, int base_unit,
    6125             :                            int64 *value, const char **unit)
    6126             : {
    6127             :     const unit_conversion *table;
    6128             :     int         i;
    6129             : 
    6130         300 :     *unit = NULL;
    6131             : 
    6132         300 :     if (base_unit & GUC_UNIT_MEMORY)
    6133         244 :         table = memory_unit_conversion_table;
    6134             :     else
    6135          56 :         table = time_unit_conversion_table;
    6136             : 
    6137        2256 :     for (i = 0; *table[i].unit; i++)
    6138             :     {
    6139        2256 :         if (base_unit == table[i].base_unit)
    6140             :         {
    6141             :             /*
    6142             :              * Accept the first conversion that divides the value evenly.  We
    6143             :              * assume that the conversions for each base unit are ordered from
    6144             :              * greatest unit to the smallest!
    6145             :              */
    6146        1852 :             if (table[i].multiplier <= 1.0 ||
    6147         904 :                 base_value % (int64) table[i].multiplier == 0)
    6148             :             {
    6149         300 :                 *value = (int64) rint(base_value / table[i].multiplier);
    6150         300 :                 *unit = table[i].unit;
    6151         300 :                 break;
    6152             :             }
    6153             :         }
    6154             :     }
    6155             : 
    6156             :     Assert(*unit != NULL);
    6157         300 : }
    6158             : 
    6159             : /*
    6160             :  * Convert a floating-point value in some base unit to a human-friendly unit.
    6161             :  *
    6162             :  * Same as above, except we have to do the math a bit differently, and
    6163             :  * there's a possibility that we don't find any exact divisor.
    6164             :  */
    6165             : static void
    6166         180 : convert_real_from_base_unit(double base_value, int base_unit,
    6167             :                             double *value, const char **unit)
    6168             : {
    6169             :     const unit_conversion *table;
    6170             :     int         i;
    6171             : 
    6172         180 :     *unit = NULL;
    6173             : 
    6174         180 :     if (base_unit & GUC_UNIT_MEMORY)
    6175           0 :         table = memory_unit_conversion_table;
    6176             :     else
    6177         180 :         table = time_unit_conversion_table;
    6178             : 
    6179         916 :     for (i = 0; *table[i].unit; i++)
    6180             :     {
    6181         916 :         if (base_unit == table[i].base_unit)
    6182             :         {
    6183             :             /*
    6184             :              * Accept the first conversion that divides the value evenly; or
    6185             :              * if there is none, use the smallest (last) target unit.
    6186             :              *
    6187             :              * What we actually care about here is whether snprintf with "%g"
    6188             :              * will print the value as an integer, so the obvious test of
    6189             :              * "*value == rint(*value)" is too strict; roundoff error might
    6190             :              * make us choose an unreasonably small unit.  As a compromise,
    6191             :              * accept a divisor that is within 1e-8 of producing an integer.
    6192             :              */
    6193         916 :             *value = base_value / table[i].multiplier;
    6194         916 :             *unit = table[i].unit;
    6195        1832 :             if (*value > 0 &&
    6196         916 :                 fabs((rint(*value) / *value) - 1.0) <= 1e-8)
    6197         180 :                 break;
    6198             :         }
    6199             :     }
    6200             : 
    6201             :     Assert(*unit != NULL);
    6202         180 : }
    6203             : 
    6204             : /*
    6205             :  * Return the name of a GUC's base unit (e.g. "ms") given its flags.
    6206             :  * Return NULL if the GUC is unitless.
    6207             :  */
    6208             : static const char *
    6209        8964 : get_config_unit_name(int flags)
    6210             : {
    6211        8964 :     switch (flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME))
    6212             :     {
    6213             :         case 0:
    6214        7504 :             return NULL;        /* GUC has no units */
    6215             :         case GUC_UNIT_BYTE:
    6216          56 :             return "B";
    6217             :         case GUC_UNIT_KB:
    6218         224 :             return "kB";
    6219             :         case GUC_UNIT_MB:
    6220          56 :             return "MB";
    6221             :         case GUC_UNIT_BLOCKS:
    6222             :             {
    6223             :                 static char bbuf[8];
    6224             : 
    6225             :                 /* initialize if first time through */
    6226         252 :                 if (bbuf[0] == '\0')
    6227          14 :                     snprintf(bbuf, sizeof(bbuf), "%dkB", BLCKSZ / 1024);
    6228         252 :                 return bbuf;
    6229             :             }
    6230             :         case GUC_UNIT_XBLOCKS:
    6231             :             {
    6232             :                 static char xbuf[8];
    6233             : 
    6234             :                 /* initialize if first time through */
    6235          56 :                 if (xbuf[0] == '\0')
    6236          14 :                     snprintf(xbuf, sizeof(xbuf), "%dkB", XLOG_BLCKSZ / 1024);
    6237          56 :                 return xbuf;
    6238             :             }
    6239             :         case GUC_UNIT_MS:
    6240         480 :             return "ms";
    6241             :         case GUC_UNIT_S:
    6242         280 :             return "s";
    6243             :         case GUC_UNIT_MIN:
    6244          56 :             return "min";
    6245             :         default:
    6246           0 :             elog(ERROR, "unrecognized GUC units value: %d",
    6247             :                  flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME));
    6248             :             return NULL;
    6249             :     }
    6250             : }
    6251             : 
    6252             : 
    6253             : /*
    6254             :  * Try to parse value as an integer.  The accepted formats are the
    6255             :  * usual decimal, octal, or hexadecimal formats, as well as floating-point
    6256             :  * formats (which will be rounded to integer after any units conversion).
    6257             :  * Optionally, the value can be followed by a unit name if "flags" indicates
    6258             :  * a unit is allowed.
    6259             :  *
    6260             :  * If the string parses okay, return true, else false.
    6261             :  * If okay and result is not NULL, return the value in *result.
    6262             :  * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
    6263             :  * HINT message, or NULL if no hint provided.
    6264             :  */
    6265             : bool
    6266       39614 : parse_int(const char *value, int *result, int flags, const char **hintmsg)
    6267             : {
    6268             :     /*
    6269             :      * We assume here that double is wide enough to represent any integer
    6270             :      * value with adequate precision.
    6271             :      */
    6272             :     double      val;
    6273             :     char       *endptr;
    6274             : 
    6275             :     /* To suppress compiler warnings, always set output params */
    6276       39614 :     if (result)
    6277       39614 :         *result = 0;
    6278       39614 :     if (hintmsg)
    6279       35782 :         *hintmsg = NULL;
    6280             : 
    6281             :     /*
    6282             :      * Try to parse as an integer (allowing octal or hex input).  If the
    6283             :      * conversion stops at a decimal point or 'e', or overflows, re-parse as
    6284             :      * float.  This should work fine as long as we have no unit names starting
    6285             :      * with 'e'.  If we ever do, the test could be extended to check for a
    6286             :      * sign or digit after 'e', but for now that's unnecessary.
    6287             :      */
    6288       39614 :     errno = 0;
    6289       39614 :     val = strtol(value, &endptr, 0);
    6290       79224 :     if (*endptr == '.' || *endptr == 'e' || *endptr == 'E' ||
    6291       39610 :         errno == ERANGE)
    6292             :     {
    6293           4 :         errno = 0;
    6294           4 :         val = strtod(value, &endptr);
    6295             :     }
    6296             : 
    6297       39614 :     if (endptr == value || errno == ERANGE)
    6298          12 :         return false;           /* no HINT for these cases */
    6299             : 
    6300             :     /* reject NaN (infinities will fail range check below) */
    6301       39602 :     if (isnan(val))
    6302           0 :         return false;           /* treat same as syntax error; no HINT */
    6303             : 
    6304             :     /* allow whitespace between number and unit */
    6305       79204 :     while (isspace((unsigned char) *endptr))
    6306           0 :         endptr++;
    6307             : 
    6308             :     /* Handle possible unit */
    6309       39602 :     if (*endptr != '\0')
    6310             :     {
    6311        5340 :         if ((flags & GUC_UNIT) == 0)
    6312           0 :             return false;       /* this setting does not accept a unit */
    6313             : 
    6314        5340 :         if (!convert_to_base_unit(val,
    6315             :                                   endptr, (flags & GUC_UNIT),
    6316             :                                   &val))
    6317             :         {
    6318             :             /* invalid unit, or garbage after the unit; set hint and fail. */
    6319           0 :             if (hintmsg)
    6320             :             {
    6321           0 :                 if (flags & GUC_UNIT_MEMORY)
    6322           0 :                     *hintmsg = memory_units_hint;
    6323             :                 else
    6324           0 :                     *hintmsg = time_units_hint;
    6325             :             }
    6326           0 :             return false;
    6327             :         }
    6328             :     }
    6329             : 
    6330             :     /* Round to int, then check for overflow */
    6331       39602 :     val = rint(val);
    6332             : 
    6333       39602 :     if (val > INT_MAX || val < INT_MIN)
    6334             :     {
    6335           0 :         if (hintmsg)
    6336           0 :             *hintmsg = gettext_noop("Value exceeds integer range.");
    6337           0 :         return false;
    6338             :     }
    6339             : 
    6340       39602 :     if (result)
    6341       39602 :         *result = (int) val;
    6342       39602 :     return true;
    6343             : }
    6344             : 
    6345             : /*
    6346             :  * Try to parse value as a floating point number in the usual format.
    6347             :  * Optionally, the value can be followed by a unit name if "flags" indicates
    6348             :  * a unit is allowed.
    6349             :  *
    6350             :  * If the string parses okay, return true, else false.
    6351             :  * If okay and result is not NULL, return the value in *result.
    6352             :  * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
    6353             :  * HINT message, or NULL if no hint provided.
    6354             :  */
    6355             : bool
    6356        3512 : parse_real(const char *value, double *result, int flags, const char **hintmsg)
    6357             : {
    6358             :     double      val;
    6359             :     char       *endptr;
    6360             : 
    6361             :     /* To suppress compiler warnings, always set output params */
    6362        3512 :     if (result)
    6363        3512 :         *result = 0;
    6364        3512 :     if (hintmsg)
    6365        3194 :         *hintmsg = NULL;
    6366             : 
    6367        3512 :     errno = 0;
    6368        3512 :     val = strtod(value, &endptr);
    6369             : 
    6370        3512 :     if (endptr == value || errno == ERANGE)
    6371          16 :         return false;           /* no HINT for these cases */
    6372             : 
    6373             :     /* reject NaN (infinities will fail range checks later) */
    6374        3496 :     if (isnan(val))
    6375           4 :         return false;           /* treat same as syntax error; no HINT */
    6376             : 
    6377             :     /* allow whitespace between number and unit */
    6378        6984 :     while (isspace((unsigned char) *endptr))
    6379           0 :         endptr++;
    6380             : 
    6381             :     /* Handle possible unit */
    6382        3492 :     if (*endptr != '\0')
    6383             :     {
    6384           8 :         if ((flags & GUC_UNIT) == 0)
    6385           0 :             return false;       /* this setting does not accept a unit */
    6386             : 
    6387           8 :         if (!convert_to_base_unit(val,
    6388             :                                   endptr, (flags & GUC_UNIT),
    6389             :                                   &val))
    6390             :         {
    6391             :             /* invalid unit, or garbage after the unit; set hint and fail. */
    6392           0 :             if (hintmsg)
    6393             :             {
    6394           0 :                 if (flags & GUC_UNIT_MEMORY)
    6395           0 :                     *hintmsg = memory_units_hint;
    6396             :                 else
    6397           0 :                     *hintmsg = time_units_hint;
    6398             :             }
    6399           0 :             return false;
    6400             :         }
    6401             :     }
    6402             : 
    6403        3492 :     if (result)
    6404        3492 :         *result = val;
    6405        3492 :     return true;
    6406             : }
    6407             : 
    6408             : 
    6409             : /*
    6410             :  * Lookup the name for an enum option with the selected value.
    6411             :  * Should only ever be called with known-valid values, so throws
    6412             :  * an elog(ERROR) if the enum option is not found.
    6413             :  *
    6414             :  * The returned string is a pointer to static data and not
    6415             :  * allocated for modification.
    6416             :  */
    6417             : const char *
    6418       22316 : config_enum_lookup_by_value(struct config_enum *record, int val)
    6419             : {
    6420             :     const struct config_enum_entry *entry;
    6421             : 
    6422       38384 :     for (entry = record->options; entry && entry->name; entry++)
    6423             :     {
    6424       38384 :         if (entry->val == val)
    6425       22316 :             return entry->name;
    6426             :     }
    6427             : 
    6428           0 :     elog(ERROR, "could not find enum option %d for %s",
    6429             :          val, record->gen.name);
    6430             :     return NULL;                /* silence compiler */
    6431             : }
    6432             : 
    6433             : 
    6434             : /*
    6435             :  * Lookup the value for an enum option with the selected name
    6436             :  * (case-insensitive).
    6437             :  * If the enum option is found, sets the retval value and returns
    6438             :  * true. If it's not found, return false and retval is set to 0.
    6439             :  */
    6440             : bool
    6441       29494 : config_enum_lookup_by_name(struct config_enum *record, const char *value,
    6442             :                            int *retval)
    6443             : {
    6444             :     const struct config_enum_entry *entry;
    6445             : 
    6446       61008 :     for (entry = record->options; entry && entry->name; entry++)
    6447             :     {
    6448       61000 :         if (pg_strcasecmp(value, entry->name) == 0)
    6449             :         {
    6450       29486 :             *retval = entry->val;
    6451       29486 :             return true;
    6452             :         }
    6453             :     }
    6454             : 
    6455           8 :     *retval = 0;
    6456           8 :     return false;
    6457             : }
    6458             : 
    6459             : 
    6460             : /*
    6461             :  * Return a list of all available options for an enum, excluding
    6462             :  * hidden ones, separated by the given separator.
    6463             :  * If prefix is non-NULL, it is added before the first enum value.
    6464             :  * If suffix is non-NULL, it is added to the end of the string.
    6465             :  */
    6466             : static char *
    6467         848 : config_enum_get_options(struct config_enum *record, const char *prefix,
    6468             :                         const char *suffix, const char *separator)
    6469             : {
    6470             :     const struct config_enum_entry *entry;
    6471             :     StringInfoData retstr;
    6472             :     int         seplen;
    6473             : 
    6474         848 :     initStringInfo(&retstr);
    6475         848 :     appendStringInfoString(&retstr, prefix);
    6476             : 
    6477         848 :     seplen = strlen(separator);
    6478        5900 :     for (entry = record->options; entry && entry->name; entry++)
    6479             :     {
    6480        5052 :         if (!entry->hidden)
    6481             :         {
    6482        3668 :             appendStringInfoString(&retstr, entry->name);
    6483        3668 :             appendBinaryStringInfo(&retstr, separator, seplen);
    6484             :         }
    6485             :     }
    6486             : 
    6487             :     /*
    6488             :      * All the entries may have been hidden, leaving the string empty if no
    6489             :      * prefix was given. This indicates a broken GUC setup, since there is no
    6490             :      * use for an enum without any values, so we just check to make sure we
    6491             :      * don't write to invalid memory instead of actually trying to do
    6492             :      * something smart with it.
    6493             :      */
    6494         848 :     if (retstr.len >= seplen)
    6495             :     {
    6496             :         /* Replace final separator */
    6497         848 :         retstr.data[retstr.len - seplen] = '\0';
    6498         848 :         retstr.len -= seplen;
    6499             :     }
    6500             : 
    6501         848 :     appendStringInfoString(&retstr, suffix);
    6502             : 
    6503         848 :     return retstr.data;
    6504             : }
    6505             : 
    6506             : /*
    6507             :  * Parse and validate a proposed value for the specified configuration
    6508             :  * parameter.
    6509             :  *
    6510             :  * This does built-in checks (such as range limits for an integer parameter)
    6511             :  * and also calls any check hook the parameter may have.
    6512             :  *
    6513             :  * record: GUC variable's info record
    6514             :  * name: variable name (should match the record of course)
    6515             :  * value: proposed value, as a string
    6516             :  * source: identifies source of value (check hooks may need this)
    6517             :  * elevel: level to log any error reports at
    6518             :  * newval: on success, converted parameter value is returned here
    6519             :  * newextra: on success, receives any "extra" data returned by check hook
    6520             :  *  (caller must initialize *newextra to NULL)
    6521             :  *
    6522             :  * Returns true if OK, false if not (or throws error, if elevel >= ERROR)
    6523             :  */
    6524             : static bool
    6525      254982 : parse_and_validate_value(struct config_generic *record,
    6526             :                          const char *name, const char *value,
    6527             :                          GucSource source, int elevel,
    6528             :                          union config_var_val *newval, void **newextra)
    6529             : {
    6530      254982 :     switch (record->vartype)
    6531             :     {
    6532             :         case PGC_BOOL:
    6533             :             {
    6534       51848 :                 struct config_bool *conf = (struct config_bool *) record;
    6535             : 
    6536       51848 :                 if (!parse_bool(value, &newval->boolval))
    6537             :                 {
    6538           0 :                     ereport(elevel,
    6539             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    6540             :                              errmsg("parameter \"%s\" requires a Boolean value",
    6541             :                                     name)));
    6542           0 :                     return false;
    6543             :                 }
    6544             : 
    6545       51848 :                 if (!call_bool_check_hook(conf, &newval->boolval, newextra,
    6546             :                                           source, elevel))
    6547           0 :                     return false;
    6548             :             }
    6549       51832 :             break;
    6550             :         case PGC_INT:
    6551             :             {
    6552       35782 :                 struct config_int *conf = (struct config_int *) record;
    6553             :                 const char *hintmsg;
    6554             : 
    6555       35782 :                 if (!parse_int(value, &newval->intval,
    6556             :                                conf->gen.flags, &hintmsg))
    6557             :                 {
    6558           0 :                     ereport(elevel,
    6559             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    6560             :                              errmsg("invalid value for parameter \"%s\": \"%s\"",
    6561             :                                     name, value),
    6562             :                              hintmsg ? errhint("%s", _(hintmsg)) : 0));
    6563           0 :                     return false;
    6564             :                 }
    6565             : 
    6566       35782 :                 if (newval->intval < conf->min || newval->intval > conf->max)
    6567             :                 {
    6568           0 :                     const char *unit = get_config_unit_name(conf->gen.flags);
    6569             : 
    6570           0 :                     ereport(elevel,
    6571             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    6572             :                              errmsg("%d%s%s is outside the valid range for parameter \"%s\" (%d .. %d)",
    6573             :                                     newval->intval,
    6574             :                                     unit ? " " : "",
    6575             :                                     unit ? unit : "",
    6576             :                                     name,
    6577             :                                     conf->min, conf->max)));
    6578           0 :                     return false;
    6579             :                 }
    6580             : 
    6581       35782 :                 if (!call_int_check_hook(conf, &newval->intval, newextra,
    6582             :                                          source, elevel))
    6583           0 :                     return false;
    6584             :             }
    6585       35782 :             break;
    6586             :         case PGC_REAL:
    6587             :             {
    6588        3194 :                 struct config_real *conf = (struct config_real *) record;
    6589             :                 const char *hintmsg;
    6590             : 
    6591        3194 :                 if (!parse_real(value, &newval->realval,
    6592             :                                 conf->gen.flags, &hintmsg))
    6593             :                 {
    6594           4 :                     ereport(elevel,
    6595             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    6596             :                              errmsg("invalid value for parameter \"%s\": \"%s\"",
    6597             :                                     name, value),
    6598             :                              hintmsg ? errhint("%s", _(hintmsg)) : 0));
    6599           0 :                     return false;
    6600             :                 }
    6601             : 
    6602        3190 :                 if (newval->realval < conf->min || newval->realval > conf->max)
    6603             :                 {
    6604           4 :                     const char *unit = get_config_unit_name(conf->gen.flags);
    6605             : 
    6606           4 :                     ereport(elevel,
    6607             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    6608             :                              errmsg("%g%s%s is outside the valid range for parameter \"%s\" (%g .. %g)",
    6609             :                                     newval->realval,
    6610             :                                     unit ? " " : "",
    6611             :                                     unit ? unit : "",
    6612             :                                     name,
    6613             :                                     conf->min, conf->max)));
    6614           0 :                     return false;
    6615             :                 }
    6616             : 
    6617        3186 :                 if (!call_real_check_hook(conf, &newval->realval, newextra,
    6618             :                                           source, elevel))
    6619           0 :                     return false;
    6620             :             }
    6621        3186 :             break;
    6622             :         case PGC_STRING:
    6623             :             {
    6624      134664 :                 struct config_string *conf = (struct config_string *) record;
    6625             : 
    6626             :                 /*
    6627             :                  * The value passed by the caller could be transient, so we
    6628             :                  * always strdup it.
    6629             :                  */
    6630      134664 :                 newval->stringval = guc_strdup(elevel, value);
    6631      134664 :                 if (newval->stringval == NULL)
    6632           0 :                     return false;
    6633             : 
    6634             :                 /*
    6635             :                  * The only built-in "parsing" check we have is to apply
    6636             :                  * truncation if GUC_IS_NAME.
    6637             :                  */
    6638      134664 :                 if (conf->gen.flags & GUC_IS_NAME)
    6639       40602 :                     truncate_identifier(newval->stringval,
    6640       40602 :                                         strlen(newval->stringval),
    6641             :                                         true);
    6642             : 
    6643      134664 :                 if (!call_string_check_hook(conf, &newval->stringval, newextra,
    6644             :                                             source, elevel))
    6645             :                 {
    6646           0 :                     free(newval->stringval);
    6647           0 :                     newval->stringval = NULL;
    6648           0 :                     return false;
    6649             :                 }
    6650             :             }
    6651      134644 :             break;
    6652             :         case PGC_ENUM:
    6653             :             {
    6654       29494 :                 struct config_enum *conf = (struct config_enum *) record;
    6655             : 
    6656       29494 :                 if (!config_enum_lookup_by_name(conf, value, &newval->enumval))
    6657             :                 {
    6658             :                     char       *hintmsg;
    6659             : 
    6660           8 :                     hintmsg = config_enum_get_options(conf,
    6661             :                                                       "Available values: ",
    6662             :                                                       ".", ", ");
    6663             : 
    6664           8 :                     ereport(elevel,
    6665             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    6666             :                              errmsg("invalid value for parameter \"%s\": \"%s\"",
    6667             :                                     name, value),
    6668             :                              hintmsg ? errhint("%s", _(hintmsg)) : 0));
    6669             : 
    6670           0 :                     if (hintmsg)
    6671           0 :                         pfree(hintmsg);
    6672           0 :                     return false;
    6673             :                 }
    6674             : 
    6675       29486 :                 if (!call_enum_check_hook(conf, &newval->enumval, newextra,
    6676             :                                           source, elevel))
    6677           0 :                     return false;
    6678             :             }
    6679       29484 :             break;
    6680             :     }
    6681             : 
    6682      254928 :     return true;
    6683             : }
    6684             : 
    6685             : 
    6686             : /*
    6687             :  * Sets option `name' to given value.
    6688             :  *
    6689             :  * The value should be a string, which will be parsed and converted to
    6690             :  * the appropriate data type.  The context and source parameters indicate
    6691             :  * in which context this function is being called, so that it can apply the
    6692             :  * access restrictions properly.
    6693             :  *
    6694             :  * If value is NULL, set the option to its default value (normally the
    6695             :  * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
    6696             :  *
    6697             :  * action indicates whether to set the value globally in the session, locally
    6698             :  * to the current top transaction, or just for the duration of a function call.
    6699             :  *
    6700             :  * If changeVal is false then don't really set the option but do all
    6701             :  * the checks to see if it would work.
    6702             :  *
    6703             :  * elevel should normally be passed as zero, allowing this function to make
    6704             :  * its standard choice of ereport level.  However some callers need to be
    6705             :  * able to override that choice; they should pass the ereport level to use.
    6706             :  *
    6707             :  * Return value:
    6708             :  *  +1: the value is valid and was successfully applied.
    6709             :  *  0:  the name or value is invalid (but see below).
    6710             :  *  -1: the value was not applied because of context, priority, or changeVal.
    6711             :  *
    6712             :  * If there is an error (non-existing option, invalid value) then an
    6713             :  * ereport(ERROR) is thrown *unless* this is called for a source for which
    6714             :  * we don't want an ERROR (currently, those are defaults, the config file,
    6715             :  * and per-database or per-user settings, as well as callers who specify
    6716             :  * a less-than-ERROR elevel).  In those cases we write a suitable error
    6717             :  * message via ereport() and return 0.
    6718             :  *
    6719             :  * See also SetConfigOption for an external interface.
    6720             :  */
    6721             : int
    6722      256734 : set_config_option(const char *name, const char *value,
    6723             :                   GucContext context, GucSource source,
    6724             :                   GucAction action, bool changeVal, int elevel,
    6725             :                   bool is_reload)
    6726             : {
    6727             :     struct config_generic *record;
    6728             :     union config_var_val newval_union;
    6729      256734 :     void       *newextra = NULL;
    6730      256734 :     bool        prohibitValueChange = false;
    6731             :     bool        makeDefault;
    6732             : 
    6733      256734 :     if (elevel == 0)
    6734             :     {
    6735      206614 :         if (source == PGC_S_DEFAULT || source == PGC_S_FILE)
    6736             :         {
    6737             :             /*
    6738             :              * To avoid cluttering the log, only the postmaster bleats loudly
    6739             :              * about problems with the config file.
    6740             :              */
    6741       28686 :             elevel = IsUnderPostmaster ? DEBUG3 : LOG;
    6742             :         }
    6743      177928 :         else if (source == PGC_S_GLOBAL ||
    6744      152212 :                  source == PGC_S_DATABASE ||
    6745      152212 :                  source == PGC_S_USER ||
    6746             :                  source == PGC_S_DATABASE_USER)
    6747       25716 :             elevel = WARNING;
    6748             :         else
    6749      152212 :             elevel = ERROR;
    6750             :     }
    6751             : 
    6752             :     /*
    6753             :      * GUC_ACTION_SAVE changes are acceptable during a parallel operation,
    6754             :      * because the current worker will also pop the change.  We're probably
    6755             :      * dealing with a function having a proconfig entry.  Only the function's
    6756             :      * body should observe the change, and peer workers do not share in the
    6757             :      * execution of a function call started by this worker.
    6758             :      *
    6759             :      * Other changes might need to affect other workers, so forbid them.
    6760             :      */
    6761      256734 :     if (IsInParallelMode() && changeVal && action != GUC_ACTION_SAVE)
    6762           0 :         ereport(elevel,
    6763             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    6764             :                  errmsg("cannot set parameters during a parallel operation")));
    6765             : 
    6766      256734 :     record = find_option(name, true, elevel);
    6767      256734 :     if (record == NULL)
    6768             :     {
    6769           0 :         ereport(elevel,
    6770             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    6771             :                  errmsg("unrecognized configuration parameter \"%s\"", name)));
    6772           0 :         return 0;
    6773             :     }
    6774             : 
    6775             :     /*
    6776             :      * Check if the option can be set at this time. See guc.h for the precise
    6777             :      * rules.
    6778             :      */
    6779      256734 :     switch (record->context)
    6780             :     {
    6781             :         case PGC_INTERNAL:
    6782       50706 :             if (context != PGC_INTERNAL)
    6783             :             {
    6784           0 :                 ereport(elevel,
    6785             :                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    6786             :                          errmsg("parameter \"%s\" cannot be changed",
    6787             :                                 name)));
    6788           0 :                 return 0;
    6789             :             }
    6790       50706 :             break;
    6791             :         case PGC_POSTMASTER:
    6792       22032 :             if (context == PGC_SIGHUP)
    6793             :             {
    6794             :                 /*
    6795             :                  * We are re-reading a PGC_POSTMASTER variable from
    6796             :                  * postgresql.conf.  We can't change the setting, so we should
    6797             :                  * give a warning if the DBA tries to change it.  However,
    6798             :                  * because of variant formats, canonicalization by check
    6799             :                  * hooks, etc, we can't just compare the given string directly
    6800             :                  * to what's stored.  Set a flag to check below after we have
    6801             :                  * the final storable value.
    6802             :                  */
    6803        1956 :                 prohibitValueChange = true;
    6804             :             }
    6805       20076 :             else if (context != PGC_POSTMASTER)
    6806             :             {
    6807           0 :                 ereport(elevel,
    6808             :                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    6809             :                          errmsg("parameter \"%s\" cannot be changed without restarting the server",
    6810             :                                 name)));
    6811           0 :                 return 0;
    6812             :             }
    6813       22032 :             break;
    6814             :         case PGC_SIGHUP:
    6815       19372 :             if (context != PGC_SIGHUP && context != PGC_POSTMASTER)
    6816             :             {
    6817           0 :                 ereport(elevel,
    6818             :                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    6819             :                          errmsg("parameter \"%s\" cannot be changed now",
    6820             :                                 name)));
    6821           0 :                 return 0;
    6822             :             }
    6823             : 
    6824             :             /*
    6825             :              * Hmm, the idea of the SIGHUP context is "ought to be global, but
    6826             :              * can be changed after postmaster start". But there's nothing
    6827             :              * that prevents a crafty administrator from sending SIGHUP
    6828             :              * signals to individual backends only.
    6829             :              */
    6830       19372 :             break;
    6831             :         case PGC_SU_BACKEND:
    6832             :             /* Reject if we're connecting but user is not superuser */
    6833          30 :             if (context == PGC_BACKEND)
    6834             :             {
    6835           0 :                 ereport(elevel,
    6836             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    6837             :                          errmsg("permission denied to set parameter \"%s\"",
    6838             :                                 name)));
    6839           0 :                 return 0;
    6840             :             }
    6841             :             /* fall through to process the same as PGC_BACKEND */
    6842             :             /* FALLTHROUGH */
    6843             :         case PGC_BACKEND:
    6844          30 :             if (context == PGC_SIGHUP)
    6845             :             {
    6846             :                 /*
    6847             :                  * If a PGC_BACKEND or PGC_SU_BACKEND parameter is changed in
    6848             :                  * the config file, we want to accept the new value in the
    6849             :                  * postmaster (whence it will propagate to
    6850             :                  * subsequently-started backends), but ignore it in existing
    6851             :                  * backends.  This is a tad klugy, but necessary because we
    6852             :                  * don't re-read the config file during backend start.
    6853             :                  *
    6854             :                  * In EXEC_BACKEND builds, this works differently: we load all
    6855             :                  * non-default settings from the CONFIG_EXEC_PARAMS file
    6856             :                  * during backend start.  In that case we must accept
    6857             :                  * PGC_SIGHUP settings, so as to have the same value as if
    6858             :                  * we'd forked from the postmaster.  This can also happen when
    6859             :                  * using RestoreGUCState() within a background worker that
    6860             :                  * needs to have the same settings as the user backend that
    6861             :                  * started it. is_reload will be true when either situation
    6862             :                  * applies.
    6863             :                  */
    6864           4 :                 if (IsUnderPostmaster && !is_reload)
    6865           2 :                     return -1;
    6866             :             }
    6867          26 :             else if (context != PGC_POSTMASTER &&
    6868           0 :                      context != PGC_BACKEND &&
    6869           0 :                      context != PGC_SU_BACKEND &&
    6870             :                      source != PGC_S_CLIENT)
    6871             :             {
    6872           0 :                 ereport(elevel,
    6873             :                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    6874             :                          errmsg("parameter \"%s\" cannot be set after connection start",
    6875             :                                 name)));
    6876           0 :                 return 0;
    6877             :             }
    6878          28 :             break;
    6879             :         case PGC_SUSET:
    6880       15012 :             if (context == PGC_USERSET || context == PGC_BACKEND)
    6881             :             {
    6882           0 :                 ereport(elevel,
    6883             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    6884             :                          errmsg("permission denied to set parameter \"%s\"",
    6885             :                                 name)));
    6886           0 :                 return 0;
    6887             :             }
    6888       15012 :             break;
    6889             :         case PGC_USERSET:
    6890             :             /* always okay */
    6891      149582 :             break;
    6892             :     }
    6893             : 
    6894             :     /*
    6895             :      * Disallow changing GUC_NOT_WHILE_SEC_REST values if we are inside a
    6896             :      * security restriction context.  We can reject this regardless of the GUC
    6897             :      * context or source, mainly because sources that it might be reasonable
    6898             :      * to override for won't be seen while inside a function.
    6899             :      *
    6900             :      * Note: variables marked GUC_NOT_WHILE_SEC_REST should usually be marked
    6901             :      * GUC_NO_RESET_ALL as well, because ResetAllOptions() doesn't check this.
    6902             :      * An exception might be made if the reset value is assumed to be "safe".
    6903             :      *
    6904             :      * Note: this flag is currently used for "session_authorization" and
    6905             :      * "role".  We need to prohibit changing these inside a local userid
    6906             :      * context because when we exit it, GUC won't be notified, leaving things
    6907             :      * out of sync.  (This could be fixed by forcing a new GUC nesting level,
    6908             :      * but that would change behavior in possibly-undesirable ways.)  Also, we
    6909             :      * prohibit changing these in a security-restricted operation because
    6910             :      * otherwise RESET could be used to regain the session user's privileges.
    6911             :      */
    6912      256732 :     if (record->flags & GUC_NOT_WHILE_SEC_REST)
    6913             :     {
    6914       12236 :         if (InLocalUserIdChange())
    6915             :         {
    6916             :             /*
    6917             :              * Phrasing of this error message is historical, but it's the most
    6918             :              * common case.
    6919             :              */
    6920           0 :             ereport(elevel,
    6921             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    6922             :                      errmsg("cannot set parameter \"%s\" within security-definer function",
    6923             :                             name)));
    6924           0 :             return 0;
    6925             :         }
    6926       12236 :         if (InSecurityRestrictedOperation())
    6927             :         {
    6928           0 :             ereport(elevel,
    6929             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    6930             :                      errmsg("cannot set parameter \"%s\" within security-restricted operation",
    6931             :                             name)));
    6932           0 :             return 0;
    6933             :         }
    6934             :     }
    6935             : 
    6936             :     /*
    6937             :      * Should we set reset/stacked values?  (If so, the behavior is not
    6938             :      * transactional.)  This is done either when we get a default value from
    6939             :      * the database's/user's/client's default settings or when we reset a
    6940             :      * value to its default.
    6941             :      */
    6942      461822 :     makeDefault = changeVal && (source <= PGC_S_OVERRIDE) &&
    6943           0 :         ((value != NULL) || source == PGC_S_DEFAULT);
    6944             : 
    6945             :     /*
    6946             :      * Ignore attempted set if overridden by previously processed setting.
    6947             :      * However, if changeVal is false then plow ahead anyway since we are
    6948             :      * trying to find out if the value is potentially good, not actually use
    6949             :      * it. Also keep going if makeDefault is true, since we may want to set
    6950             :      * the reset/stacked values even if we can't set the variable itself.
    6951             :      */
    6952      256732 :     if (record->source > source)
    6953             :     {
    6954         822 :         if (changeVal && !makeDefault)
    6955             :         {
    6956           0 :             elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
    6957             :                  name);
    6958           0 :             return -1;
    6959             :         }
    6960         822 :         changeVal = false;
    6961             :     }
    6962             : 
    6963             :     /*
    6964             :      * Evaluate value and set variable.
    6965             :      */
    6966      256732 :     switch (record->vartype)
    6967             :     {
    6968             :         case PGC_BOOL:
    6969             :             {
    6970       52430 :                 struct config_bool *conf = (struct config_bool *) record;
    6971             : 
    6972             : #define newval (newval_union.boolval)
    6973             : 
    6974       52430 :                 if (value)
    6975             :                 {
    6976       51836 :                     if (!parse_and_validate_value(record, name, value,
    6977             :                                                   source, elevel,
    6978             :                                                   &newval_union, &newextra))
    6979           0 :                         return 0;
    6980             :                 }
    6981         594 :                 else if (source == PGC_S_DEFAULT)
    6982             :                 {
    6983           0 :                     newval = conf->boot_val;
    6984           0 :                     if (!call_bool_check_hook(conf, &newval, &newextra,
    6985             :                                               source, elevel))
    6986           0 :                         return 0;
    6987             :                 }
    6988             :                 else
    6989             :                 {
    6990         594 :                     newval = conf->reset_val;
    6991         594 :                     newextra = conf->reset_extra;
    6992         594 :                     source = conf->gen.reset_source;
    6993         594 :                     context = conf->gen.reset_scontext;
    6994             :                 }
    6995             : 
    6996       52414 :                 if (prohibitValueChange)
    6997             :                 {
    6998         264 :                     if (*conf->variable != newval)
    6999             :                     {
    7000           0 :                         record->status |= GUC_PENDING_RESTART;
    7001           0 :                         ereport(elevel,
    7002             :                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    7003             :                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    7004             :                                         name)));
    7005           0 :                         return 0;
    7006             :                     }
    7007         264 :                     record->status &= ~GUC_PENDING_RESTART;
    7008         264 :                     return -1;
    7009             :                 }
    7010             : 
    7011       52150 :                 if (changeVal)
    7012             :                 {
    7013             :                     /* Save old value to support transaction abort */
    7014       52146 :                     if (!makeDefault)
    7015       12826 :                         push_old_value(&conf->gen, action);
    7016             : 
    7017       52146 :                     if (conf->assign_hook)
    7018           0 :                         conf->assign_hook(newval, newextra);
    7019       52146 :                     *conf->variable = newval;
    7020       52146 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    7021             :                                     newextra);
    7022       52146 :                     conf->gen.source = source;
    7023       52146 :                     conf->gen.scontext = context;
    7024             :                 }
    7025       52150 :                 if (makeDefault)
    7026             :                 {
    7027             :                     GucStack   *stack;
    7028             : 
    7029       39320 :                     if (conf->gen.reset_source <= source)
    7030             :                     {
    7031       39320 :                         conf->reset_val = newval;
    7032       39320 :                         set_extra_field(&conf->gen, &conf->reset_extra,
    7033             :                                         newextra);
    7034       39320 :                         conf->gen.reset_source = source;
    7035       39320 :                         conf->gen.reset_scontext = context;
    7036             :                     }
    7037       39320 :                     for (stack = conf->gen.stack; stack; stack = stack->prev)
    7038             :                     {
    7039           0 :                         if (stack->source <= source)
    7040             :                         {
    7041           0 :                             stack->prior.val.boolval = newval;
    7042           0 :                             set_extra_field(&conf->gen, &stack->prior.extra,
    7043             :                                             newextra);
    7044           0 :                             stack->source = source;
    7045           0 :                             stack->scontext = context;
    7046             :                         }
    7047             :                     }
    7048             :                 }
    7049             : 
    7050             :                 /* Perhaps we didn't install newextra anywhere */
    7051       52150 :                 if (newextra && !extra_field_used(&conf->gen, newextra))
    7052           0 :                     free(newextra);
    7053       52150 :                 break;
    7054             : 
    7055             : #undef newval
    7056             :             }
    7057             : 
    7058             :         case PGC_INT:
    7059             :             {
    7060       35862 :                 struct config_int *conf = (struct config_int *) record;
    7061             : 
    7062             : #define newval (newval_union.intval)
    7063             : 
    7064       35862 :                 if (value)
    7065             :                 {
    7066       35782 :                     if (!parse_and_validate_value(record, name, value,
    7067             :                                                   source, elevel,
    7068             :                                                   &newval_union, &newextra))
    7069           0 :                         return 0;
    7070             :                 }
    7071          80 :                 else if (source == PGC_S_DEFAULT)
    7072             :                 {
    7073           0 :                     newval = conf->boot_val;
    7074           0 :                     if (!call_int_check_hook(conf, &newval, &newextra,
    7075             :                                              source, elevel))
    7076           0 :                         return 0;
    7077             :                 }
    7078             :                 else
    7079             :                 {
    7080          80 :                     newval = conf->reset_val;
    7081          80 :                     newextra = conf->reset_extra;
    7082          80 :                     source = conf->gen.reset_source;
    7083          80 :                     context = conf->gen.reset_scontext;
    7084             :                 }
    7085             : 
    7086       35862 :                 if (prohibitValueChange)
    7087             :                 {
    7088         908 :                     if (*conf->variable != newval)
    7089             :                     {
    7090           0 :                         record->status |= GUC_PENDING_RESTART;
    7091           0 :                         ereport(elevel,
    7092             :                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    7093             :                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    7094             :                                         name)));
    7095           0 :                         return 0;
    7096             :                     }
    7097         908 :                     record->status &= ~GUC_PENDING_RESTART;
    7098         908 :                     return -1;
    7099             :                 }
    7100             : 
    7101       34954 :                 if (changeVal)
    7102             :                 {
    7103             :                     /* Save old value to support transaction abort */
    7104       34904 :                     if (!makeDefault)
    7105       11332 :                         push_old_value(&conf->gen, action);
    7106             : 
    7107       34904 :                     if (conf->assign_hook)
    7108        7100 :                         conf->assign_hook(newval, newextra);
    7109       34904 :                     *conf->variable = newval;
    7110       34904 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    7111             :                                     newextra);
    7112       34904 :                     conf->gen.source = source;
    7113       34904 :                     conf->gen.scontext = context;
    7114             :                 }
    7115       34954 :                 if (makeDefault)
    7116             :                 {
    7117             :                     GucStack   *stack;
    7118             : 
    7119       23572 :                     if (conf->gen.reset_source <= source)
    7120             :                     {
    7121       23572 :                         conf->reset_val = newval;
    7122       23572 :                         set_extra_field(&conf->gen, &conf->reset_extra,
    7123             :                                         newextra);
    7124       23572 :                         conf->gen.reset_source = source;
    7125       23572 :                         conf->gen.reset_scontext = context;
    7126             :                     }
    7127       23572 :                     for (stack = conf->gen.stack; stack; stack = stack->prev)
    7128             :                     {
    7129           0 :                         if (stack->source <= source)
    7130             :                         {
    7131           0 :                             stack->prior.val.intval = newval;
    7132           0 :                             set_extra_field(&conf->gen, &stack->prior.extra,
    7133             :                                             newextra);
    7134           0 :                             stack->source = source;
    7135           0 :                             stack->scontext = context;
    7136             :                         }
    7137             :                     }
    7138             :                 }
    7139             : 
    7140             :                 /* Perhaps we didn't install newextra anywhere */
    7141       34954 :                 if (newextra && !extra_field_used(&conf->gen, newextra))
    7142           0 :                     free(newextra);
    7143       34954 :                 break;
    7144             : 
    7145             : #undef newval
    7146             :             }
    7147             : 
    7148             :         case PGC_REAL:
    7149             :             {
    7150        3228 :                 struct config_real *conf = (struct config_real *) record;
    7151             : 
    7152             : #define newval (newval_union.realval)
    7153             : 
    7154        3228 :                 if (value)
    7155             :                 {
    7156        3194 :                     if (!parse_and_validate_value(record, name, value,
    7157             :                                                   source, elevel,
    7158             :                                                   &newval_union, &newextra))
    7159           0 :                         return 0;
    7160             :                 }
    7161          34 :                 else if (source == PGC_S_DEFAULT)
    7162             :                 {
    7163           0 :                     newval = conf->boot_val;
    7164           0 :                     if (!call_real_check_hook(conf, &newval, &newextra,
    7165             :                                               source, elevel))
    7166           0 :                         return 0;
    7167             :                 }
    7168             :                 else
    7169             :                 {
    7170          34 :                     newval = conf->reset_val;
    7171          34 :                     newextra = conf->reset_extra;
    7172          34 :                     source = conf->gen.reset_source;
    7173          34 :                     context = conf->gen.reset_scontext;
    7174             :                 }
    7175             : 
    7176        3220 :                 if (prohibitValueChange)
    7177             :                 {
    7178           0 :                     if (*conf->variable != newval)
    7179             :                     {
    7180           0 :                         record->status |= GUC_PENDING_RESTART;
    7181           0 :                         ereport(elevel,
    7182             :                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    7183             :                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    7184             :                                         name)));
    7185           0 :                         return 0;
    7186             :                     }
    7187           0 :                     record->status &= ~GUC_PENDING_RESTART;
    7188           0 :                     return -1;
    7189             :                 }
    7190             : 
    7191        3220 :                 if (changeVal)
    7192             :                 {
    7193             :                     /* Save old value to support transaction abort */
    7194        3220 :                     if (!makeDefault)
    7195        3216 :                         push_old_value(&conf->gen, action);
    7196             : 
    7197        3220 :                     if (conf->assign_hook)
    7198           0 :                         conf->assign_hook(newval, newextra);
    7199        3220 :                     *conf->variable = newval;
    7200        3220 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    7201             :                                     newextra);
    7202        3220 :                     conf->gen.source = source;
    7203        3220 :                     conf->gen.scontext = context;
    7204             :                 }
    7205        3220 :                 if (makeDefault)
    7206             :                 {
    7207             :                     GucStack   *stack;
    7208             : 
    7209           4 :                     if (conf->gen.reset_source <= source)
    7210             :                     {
    7211           4 :                         conf->reset_val = newval;
    7212           4 :                         set_extra_field(&conf->gen, &conf->reset_extra,
    7213             :                                         newextra);
    7214           4 :                         conf->gen.reset_source = source;
    7215           4 :                         conf->gen.reset_scontext = context;
    7216             :                     }
    7217           4 :                     for (stack = conf->gen.stack; stack; stack = stack->prev)
    7218             :                     {
    7219           0 :                         if (stack->source <= source)
    7220             :                         {
    7221           0 :                             stack->prior.val.realval = newval;
    7222           0 :                             set_extra_field(&conf->gen, &stack->prior.extra,
    7223             :                                             newextra);
    7224           0 :                             stack->source = source;
    7225           0 :                             stack->scontext = context;
    7226             :                         }
    7227             :                     }
    7228             :                 }
    7229             : 
    7230             :                 /* Perhaps we didn't install newextra anywhere */
    7231        3220 :                 if (newextra && !extra_field_used(&conf->gen, newextra))
    7232           0 :                     free(newextra);
    7233        3220 :                 break;
    7234             : 
    7235             : #undef newval
    7236             :             }
    7237             : 
    7238             :         case PGC_STRING:
    7239             :             {
    7240      135594 :                 struct config_string *conf = (struct config_string *) record;
    7241             : 
    7242             : #define newval (newval_union.stringval)
    7243             : 
    7244      135594 :                 if (value)
    7245             :                 {
    7246      134646 :                     if (!parse_and_validate_value(record, name, value,
    7247             :                                                   source, elevel,
    7248             :                                                   &newval_union, &newextra))
    7249           0 :                         return 0;
    7250             :                 }
    7251         948 :                 else if (source == PGC_S_DEFAULT)
    7252             :                 {
    7253             :                     /* non-NULL boot_val must always get strdup'd */
    7254           0 :                     if (conf->boot_val != NULL)
    7255             :                     {
    7256           0 :                         newval = guc_strdup(elevel, conf->boot_val);
    7257           0 :                         if (newval == NULL)
    7258           0 :                             return 0;
    7259             :                     }
    7260             :                     else
    7261           0 :                         newval = NULL;
    7262             : 
    7263           0 :                     if (!call_string_check_hook(conf, &newval, &newextra,
    7264             :                                                 source, elevel))
    7265             :                     {
    7266           0 :                         free(newval);
    7267           0 :                         return 0;
    7268             :                     }
    7269             :                 }
    7270             :                 else
    7271             :                 {
    7272             :                     /*
    7273             :                      * strdup not needed, since reset_val is already under
    7274             :                      * guc.c's control
    7275             :                      */
    7276         948 :                     newval = conf->reset_val;
    7277         948 :                     newextra = conf->reset_extra;
    7278         948 :                     source = conf->gen.reset_source;
    7279         948 :                     context = conf->gen.reset_scontext;
    7280             :                 }
    7281             : 
    7282      135574 :                 if (prohibitValueChange)
    7283             :                 {
    7284             :                     /* newval shouldn't be NULL, so we're a bit sloppy here */
    7285         860 :                     if (*conf->variable == NULL || newval == NULL ||
    7286         430 :                         strcmp(*conf->variable, newval) != 0)
    7287             :                     {
    7288           0 :                         record->status |= GUC_PENDING_RESTART;
    7289           0 :                         ereport(elevel,
    7290             :                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    7291             :                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    7292             :                                         name)));
    7293           0 :                         return 0;
    7294             :                     }
    7295         430 :                     record->status &= ~GUC_PENDING_RESTART;
    7296         430 :                     return -1;
    7297             :                 }
    7298             : 
    7299      135144 :                 if (changeVal)
    7300             :                 {
    7301             :                     /* Save old value to support transaction abort */
    7302      133580 :                     if (!makeDefault)
    7303       10870 :                         push_old_value(&conf->gen, action);
    7304             : 
    7305      133580 :                     if (conf->assign_hook)
    7306       96742 :                         conf->assign_hook(newval, newextra);
    7307      133578 :                     set_string_field(conf, conf->variable, newval);
    7308      133578 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    7309             :                                     newextra);
    7310      133578 :                     conf->gen.source = source;
    7311      133578 :                     conf->gen.scontext = context;
    7312             :                 }
    7313             : 
    7314      135142 :                 if (makeDefault)
    7315             :                 {
    7316             :                     GucStack   *stack;
    7317             : 
    7318      123480 :                     if (conf->gen.reset_source <= source)
    7319             :                     {
    7320      122708 :                         set_string_field(conf, &conf->reset_val, newval);
    7321      122708 :                         set_extra_field(&conf->gen, &conf->reset_extra,
    7322             :                                         newextra);
    7323      122708 :                         conf->gen.reset_source = source;
    7324      122708 :                         conf->gen.reset_scontext = context;
    7325             :                     }
    7326      123480 :                     for (stack = conf->gen.stack; stack; stack = stack->prev)
    7327             :                     {
    7328           0 :                         if (stack->source <= source)
    7329             :                         {
    7330           0 :                             set_string_field(conf, &stack->prior.val.stringval,
    7331             :                                              newval);
    7332           0 :                             set_extra_field(&conf->gen, &stack->prior.extra,
    7333             :                                             newextra);
    7334           0 :                             stack->source = source;
    7335           0 :                             stack->scontext = context;
    7336             :                         }
    7337             :                     }
    7338             :                 }
    7339             : 
    7340             :                 /* Perhaps we didn't install newval anywhere */
    7341      135142 :                 if (newval && !string_field_used(conf, newval))
    7342        1544 :                     free(newval);
    7343             :                 /* Perhaps we didn't install newextra anywhere */
    7344      135142 :                 if (newextra && !extra_field_used(&conf->gen, newextra))
    7345         910 :                     free(newextra);
    7346      135142 :                 break;
    7347             : 
    7348             : #undef newval
    7349             :             }
    7350             : 
    7351             :         case PGC_ENUM:
    7352             :             {
    7353       29618 :                 struct config_enum *conf = (struct config_enum *) record;
    7354             : 
    7355             : #define newval (newval_union.enumval)
    7356             : 
    7357       29618 :                 if (value)
    7358             :                 {
    7359       29494 :                     if (!parse_and_validate_value(record, name, value,
    7360             :                                                   source, elevel,
    7361             :                                                   &newval_union, &newextra))
    7362           0 :                         return 0;
    7363             :                 }
    7364         124 :                 else if (source == PGC_S_DEFAULT)
    7365             :                 {
    7366           0 :                     newval = conf->boot_val;
    7367           0 :                     if (!call_enum_check_hook(conf, &newval, &newextra,
    7368             :                                               source, elevel))
    7369           0 :                         return 0;
    7370             :                 }
    7371             :                 else
    7372             :                 {
    7373         124 :                     newval = conf->reset_val;
    7374         124 :                     newextra = conf->reset_extra;
    7375         124 :                     source = conf->gen.reset_source;
    7376         124 :                     context = conf->gen.reset_scontext;
    7377             :                 }
    7378             : 
    7379       29608 :                 if (prohibitValueChange)
    7380             :                 {
    7381         354 :                     if (*conf->variable != newval)
    7382             :                     {
    7383           0 :                         record->status |= GUC_PENDING_RESTART;
    7384           0 :                         ereport(elevel,
    7385             :                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    7386             :                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    7387             :                                         name)));
    7388           0 :                         return 0;
    7389             :                     }
    7390         354 :                     record->status &= ~GUC_PENDING_RESTART;
    7391         354 :                     return -1;
    7392             :                 }
    7393             : 
    7394       29254 :                 if (changeVal)
    7395             :                 {
    7396             :                     /* Save old value to support transaction abort */
    7397       29114 :                     if (!makeDefault)
    7398       12344 :                         push_old_value(&conf->gen, action);
    7399             : 
    7400       29114 :                     if (conf->assign_hook)
    7401         526 :                         conf->assign_hook(newval, newextra);
    7402       29114 :                     *conf->variable = newval;
    7403       29114 :                     set_extra_field(&conf->gen, &conf->gen.extra,
    7404             :                                     newextra);
    7405       29114 :                     conf->gen.source = source;
    7406       29114 :                     conf->gen.scontext = context;
    7407             :                 }
    7408       29254 :                 if (makeDefault)
    7409             :                 {
    7410             :                     GucStack   *stack;
    7411             : 
    7412       16770 :                     if (conf->gen.reset_source <= source)
    7413             :                     {
    7414       16770 :                         conf->reset_val = newval;
    7415       16770 :                         set_extra_field(&conf->gen, &conf->reset_extra,
    7416             :                                         newextra);
    7417       16770 :                         conf->gen.reset_source = source;
    7418       16770 :                         conf->gen.reset_scontext = context;
    7419             :                     }
    7420       16770 :                     for (stack = conf->gen.stack; stack; stack = stack->prev)
    7421             :                     {
    7422           0 :                         if (stack->source <= source)
    7423             :                         {
    7424           0 :                             stack->prior.val.enumval = newval;
    7425           0 :                             set_extra_field(&conf->gen, &stack->prior.extra,
    7426             :                                             newextra);
    7427           0 :                             stack->source = source;
    7428           0 :                             stack->scontext = context;
    7429             :                         }
    7430             :                     }
    7431             :                 }
    7432             : 
    7433             :                 /* Perhaps we didn't install newextra anywhere */
    7434       29254 :                 if (newextra && !extra_field_used(&conf->gen, newextra))
    7435           0 :                     free(newextra);
    7436       29254 :                 break;
    7437             : 
    7438             : #undef newval
    7439             :             }
    7440             :     }
    7441             : 
    7442      254720 :     if (changeVal && (record->flags & GUC_REPORT))
    7443       89130 :         ReportGUCOption(record);
    7444             : 
    7445      254720 :     return changeVal ? 1 : -1;
    7446             : }
    7447             : 
    7448             : 
    7449             : /*
    7450             :  * Set the fields for source file and line number the setting came from.
    7451             :  */
    7452             : static void
    7453       49688 : set_config_sourcefile(const char *name, char *sourcefile, int sourceline)
    7454             : {
    7455             :     struct config_generic *record;
    7456             :     int         elevel;
    7457             : 
    7458             :     /*
    7459             :      * To avoid cluttering the log, only the postmaster bleats loudly about
    7460             :      * problems with the config file.
    7461             :      */
    7462       49688 :     elevel = IsUnderPostmaster ? DEBUG3 : LOG;
    7463             : 
    7464       49688 :     record = find_option(name, true, elevel);
    7465             :     /* should not happen */
    7466       49688 :     if (record == NULL)
    7467           0 :         elog(ERROR, "unrecognized configuration parameter \"%s\"", name);
    7468             : 
    7469       49688 :     sourcefile = guc_strdup(elevel, sourcefile);
    7470       49688 :     if (record->sourcefile)
    7471        5164 :         free(record->sourcefile);
    7472       49688 :     record->sourcefile = sourcefile;
    7473       49688 :     record->sourceline = sourceline;
    7474       49688 : }
    7475             : 
    7476             : /*
    7477             :  * Set a config option to the given value.
    7478             :  *
    7479             :  * See also set_config_option; this is just the wrapper to be called from
    7480             :  * outside GUC.  (This function should be used when possible, because its API
    7481             :  * is more stable than set_config_option's.)
    7482             :  *
    7483             :  * Note: there is no support here for setting source file/line, as it
    7484             :  * is currently not needed.
    7485             :  */
    7486             : void
    7487      112924 : SetConfigOption(const char *name, const char *value,
    7488             :                 GucContext context, GucSource source)
    7489             : {
    7490      112924 :     (void) set_config_option(name, value, context, source,
    7491             :                              GUC_ACTION_SET, true, 0, false);
    7492      112924 : }
    7493             : 
    7494             : 
    7495             : 
    7496             : /*
    7497             :  * Fetch the current value of the option `name', as a string.
    7498             :  *
    7499             :  * If the option doesn't exist, return NULL if missing_ok is true (NOTE that
    7500             :  * this cannot be distinguished from a string variable with a NULL value!),
    7501             :  * otherwise throw an ereport and don't return.
    7502             :  *
    7503             :  * If restrict_privileged is true, we also enforce that only superusers and
    7504             :  * members of the pg_read_all_settings role can see GUC_SUPERUSER_ONLY
    7505             :  * variables.  This should only be passed as true in user-driven calls.
    7506             :  *
    7507             :  * The string is *not* allocated for modification and is really only
    7508             :  * valid until the next call to configuration related functions.
    7509             :  */
    7510             : const char *
    7511        2354 : GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
    7512             : {
    7513             :     struct config_generic *record;
    7514             :     static char buffer[256];
    7515             : 
    7516        2354 :     record = find_option(name, false, ERROR);
    7517        2354 :     if (record == NULL)
    7518             :     {
    7519           0 :         if (missing_ok)
    7520           0 :             return NULL;
    7521           0 :         ereport(ERROR,
    7522             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    7523             :                  errmsg("unrecognized configuration parameter \"%s\"",
    7524             :                         name)));
    7525             :     }
    7526        2354 :     if (restrict_privileged &&
    7527           0 :         (record->flags & GUC_SUPERUSER_ONLY) &&
    7528           0 :         !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))
    7529           0 :         ereport(ERROR,
    7530             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    7531             :                  errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"",
    7532             :                         name)));
    7533             : 
    7534        2354 :     switch (record->vartype)
    7535             :     {
    7536             :         case PGC_BOOL:
    7537         384 :             return *((struct config_bool *) record)->variable ? "on" : "off";
    7538             : 
    7539             :         case PGC_INT:
    7540         538 :             snprintf(buffer, sizeof(buffer), "%d",
    7541         538 :                      *((struct config_int *) record)->variable);
    7542         538 :             return buffer;
    7543             : 
    7544             :         case PGC_REAL:
    7545           0 :             snprintf(buffer, sizeof(buffer), "%g",
    7546           0 :                      *((struct config_real *) record)->variable);
    7547           0 :             return buffer;
    7548             : 
    7549             :         case PGC_STRING:
    7550        1182 :             return *((struct config_string *) record)->variable;
    7551             : 
    7552             :         case PGC_ENUM:
    7553         250 :             return config_enum_lookup_by_value((struct config_enum *) record,
    7554         250 :                                                *((struct config_enum *) record)->variable);
    7555             :     }
    7556           0 :     return NULL;
    7557             : }
    7558             : 
    7559             : /*
    7560             :  * Get the RESET value associated with the given option.
    7561             :  *
    7562             :  * Note: this is not re-entrant, due to use of static result buffer;
    7563             :  * not to mention that a string variable could have its reset_val changed.
    7564             :  * Beware of assuming the result value is good for very long.
    7565             :  */
    7566             : const char *
    7567           0 : GetConfigOptionResetString(const char *name)
    7568             : {
    7569             :     struct config_generic *record;
    7570             :     static char buffer[256];
    7571             : 
    7572           0 :     record = find_option(name, false, ERROR);
    7573           0 :     if (record == NULL)
    7574           0 :         ereport(ERROR,
    7575             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    7576             :                  errmsg("unrecognized configuration parameter \"%s\"", name)));
    7577           0 :     if ((record->flags & GUC_SUPERUSER_ONLY) &&
    7578           0 :         !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))
    7579           0 :         ereport(ERROR,
    7580             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    7581             :                  errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"",
    7582             :                         name)));
    7583             : 
    7584           0 :     switch (record->vartype)
    7585             :     {
    7586             :         case PGC_BOOL:
    7587           0 :             return ((struct config_bool *) record)->reset_val ? "on" : "off";
    7588             : 
    7589             :         case PGC_INT:
    7590           0 :             snprintf(buffer, sizeof(buffer), "%d",
    7591             :                      ((struct config_int *) record)->reset_val);
    7592           0 :             return buffer;
    7593             : 
    7594             :         case PGC_REAL:
    7595           0 :             snprintf(buffer, sizeof(buffer), "%g",
    7596             :                      ((struct config_real *) record)->reset_val);
    7597           0 :             return buffer;
    7598             : 
    7599             :         case PGC_STRING:
    7600           0 :             return ((struct config_string *) record)->reset_val;
    7601             : 
    7602             :         case PGC_ENUM:
    7603           0 :             return config_enum_lookup_by_value((struct config_enum *) record,
    7604             :                                                ((struct config_enum *) record)->reset_val);
    7605             :     }
    7606           0 :     return NULL;
    7607             : }
    7608             : 
    7609             : /*
    7610             :  * Get the GUC flags associated with the given option.
    7611             :  *
    7612             :  * If the option doesn't exist, return 0 if missing_ok is true,
    7613             :  * otherwise throw an ereport and don't return.
    7614             :  */
    7615             : int
    7616          20 : GetConfigOptionFlags(const char *name, bool missing_ok)
    7617             : {
    7618             :     struct config_generic *record;
    7619             : 
    7620          20 :     record = find_option(name, false, WARNING);
    7621          20 :     if (record == NULL)
    7622             :     {
    7623           0 :         if (missing_ok)
    7624           0 :             return 0;
    7625           0 :         ereport(ERROR,
    7626             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    7627             :                  errmsg("unrecognized configuration parameter \"%s\"",
    7628             :                         name)));
    7629             :     }
    7630          20 :     return record->flags;
    7631             : }
    7632             : 
    7633             : 
    7634             : /*
    7635             :  * flatten_set_variable_args
    7636             :  *      Given a parsenode List as emitted by the grammar for SET,
    7637             :  *      convert to the flat string representation used by GUC.
    7638             :  *
    7639             :  * We need to be told the name of the variable the args are for, because
    7640             :  * the flattening rules vary (ugh).
    7641             :  *
    7642             :  * The result is NULL if args is NIL (i.e., SET ... TO DEFAULT), otherwise
    7643             :  * a palloc'd string.
    7644             :  */
    7645             : static char *
    7646       20154 : flatten_set_variable_args(const char *name, List *args)
    7647             : {
    7648             :     struct config_generic *record;
    7649             :     int         flags;
    7650             :     StringInfoData buf;
    7651             :     ListCell   *l;
    7652             : 
    7653             :     /* Fast path if just DEFAULT */
    7654       20154 :     if (args == NIL)
    7655           4 :         return NULL;
    7656             : 
    7657             :     /*
    7658             :      * Get flags for the variable; if it's not known, use default flags.
    7659             :      * (Caller might throw error later, but not our business to do so here.)
    7660             :      */
    7661       20150 :     record = find_option(name, false, WARNING);
    7662       20150 :     if (record)
    7663       20138 :         flags = record->flags;
    7664             :     else
    7665          12 :         flags = 0;
    7666             : 
    7667             :     /* Complain if list input and non-list variable */
    7668       39010 :     if ((flags & GUC_LIST_INPUT) == 0 &&
    7669       18860 :         list_length(args) != 1)
    7670           0 :         ereport(ERROR,
    7671             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    7672             :                  errmsg("SET %s takes only one argument", name)));
    7673             : 
    7674       20150 :     initStringInfo(&buf);
    7675             : 
    7676             :     /*
    7677             :      * Each list member may be a plain A_Const node, or an A_Const within a
    7678             :      * TypeCast; the latter case is supported only for ConstInterval arguments
    7679             :      * (for SET TIME ZONE).
    7680             :      */
    7681       40378 :     foreach(l, args)
    7682             :     {
    7683       20228 :         Node       *arg = (Node *) lfirst(l);
    7684             :         char       *val;
    7685       20228 :         TypeName   *typeName = NULL;
    7686             :         A_Const    *con;
    7687             : 
    7688       20228 :         if (l != list_head(args))
    7689          78 :             appendStringInfoString(&buf, ", ");
    7690             : 
    7691       20228 :         if (IsA(arg, TypeCast))
    7692             :         {
    7693           0 :             TypeCast   *tc = (TypeCast *) arg;
    7694             : 
    7695           0 :             arg = tc->arg;
    7696           0 :             typeName = tc->typeName;
    7697             :         }
    7698             : 
    7699       20228 :         if (!IsA(arg, A_Const))
    7700           0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
    7701       20228 :         con = (A_Const *) arg;
    7702             : 
    7703       20228 :         switch (nodeTag(&con->val))
    7704             :         {
    7705             :             case T_Integer:
    7706        6406 :                 appendStringInfo(&buf, "%d", intVal(&con->val));
    7707        6406 :                 break;
    7708             :             case T_Float:
    7709             :                 /* represented as a string, so just copy it */
    7710          92 :                 appendStringInfoString(&buf, strVal(&con->val));
    7711          92 :                 break;
    7712             :             case T_String:
    7713       13730 :                 val = strVal(&con->val);
    7714       13730 :                 if (typeName != NULL)
    7715             :                 {
    7716             :                     /*
    7717             :                      * Must be a ConstInterval argument for TIME ZONE. Coerce
    7718             :                      * to interval and back to normalize the value and account
    7719             :                      * for any typmod.
    7720             :                      */
    7721             :                     Oid         typoid;
    7722             :                     int32       typmod;
    7723             :                     Datum       interval;
    7724             :                     char       *intervalout;
    7725             : 
    7726           0 :                     typenameTypeIdAndMod(NULL, typeName, &typoid, &typmod);
    7727             :                     Assert(typoid == INTERVALOID);
    7728             : 
    7729           0 :                     interval =
    7730           0 :                         DirectFunctionCall3(interval_in,
    7731             :                                             CStringGetDatum(val),
    7732             :                                             ObjectIdGetDatum(InvalidOid),
    7733             :                                             Int32GetDatum(typmod));
    7734             : 
    7735           0 :                     intervalout =
    7736           0 :                         DatumGetCString(DirectFunctionCall1(interval_out,
    7737             :                                                             interval));
    7738           0 :                     appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
    7739             :                 }
    7740             :                 else
    7741             :                 {
    7742             :                     /*
    7743             :                      * Plain string literal or identifier.  For quote mode,
    7744             :                      * quote it if it's not a vanilla identifier.
    7745             :                      */
    7746       13730 :                     if (flags & GUC_LIST_QUOTE)
    7747         880 :                         appendStringInfoString(&buf, quote_identifier(val));
    7748             :                     else
    7749       12850 :                         appendStringInfoString(&buf, val);
    7750             :                 }
    7751       13730 :                 break;
    7752             :             default:
    7753           0 :                 elog(ERROR, "unrecognized node type: %d",
    7754             :                      (int) nodeTag(&con->val));
    7755             :                 break;
    7756             :         }
    7757             :     }
    7758             : 
    7759       20150 :     return buf.data;
    7760             : }
    7761             : 
    7762             : /*
    7763             :  * Write updated configuration parameter values into a temporary file.
    7764             :  * This function traverses the list of parameters and quotes the string
    7765             :  * values before writing them.
    7766             :  */
    7767             : static void
    7768          30 : write_auto_conf_file(int fd, const char *filename, ConfigVariable *head)
    7769             : {
    7770             :     StringInfoData buf;
    7771             :     ConfigVariable *item;
    7772             : 
    7773          30 :     initStringInfo(&buf);
    7774             : 
    7775             :     /* Emit file header containing warning comment */
    7776          30 :     appendStringInfoString(&buf, "# Do not edit this file manually!\n");
    7777          30 :     appendStringInfoString(&buf, "# It will be overwritten by the ALTER SYSTEM command.\n");
    7778             : 
    7779          30 :     errno = 0;
    7780          30 :     if (write(fd, buf.data, buf.len) != buf.len)
    7781             :     {
    7782             :         /* if write didn't set errno, assume problem is no disk space */
    7783           0 :         if (errno == 0)
    7784           0 :             errno = ENOSPC;
    7785           0 :         ereport(ERROR,
    7786             :                 (errcode_for_file_access(),
    7787             :                  errmsg("could not write to file \"%s\": %m", filename)));
    7788             :     }
    7789             : 
    7790             :     /* Emit each parameter, properly quoting the value */
    7791          62 :     for (item = head; item != NULL; item = item->next)
    7792             :     {
    7793             :         char       *escaped;
    7794             : 
    7795          32 :         resetStringInfo(&buf);
    7796             : 
    7797          32 :         appendStringInfoString(&buf, item->name);
    7798          32 :         appendStringInfoString(&buf, " = '");
    7799             : 
    7800          32 :         escaped = escape_single_quotes_ascii(item->value);
    7801          32 :         if (!escaped)
    7802           0 :             ereport(ERROR,
    7803             :                     (errcode(ERRCODE_OUT_OF_MEMORY),
    7804             :                      errmsg("out of memory")));
    7805          32 :         appendStringInfoString(&buf, escaped);
    7806          32 :         free(escaped);
    7807             : 
    7808          32 :         appendStringInfoString(&buf, "'\n");
    7809             : 
    7810          32 :         errno = 0;
    7811          32 :         if (write(fd, buf.data, buf.len) != buf.len)
    7812             :         {
    7813             :             /* if write didn't set errno, assume problem is no disk space */
    7814           0 :             if (errno == 0)
    7815           0 :                 errno = ENOSPC;
    7816           0 :             ereport(ERROR,
    7817             :                     (errcode_for_file_access(),
    7818             :                      errmsg("could not write to file \"%s\": %m", filename)));
    7819             :         }
    7820             :     }
    7821             : 
    7822             :     /* fsync before considering the write to be successful */
    7823          30 :     if (pg_fsync(fd) != 0)
    7824           0 :         ereport(ERROR,
    7825             :                 (errcode_for_file_access(),
    7826             :                  errmsg("could not fsync file \"%s\": %m", filename)));
    7827             : 
    7828          30 :     pfree(buf.data);
    7829          30 : }
    7830             : 
    7831             : /*
    7832             :  * Update the given list of configuration parameters, adding, replacing
    7833             :  * or deleting the entry for item "name" (delete if "value" == NULL).
    7834             :  */
    7835             : static void
    7836          30 : replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
    7837             :                           const char *name, const char *value)
    7838             : {
    7839             :     ConfigVariable *item,
    7840             :                *next,
    7841          30 :                *prev = NULL;
    7842             : 
    7843             :     /*
    7844             :      * Remove any existing match(es) for "name".  Normally there'd be at most
    7845             :      * one, but if external tools have modified the config file, there could
    7846             :      * be more.
    7847             :      */
    7848          52 :     for (item = *head_p; item != NULL; item = next)
    7849             :     {
    7850          22 :         next = item->next;
    7851          22 :         if (guc_name_compare(item->name, name) == 0)
    7852             :         {
    7853             :             /* found a match, delete it */
    7854          20 :             if (prev)
    7855           0 :                 prev->next = next;
    7856             :             else
    7857          20 :                 *head_p = next;
    7858          20 :             if (next == NULL)
    7859          20 :                 *tail_p = prev;
    7860             : 
    7861          20 :             pfree(item->name);
    7862          20 :             pfree(item->value);
    7863          20 :             pfree(item->filename);
    7864          20 :             pfree(item);
    7865             :         }
    7866             :         else
    7867           2 :             prev = item;
    7868             :     }
    7869             : 
    7870             :     /* Done if we're trying to delete it */
    7871          30 :     if (value == NULL)
    7872           0 :         return;
    7873             : 
    7874             :     /* OK, append a new entry */
    7875          30 :     item = palloc(sizeof *item);
    7876          30 :     item->name = pstrdup(name);
    7877          30 :     item->value = pstrdup(value);
    7878          30 :     item->errmsg = NULL;
    7879          30 :     item->filename = pstrdup("");  /* new item has no location */
    7880          30 :     item->sourceline = 0;
    7881          30 :     item->ignore = false;
    7882          30 :     item->applied = false;
    7883          30 :     item->next = NULL;
    7884             : 
    7885          30 :     if (*head_p == NULL)
    7886          28 :         *head_p = item;
    7887             :     else
    7888           2 :         (*tail_p)->next = item;
    7889          30 :     *tail_p = item;
    7890             : }
    7891             : 
    7892             : 
    7893             : /*
    7894             :  * Execute ALTER SYSTEM statement.
    7895             :  *
    7896             :  * Read the old PG_AUTOCONF_FILENAME file, merge in the new variable value,
    7897             :  * and write out an updated file.  If the command is ALTER SYSTEM RESET ALL,
    7898             :  * we can skip reading the old file and just write an empty file.
    7899             :  *
    7900             :  * An LWLock is used to serialize updates of the configuration file.
    7901             :  *
    7902             :  * In case of an error, we leave the original automatic
    7903             :  * configuration file (PG_AUTOCONF_FILENAME) intact.
    7904             :  */
    7905             : void
    7906          30 : AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
    7907             : {
    7908             :     char       *name;
    7909             :     char       *value;
    7910          30 :     bool        resetall = false;
    7911          30 :     ConfigVariable *head = NULL;
    7912          30 :     ConfigVariable *tail = NULL;
    7913             :     volatile int Tmpfd;
    7914             :     char        AutoConfFileName[MAXPGPATH];
    7915             :     char        AutoConfTmpFileName[MAXPGPATH];
    7916             : 
    7917          30 :     if (!superuser())
    7918           0 :         ereport(ERROR,
    7919             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    7920             :                  (errmsg("must be superuser to execute ALTER SYSTEM command"))));
    7921             : 
    7922             :     /*
    7923             :      * Extract statement arguments
    7924             :      */
    7925          30 :     name = altersysstmt->setstmt->name;
    7926             : 
    7927          30 :     switch (altersysstmt->setstmt->kind)
    7928             :     {
    7929             :         case VAR_SET_VALUE:
    7930          30 :             value = ExtractSetVariableArgs(altersysstmt->setstmt);
    7931          30 :             break;
    7932             : 
    7933             :         case VAR_SET_DEFAULT:
    7934             :         case VAR_RESET:
    7935           0 :             value = NULL;
    7936           0 :             break;
    7937             : 
    7938             :         case VAR_RESET_ALL:
    7939           0 :             value = NULL;
    7940           0 :             resetall = true;
    7941           0 :             break;
    7942             : 
    7943             :         default:
    7944           0 :             elog(ERROR, "unrecognized alter system stmt type: %d",
    7945             :                  altersysstmt->setstmt->kind);
    7946             :             break;
    7947             :     }
    7948             : 
    7949             :     /*
    7950             :      * Unless it's RESET_ALL, validate the target variable and value
    7951             :      */
    7952          30 :     if (!resetall)
    7953             :     {
    7954             :         struct config_generic *record;
    7955             : 
    7956          30 :         record = find_option(name, false, ERROR);
    7957          30 :         if (record == NULL)
    7958           0 :             ereport(ERROR,
    7959             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    7960             :                      errmsg("unrecognized configuration parameter \"%s\"",
    7961             :                             name)));
    7962             : 
    7963             :         /*
    7964             :          * Don't allow parameters that can't be set in configuration files to
    7965             :          * be set in PG_AUTOCONF_FILENAME file.
    7966             :          */
    7967          60 :         if ((record->context == PGC_INTERNAL) ||
    7968          60 :             (record->flags & GUC_DISALLOW_IN_FILE) ||
    7969          30 :             (record->flags & GUC_DISALLOW_IN_AUTO_FILE))
    7970           0 :             ereport(ERROR,
    7971             :                     (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    7972             :                      errmsg("parameter \"%s\" cannot be changed",
    7973             :                             name)));
    7974             : 
    7975             :         /*
    7976             :          * If a value is specified, verify that it's sane.
    7977             :          */
    7978          30 :         if (value)
    7979             :         {
    7980             :             union config_var_val newval;
    7981          30 :             void       *newextra = NULL;
    7982             : 
    7983             :             /* Check that it's acceptable for the indicated parameter */
    7984          30 :             if (!parse_and_validate_value(record, name, value,
    7985             :                                           PGC_S_FILE, ERROR,
    7986             :                                           &newval, &newextra))
    7987           0 :                 ereport(ERROR,
    7988             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    7989             :                          errmsg("invalid value for parameter \"%s\": \"%s\"",
    7990             :                                 name, value)));
    7991             : 
    7992          30 :             if (record->vartype == PGC_STRING && newval.stringval != NULL)
    7993          18 :                 free(newval.stringval);
    7994          30 :             if (newextra)
    7995          18 :                 free(newextra);
    7996             : 
    7997             :             /*
    7998             :              * We must also reject values containing newlines, because the
    7999             :              * grammar for config files doesn't support embedded newlines in
    8000             :              * string literals.
    8001             :              */
    8002          30 :             if (strchr(value, '\n'))
    8003           0 :                 ereport(ERROR,
    8004             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    8005             :                          errmsg("parameter value for ALTER SYSTEM must not contain a newline")));
    8006             :         }
    8007             :     }
    8008             : 
    8009             :     /*
    8010             :      * PG_AUTOCONF_FILENAME and its corresponding temporary file are always in
    8011             :      * the data directory, so we can reference them by simple relative paths.
    8012             :      */
    8013          30 :     snprintf(AutoConfFileName, sizeof(AutoConfFileName), "%s",
    8014             :              PG_AUTOCONF_FILENAME);
    8015          30 :     snprintf(AutoConfTmpFileName, sizeof(AutoConfTmpFileName), "%s.%s",
    8016             :              AutoConfFileName,
    8017             :              "tmp");
    8018             : 
    8019             :     /*
    8020             :      * Only one backend is allowed to operate on PG_AUTOCONF_FILENAME at a
    8021             :      * time.  Use AutoFileLock to ensure that.  We must hold the lock while
    8022             :      * reading the old file contents.
    8023             :      */
    8024          30 :     LWLockAcquire(AutoFileLock, LW_EXCLUSIVE);
    8025             : 
    8026             :     /*
    8027             :      * If we're going to reset everything, then no need to open or parse the
    8028             :      * old file.  We'll just write out an empty list.
    8029             :      */
    8030          30 :     if (!resetall)
    8031             :     {
    8032             :         struct stat st;
    8033             : 
    8034          30 :         if (stat(AutoConfFileName, &st) == 0)
    8035             :         {
    8036             :             /* open old file PG_AUTOCONF_FILENAME */
    8037             :             FILE       *infile;
    8038             : 
    8039          30 :             infile = AllocateFile(AutoConfFileName, "r");
    8040          30 :             if (infile == NULL)
    8041           0 :                 ereport(ERROR,
    8042             :                         (errcode_for_file_access(),
    8043             :                          errmsg("could not open file \"%s\": %m",
    8044             :                                 AutoConfFileName)));
    8045             : 
    8046             :             /* parse it */
    8047          30 :             if (!ParseConfigFp(infile, AutoConfFileName, 0, LOG, &head, &tail))
    8048           0 :                 ereport(ERROR,
    8049             :                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
    8050             :                          errmsg("could not parse contents of file \"%s\"",
    8051             :                                 AutoConfFileName)));
    8052             : 
    8053          30 :             FreeFile(infile);
    8054             :         }
    8055             : 
    8056             :         /*
    8057             :          * Now, replace any existing entry with the new value, or add it if
    8058             :          * not present.
    8059             :          */
    8060          30 :         replace_auto_config_value(&head, &tail, name, value);
    8061             :     }
    8062             : 
    8063             :     /*
    8064             :      * To ensure crash safety, first write the new file data to a temp file,
    8065             :      * then atomically rename it into place.
    8066             :      *
    8067             :      * If there is a temp file left over due to a previous crash, it's okay to
    8068             :      * truncate and reuse it.
    8069             :      */
    8070          30 :     Tmpfd = BasicOpenFile(AutoConfTmpFileName,
    8071             :                           O_CREAT | O_RDWR | O_TRUNC);
    8072          30 :     if (Tmpfd < 0)
    8073           0 :         ereport(ERROR,
    8074             :                 (errcode_for_file_access(),
    8075             :                  errmsg("could not open file \"%s\": %m",
    8076             :                         AutoConfTmpFileName)));
    8077             : 
    8078             :     /*
    8079             :      * Use a TRY block to clean up the file if we fail.  Since we need a TRY
    8080             :      * block anyway, OK to use BasicOpenFile rather than OpenTransientFile.
    8081             :      */
    8082          30 :     PG_TRY();
    8083             :     {
    8084             :         /* Write and sync the new contents to the temporary file */
    8085          30 :         write_auto_conf_file(Tmpfd, AutoConfTmpFileName, head);
    8086             : 
    8087             :         /* Close before renaming; may be required on some platforms */
    8088          30 :         close(Tmpfd);
    8089          30 :         Tmpfd = -1;
    8090             : 
    8091             :         /*
    8092             :          * As the rename is atomic operation, if any problem occurs after this
    8093             :          * at worst it can lose the parameters set by last ALTER SYSTEM
    8094             :          * command.
    8095             :          */
    8096          30 :         durable_rename(AutoConfTmpFileName, AutoConfFileName, ERROR);
    8097             :     }
    8098           0 :     PG_CATCH();
    8099             :     {
    8100             :         /* Close file first, else unlink might fail on some platforms */
    8101           0 :         if (Tmpfd >= 0)
    8102           0 :             close(Tmpfd);
    8103             : 
    8104             :         /* Unlink, but ignore any error */
    8105           0 :         (void) unlink(AutoConfTmpFileName);
    8106             : 
    8107           0 :         PG_RE_THROW();
    8108             :     }
    8109          30 :     PG_END_TRY();
    8110             : 
    8111          30 :     FreeConfigVariables(head);
    8112             : 
    8113          30 :     LWLockRelease(AutoFileLock);
    8114          30 : }
    8115             : 
    8116             : /*
    8117             :  * SET command
    8118             :  */
    8119             : void
    8120       15554 : ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
    8121             : {
    8122       15554 :     GucAction   action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
    8123             : 
    8124             :     /*
    8125             :      * Workers synchronize these parameters at the start of the parallel
    8126             :      * operation; then, we block SET during the operation.
    8127             :      */
    8128       15554 :     if (IsInParallelMode())
    8129           0 :         ereport(ERROR,
    8130             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    8131             :                  errmsg("cannot set parameters during a parallel operation")));
    8132             : 
    8133       15554 :     switch (stmt->kind)
    8134             :     {
    8135             :         case VAR_SET_VALUE:
    8136             :         case VAR_SET_CURRENT:
    8137       13500 :             if (stmt->is_local)
    8138         420 :                 WarnNoTransactionBlock(isTopLevel, "SET LOCAL");
    8139       27000 :             (void) set_config_option(stmt->name,
    8140       13500 :                                      ExtractSetVariableArgs(stmt),
    8141       13500 :                                      (superuser() ? PGC_SUSET : PGC_USERSET),
    8142             :                                      PGC_S_SESSION,
    8143             :                                      action, true, 0, false);
    8144       13472 :             break;
    8145             :         case VAR_SET_MULTI:
    8146             : 
    8147             :             /*
    8148             :              * Special-case SQL syntaxes.  The TRANSACTION and SESSION
    8149             :              * CHARACTERISTICS cases effectively set more than one variable
    8150             :              * per statement.  TRANSACTION SNAPSHOT only takes one argument,
    8151             :              * but we put it here anyway since it's a special case and not
    8152             :              * related to any GUC variable.
    8153             :              */
    8154         298 :             if (strcmp(stmt->name, "TRANSACTION") == 0)
    8155             :             {
    8156             :                 ListCell   *head;
    8157             : 
    8158         274 :                 WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
    8159             : 
    8160         724 :                 foreach(head, stmt->args)
    8161             :                 {
    8162         464 :                     DefElem    *item = (DefElem *) lfirst(head);
    8163             : 
    8164         464 :                     if (strcmp(item->defname, "transaction_isolation") == 0)
    8165         412 :                         SetPGVariable("transaction_isolation",
    8166         412 :                                       list_make1(item->arg), stmt->is_local);
    8167         258 :                     else if (strcmp(item->defname, "transaction_read_only") == 0)
    8168         508 :                         SetPGVariable("transaction_read_only",
    8169         508 :                                       list_make1(item->arg), stmt->is_local);
    8170           4 :                     else if (strcmp(item->defname, "transaction_deferrable") == 0)
    8171           8 :                         SetPGVariable("transaction_deferrable",
    8172           8 :                                       list_make1(item->arg), stmt->is_local);
    8173             :                     else
    8174           0 :                         elog(ERROR, "unexpected SET TRANSACTION element: %s",
    8175             :                              item->defname);
    8176             :                 }
    8177             :             }
    8178          24 :             else if (strcmp(stmt->name, "SESSION CHARACTERISTICS") == 0)
    8179             :             {
    8180             :                 ListCell   *head;
    8181             : 
    8182          16 :                 foreach(head, stmt->args)
    8183             :                 {
    8184           8 :                     DefElem    *item = (DefElem *) lfirst(head);
    8185             : 
    8186           8 :                     if (strcmp(item->defname, "transaction_isolation") == 0)
    8187           0 :                         SetPGVariable("default_transaction_isolation",
    8188           0 :                                       list_make1(item->arg), stmt->is_local);
    8189           8 :                     else if (strcmp(item->defname, "transaction_read_only") == 0)
    8190          16 :                         SetPGVariable("default_transaction_read_only",
    8191          16 :                                       list_make1(item->arg), stmt->is_local);
    8192           0 :                     else if (strcmp(item->defname, "transaction_deferrable") == 0)
    8193           0 :                         SetPGVariable("default_transaction_deferrable",
    8194           0 :                                       list_make1(item->arg), stmt->is_local);
    8195             :                     else
    8196           0 :                         elog(ERROR, "unexpected SET SESSION element: %s",
    8197             :                              item->defname);
    8198             :                 }
    8199             :             }
    8200          16 :             else if (strcmp(stmt->name, "TRANSACTION SNAPSHOT") == 0)
    8201             :             {
    8202          16 :                 A_Const    *con = linitial_node(A_Const, stmt->args);
    8203             : 
    8204          16 :                 if (stmt->is_local)
    8205           0 :                     ereport(ERROR,
    8206             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    8207             :                              errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
    8208             : 
    8209          16 :                 WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
    8210             :                 Assert(nodeTag(&con->val) == T_String);
    8211          16 :                 ImportSnapshot(strVal(&con->val));
    8212             :             }
    8213             :             else
    8214           0 :                 elog(ERROR, "unexpected SET MULTI element: %s",
    8215             :                      stmt->name);
    8216         284 :             break;
    8217             :         case VAR_SET_DEFAULT:
    8218          32 :             if (stmt->is_local)
    8219           0 :                 WarnNoTransactionBlock(isTopLevel, "SET LOCAL");
    8220             :             /* fall through */
    8221             :         case VAR_RESET:
    8222        1756 :             if (strcmp(stmt->name, "transaction_isolation") == 0)
    8223           2 :                 WarnNoTransactionBlock(isTopLevel, "RESET TRANSACTION");
    8224             : 
    8225        1756 :             (void) set_config_option(stmt->name,
    8226             :                                      NULL,
    8227        1756 :                                      (superuser() ? PGC_SUSET : PGC_USERSET),
    8228             :                                      PGC_S_SESSION,
    8229             :                                      action, true, 0, false);
    8230        1756 :             break;
    8231             :         case VAR_RESET_ALL:
    8232           0 :             ResetAllOptions();
    8233           0 :             break;
    8234             :     }
    8235       15512 : }
    8236             : 
    8237             : /*
    8238             :  * Get the value to assign for a VariableSetStmt, or NULL if it's RESET.
    8239             :  * The result is palloc'd.
    8240             :  *
    8241             :  * This is exported for use by actions such as ALTER ROLE SET.
    8242             :  */
    8243             : char *
    8244       14460 : ExtractSetVariableArgs(VariableSetStmt *stmt)
    8245             : {
    8246       14460 :     switch (stmt->kind)
    8247             :     {
    8248             :         case VAR_SET_VALUE:
    8249       14440 :             return flatten_set_variable_args(stmt->name, stmt->args);
    8250             :         case VAR_SET_CURRENT:
    8251           0 :             return GetConfigOptionByName(stmt->name, NULL, false);
    8252             :         default:
    8253          20 :             return NULL;
    8254             :     }
    8255             : }
    8256             : 
    8257             : /*
    8258             :  * SetPGVariable - SET command exported as an easily-C-callable function.
    8259             :  *
    8260             :  * This provides access to SET TO value, as well as SET TO DEFAULT (expressed
    8261             :  * by passing args == NIL), but not SET FROM CURRENT functionality.
    8262             :  */
    8263             : void
    8264        5714 : SetPGVariable(const char *name, List *args, bool is_local)
    8265             : {
    8266        5714 :     char       *argstring = flatten_set_variable_args(name, args);
    8267             : 
    8268             :     /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
    8269       11428 :     (void) set_config_option(name,
    8270             :                              argstring,
    8271        5714 :                              (superuser() ? PGC_SUSET : PGC_USERSET),
    8272             :                              PGC_S_SESSION,
    8273             :                              is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
    8274             :                              true, 0, false);
    8275        5700 : }
    8276             : 
    8277             : /*
    8278             :  * SET command wrapped as a SQL callable function.
    8279             :  */
    8280             : Datum
    8281        1116 : set_config_by_name(PG_FUNCTION_ARGS)
    8282             : {
    8283             :     char       *name;
    8284             :     char       *value;
    8285             :     char       *new_value;
    8286             :     bool        is_local;
    8287             : 
    8288        1116 :     if (PG_ARGISNULL(0))
    8289           0 :         ereport(ERROR,
    8290             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    8291             :                  errmsg("SET requires parameter name")));
    8292             : 
    8293             :     /* Get the GUC variable name */
    8294        1116 :     name = TextDatumGetCString(PG_GETARG_DATUM(0));
    8295             : 
    8296             :     /* Get the desired value or set to NULL for a reset request */
    8297        1116 :     if (PG_ARGISNULL(1))
    8298           0 :         value = NULL;
    8299             :     else
    8300        1116 :         value = TextDatumGetCString(PG_GETARG_DATUM(1));
    8301             : 
    8302             :     /*
    8303             :      * Get the desired state of is_local. Default to false if provided value
    8304             :      * is NULL
    8305             :      */
    8306        1116 :     if (PG_ARGISNULL(2))
    8307           0 :         is_local = false;
    8308             :     else
    8309        1116 :         is_local = PG_GETARG_BOOL(2);
    8310             : 
    8311             :     /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
    8312        2232 :     (void) set_config_option(name,
    8313             :                              value,
    8314        1116 :                              (superuser() ? PGC_SUSET : PGC_USERSET),
    8315             :                              PGC_S_SESSION,
    8316             :                              is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
    8317             :                              true, 0, false);
    8318             : 
    8319             :     /* get the new current value */
    8320        1116 :     new_value = GetConfigOptionByName(name, NULL, false);
    8321             : 
    8322             :     /* Convert return string to text */
    8323        1116 :     PG_RETURN_TEXT_P(cstring_to_text(new_value));
    8324             : }
    8325             : 
    8326             : 
    8327             : /*
    8328             :  * Common code for DefineCustomXXXVariable subroutines: allocate the
    8329             :  * new variable's config struct and fill in generic fields.
    8330             :  */
    8331             : static struct config_generic *
    8332       10960 : init_custom_variable(const char *name,
    8333             :                      const char *short_desc,
    8334             :                      const char *long_desc,
    8335             :                      GucContext context,
    8336             :                      int flags,
    8337             :                      enum config_type type,
    8338             :                      size_t sz)
    8339             : {
    8340             :     struct config_generic *gen;
    8341             : 
    8342             :     /*
    8343             :      * Only allow custom PGC_POSTMASTER variables to be created during shared
    8344             :      * library preload; any later than that, we can't ensure that the value
    8345             :      * doesn't change after startup.  This is a fatal elog if it happens; just
    8346             :      * erroring out isn't safe because we don't know what the calling loadable
    8347             :      * module might already have hooked into.
    8348             :      */
    8349       10966 :     if (context == PGC_POSTMASTER &&
    8350           6 :         !process_shared_preload_libraries_in_progress)
    8351           0 :         elog(FATAL, "cannot create PGC_POSTMASTER variables after startup");
    8352             : 
    8353             :     /*
    8354             :      * We can't support custom GUC_LIST_QUOTE variables, because the wrong
    8355             :      * things would happen if such a variable were set or pg_dump'd when the
    8356             :      * defining extension isn't loaded.  Again, treat this as fatal because
    8357             :      * the loadable module may be partly initialized already.
    8358             :      */
    8359       10960 :     if (flags & GUC_LIST_QUOTE)
    8360           0 :         elog(FATAL, "extensions cannot define GUC_LIST_QUOTE variables");
    8361             : 
    8362             :     /*
    8363             :      * Before pljava commit 398f3b876ed402bdaec8bc804f29e2be95c75139
    8364             :      * (2015-12-15), two of that module's PGC_USERSET variables facilitated
    8365             :      * trivial escalation to superuser privileges.  Restrict the variables to
    8366             :      * protect sites that have yet to upgrade pljava.
    8367             :      */
    8368       19608 :     if (context == PGC_USERSET &&
    8369       17296 :         (strcmp(name, "pljava.classpath") == 0 ||
    8370        8648 :          strcmp(name, "pljava.vmoptions") == 0))
    8371           0 :         context = PGC_SUSET;
    8372             : 
    8373       10960 :     gen = (struct config_generic *) guc_malloc(ERROR, sz);
    8374       10960 :     memset(gen, 0, sz);
    8375             : 
    8376       10960 :     gen->name = guc_strdup(ERROR, name);
    8377       10960 :     gen->context = context;
    8378       10960 :     gen->group = CUSTOM_OPTIONS;
    8379       10960 :     gen->short_desc = short_desc;
    8380       10960 :     gen->long_desc = long_desc;
    8381       10960 :     gen->flags = flags;
    8382       10960 :     gen->vartype = type;
    8383             : 
    8384       10960 :     return gen;
    8385             : }
    8386             : 
    8387             : /*
    8388             :  * Common code for DefineCustomXXXVariable subroutines: insert the new
    8389             :  * variable into the GUC variable array, replacing any placeholder.
    8390             :  */
    8391             : static void
    8392       10960 : define_custom_variable(struct config_generic *variable)
    8393             : {
    8394       10960 :     const char *name = variable->name;
    8395       10960 :     const char **nameAddr = &name;
    8396             :     struct config_string *pHolder;
    8397             :     struct config_generic **res;
    8398             : 
    8399             :     /*
    8400             :      * See if there's a placeholder by the same name.
    8401             :      */
    8402       10960 :     res = (struct config_generic **) bsearch((void *) &nameAddr,
    8403             :                                              (void *) guc_variables,
    8404             :                                              num_guc_variables,
    8405             :                                              sizeof(struct config_generic *),
    8406             :                                              guc_var_compare);
    8407       10960 :     if (res == NULL)
    8408             :     {
    8409             :         /*
    8410             :          * No placeholder to replace, so we can just add it ... but first,
    8411             :          * make sure it's initialized to its default value.
    8412             :          */
    8413       10954 :         InitializeOneGUCOption(variable);
    8414       10954 :         add_guc_variable(variable, ERROR);
    8415       10954 :         return;
    8416             :     }
    8417             : 
    8418             :     /*
    8419             :      * This better be a placeholder
    8420             :      */
    8421           6 :     if (((*res)->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
    8422           0 :         ereport(ERROR,
    8423             :                 (errcode(ERRCODE_INTERNAL_ERROR),
    8424             :                  errmsg("attempt to redefine parameter \"%s\"", name)));
    8425             : 
    8426             :     Assert((*res)->vartype == PGC_STRING);
    8427           6 :     pHolder = (struct config_string *) (*res);
    8428             : 
    8429             :     /*
    8430             :      * First, set the variable to its default value.  We must do this even
    8431             :      * though we intend to immediately apply a new value, since it's possible
    8432             :      * that the new value is invalid.
    8433             :      */
    8434           6 :     InitializeOneGUCOption(variable);
    8435             : 
    8436             :     /*
    8437             :      * Replace the placeholder. We aren't changing the name, so no re-sorting
    8438             :      * is necessary
    8439             :      */
    8440           6 :     *res = variable;
    8441             : 
    8442             :     /*
    8443             :      * Assign the string value(s) stored in the placeholder to the real
    8444             :      * variable.  Essentially, we need to duplicate all the active and stacked
    8445             :      * values, but with appropriate validation and datatype adjustment.
    8446             :      *
    8447             :      * If an assignment fails, we report a WARNING and keep going.  We don't
    8448             :      * want to throw ERROR for bad values, because it'd bollix the add-on
    8449             :      * module that's presumably halfway through getting loaded.  In such cases
    8450             :      * the default or previous state will become active instead.
    8451             :      */
    8452             : 
    8453             :     /* First, apply the reset value if any */
    8454           6 :     if (pHolder->reset_val)
    8455           2 :         (void) set_config_option(name, pHolder->reset_val,
    8456             :                                  pHolder->gen.reset_scontext,
    8457             :                                  pHolder->gen.reset_source,
    8458             :                                  GUC_ACTION_SET, true, WARNING, false);
    8459             :     /* That should not have resulted in stacking anything */
    8460             :     Assert(variable->stack == NULL);
    8461             : 
    8462             :     /* Now, apply current and stacked values, in the order they were stacked */
    8463          12 :     reapply_stacked_values(variable, pHolder, pHolder->gen.stack,
    8464           6 :                            *(pHolder->variable),
    8465             :                            pHolder->gen.scontext, pHolder->gen.source);
    8466             : 
    8467             :     /* Also copy over any saved source-location information */
    8468           6 :     if (pHolder->gen.sourcefile)
    8469           2 :         set_config_sourcefile(name, pHolder->gen.sourcefile,
    8470             :                               pHolder->gen.sourceline);
    8471             : 
    8472             :     /*
    8473             :      * Free up as much as we conveniently can of the placeholder structure.
    8474             :      * (This neglects any stack items, so it's possible for some memory to be
    8475             :      * leaked.  Since this can only happen once per session per variable, it
    8476             :      * doesn't seem worth spending much code on.)
    8477             :      */
    8478           6 :     set_string_field(pHolder, pHolder->variable, NULL);
    8479           6 :     set_string_field(pHolder, &pHolder->reset_val, NULL);
    8480             : 
    8481           6 :     free(pHolder);
    8482             : }
    8483             : 
    8484             : /*
    8485             :  * Recursive subroutine for define_custom_variable: reapply non-reset values
    8486             :  *
    8487             :  * We recurse so that the values are applied in the same order as originally.
    8488             :  * At each recursion level, apply the upper-level value (passed in) in the
    8489             :  * fashion implied by the stack entry.
    8490             :  */
    8491             : static void
    8492           6 : reapply_stacked_values(struct config_generic *variable,
    8493             :                        struct config_string *pHolder,
    8494             :                        GucStack *stack,
    8495             :                        const char *curvalue,
    8496             :                        GucContext curscontext, GucSource cursource)
    8497             : {
    8498           6 :     const char *name = variable->name;
    8499           6 :     GucStack   *oldvarstack = variable->stack;
    8500             : 
    8501           6 :     if (stack != NULL)
    8502             :     {
    8503             :         /* First, recurse, so that stack items are processed bottom to top */
    8504           0 :         reapply_stacked_values(variable, pHolder, stack->prev,
    8505           0 :                                stack->prior.val.stringval,
    8506             :                                stack->scontext, stack->source);
    8507             : 
    8508             :         /* See how to apply the passed-in value */
    8509           0 :         switch (stack->state)
    8510             :         {
    8511             :             case GUC_SAVE:
    8512           0 :                 (void) set_config_option(name, curvalue,
    8513             :                                          curscontext, cursource,
    8514             :                                          GUC_ACTION_SAVE, true,
    8515             :                                          WARNING, false);
    8516           0 :                 break;
    8517             : 
    8518             :             case GUC_SET:
    8519           0 :                 (void) set_config_option(name, curvalue,
    8520             :                                          curscontext, cursource,
    8521             :                                          GUC_ACTION_SET, true,
    8522             :                                          WARNING, false);
    8523           0 :                 break;
    8524             : 
    8525             :             case GUC_LOCAL:
    8526           0 :                 (void) set_config_option(name, curvalue,
    8527             :                                          curscontext, cursource,
    8528             :                                          GUC_ACTION_LOCAL, true,
    8529             :                                          WARNING, false);
    8530           0 :                 break;
    8531             : 
    8532             :             case GUC_SET_LOCAL:
    8533             :                 /* first, apply the masked value as SET */
    8534           0 :                 (void) set_config_option(name, stack->masked.val.stringval,
    8535             :                                          stack->masked_scontext, PGC_S_SESSION,
    8536             :                                          GUC_ACTION_SET, true,
    8537             :                                          WARNING, false);
    8538             :                 /* then apply the current value as LOCAL */
    8539           0 :                 (void) set_config_option(name, curvalue,
    8540             :                                          curscontext, cursource,
    8541             :                                          GUC_ACTION_LOCAL, true,
    8542             :                                          WARNING, false);
    8543           0 :                 break;
    8544             :         }
    8545             : 
    8546             :         /* If we successfully made a stack entry, adjust its nest level */
    8547           0 :         if (variable->stack != oldvarstack)
    8548           0 :             variable->stack->nest_level = stack->nest_level;
    8549             :     }
    8550             :     else
    8551             :     {
    8552             :         /*
    8553             :          * We are at the end of the stack.  If the active/previous value is
    8554             :          * different from the reset value, it must represent a previously
    8555             :          * committed session value.  Apply it, and then drop the stack entry
    8556             :          * that set_config_option will have created under the impression that
    8557             :          * this is to be just a transactional assignment.  (We leak the stack
    8558             :          * entry.)
    8559             :          */
    8560           8 :         if (curvalue != pHolder->reset_val ||
    8561           4 :             curscontext != pHolder->gen.reset_scontext ||
    8562           2 :             cursource != pHolder->gen.reset_source)
    8563             :         {
    8564           4 :             (void) set_config_option(name, curvalue,
    8565             :                                      curscontext, cursource,
    8566             :                                      GUC_ACTION_SET, true, WARNING, false);
    8567           4 :             variable->stack = NULL;
    8568             :         }
    8569             :     }
    8570           6 : }
    8571             : 
    8572             : void
    8573        4338 : DefineCustomBoolVariable(const char *name,
    8574             :                          const char *short_desc,
    8575             :                          const char *long_desc,
    8576             :                          bool *valueAddr,
    8577             :                          bool bootValue,
    8578             :                          GucContext context,
    8579             :                          int flags,
    8580             :                          GucBoolCheckHook check_hook,
    8581             :                          GucBoolAssignHook assign_hook,
    8582             :                          GucShowHook show_hook)
    8583             : {
    8584             :     struct config_bool *var;
    8585             : 
    8586        4338 :     var = (struct config_bool *)
    8587             :         init_custom_variable(name, short_desc, long_desc, context, flags,
    8588             :                              PGC_BOOL, sizeof(struct config_bool));
    8589        4338 :     var->variable = valueAddr;
    8590        4338 :     var->boot_val = bootValue;
    8591        4338 :     var->reset_val = bootValue;
    8592        4338 :     var->check_hook = check_hook;
    8593        4338 :     var->assign_hook = assign_hook;
    8594        4338 :     var->show_hook = show_hook;
    8595        4338 :     define_custom_variable(&var->gen);
    8596        4338 : }
    8597             : 
    8598             : void
    8599           6 : DefineCustomIntVariable(const char *name,
    8600             :                         const char *short_desc,
    8601             :                         const char *long_desc,
    8602             :                         int *valueAddr,
    8603             :                         int bootValue,
    8604             :                         int minValue,
    8605             :                         int maxValue,
    8606             :                         GucContext context,
    8607             :                         int flags,
    8608             :                         GucIntCheckHook check_hook,
    8609             :                         GucIntAssignHook assign_hook,
    8610             :                         GucShowHook show_hook)
    8611             : {
    8612             :     struct config_int *var;
    8613             : 
    8614           6 :     var = (struct config_int *)
    8615             :         init_custom_variable(name, short_desc, long_desc, context, flags,
    8616             :                              PGC_INT, sizeof(struct config_int));
    8617           6 :     var->variable = valueAddr;
    8618           6 :     var->boot_val = bootValue;
    8619           6 :     var->reset_val = bootValue;
    8620           6 :     var->min = minValue;
    8621           6 :     var->max = maxValue;
    8622           6 :     var->check_hook = check_hook;
    8623           6 :     var->assign_hook = assign_hook;
    8624           6 :     var->show_hook = show_hook;
    8625           6 :     define_custom_variable(&var->gen);
    8626           6 : }
    8627             : 
    8628             : void
    8629          18 : DefineCustomRealVariable(const char *name,
    8630             :                          const char *short_desc,
    8631             :                          const char *long_desc,
    8632             :                          double *valueAddr,
    8633             :                          double bootValue,
    8634             :                          double minValue,
    8635             :                          double maxValue,
    8636             :                          GucContext context,
    8637             :                          int flags,
    8638             :                          GucRealCheckHook check_hook,
    8639             :                          GucRealAssignHook assign_hook,
    8640             :                          GucShowHook show_hook)
    8641             : {
    8642             :     struct config_real *var;
    8643             : 
    8644          18 :     var = (struct config_real *)
    8645             :         init_custom_variable(name, short_desc, long_desc, context, flags,
    8646             :                              PGC_REAL, sizeof(struct config_real));
    8647          18 :     var->variable = valueAddr;
    8648          18 :     var->boot_val = bootValue;
    8649          18 :     var->reset_val = bootValue;
    8650          18 :     var->min = minValue;
    8651          18 :     var->max = maxValue;
    8652          18 :     var->check_hook = check_hook;
    8653          18 :     var->assign_hook = assign_hook;
    8654          18 :     var->show_hook = show_hook;
    8655          18 :     define_custom_variable(&var->gen);
    8656          18 : }
    8657             : 
    8658             : void
    8659        4448 : DefineCustomStringVariable(const char *name,
    8660             :                            const char *short_desc,
    8661             :                            const char *long_desc,
    8662             :                            char **valueAddr,
    8663             :                            const char *bootValue,
    8664             :                            GucContext context,
    8665             :                            int flags,
    8666             :                            GucStringCheckHook check_hook,
    8667             :                            GucStringAssignHook assign_hook,
    8668             :                            GucShowHook show_hook)
    8669             : {
    8670             :     struct config_string *var;
    8671             : 
    8672        4448 :     var = (struct config_string *)
    8673             :         init_custom_variable(name, short_desc, long_desc, context, flags,
    8674             :                              PGC_STRING, sizeof(struct config_string));
    8675        4448 :     var->variable = valueAddr;
    8676        4448 :     var->boot_val = bootValue;
    8677        4448 :     var->check_hook = check_hook;
    8678        4448 :     var->assign_hook = assign_hook;
    8679        4448 :     var->show_hook = show_hook;
    8680        4448 :     define_custom_variable(&var->gen);
    8681        4448 : }
    8682             : 
    8683             : void
    8684        2150 : DefineCustomEnumVariable(const char *name,
    8685             :                          const char *short_desc,
    8686             :                          const char *long_desc,
    8687             :                          int *valueAddr,
    8688             :                          int bootValue,
    8689             :                          const struct config_enum_entry *options,
    8690             :                          GucContext context,
    8691             :                          int flags,
    8692             :                          GucEnumCheckHook check_hook,
    8693             :                          GucEnumAssignHook assign_hook,
    8694             :                          GucShowHook show_hook)
    8695             : {
    8696             :     struct config_enum *var;
    8697             : 
    8698        2150 :     var = (struct config_enum *)
    8699             :         init_custom_variable(name, short_desc, long_desc, context, flags,
    8700             :                              PGC_ENUM, sizeof(struct config_enum));
    8701        2150 :     var->variable = valueAddr;
    8702        2150 :     var->boot_val = bootValue;
    8703        2150 :     var->reset_val = bootValue;
    8704        2150 :     var->options = options;
    8705        2150 :     var->check_hook = check_hook;
    8706        2150 :     var->assign_hook = assign_hook;
    8707        2150 :     var->show_hook = show_hook;
    8708        2150 :     define_custom_variable(&var->gen);
    8709        2150 : }
    8710             : 
    8711             : void
    8712        2188 : EmitWarningsOnPlaceholders(const char *className)
    8713             : {
    8714        2188 :     int         classLen = strlen(className);
    8715             :     int         i;
    8716             : 
    8717      713278 :     for (i = 0; i < num_guc_variables; i++)
    8718             :     {
    8719      711090 :         struct config_generic *var = guc_variables[i];
    8720             : 
    8721      711094 :         if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
    8722           4 :             strncmp(className, var->name, classLen) == 0 &&
    8723           0 :             var->name[classLen] == GUC_QUALIFIER_SEPARATOR)
    8724             :         {
    8725           0 :             ereport(WARNING,
    8726             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    8727             :                      errmsg("unrecognized configuration parameter \"%s\"",
    8728             :                             var->name)));
    8729             :         }
    8730             :     }
    8731        2188 : }
    8732             : 
    8733             : 
    8734             : /*
    8735             :  * SHOW command
    8736             :  */
    8737             : void
    8738         770 : GetPGVariable(const char *name, DestReceiver *dest)
    8739             : {
    8740         770 :     if (guc_name_compare(name, "all") == 0)
    8741           4 :         ShowAllGUCConfig(dest);
    8742             :     else
    8743         766 :         ShowGUCConfigOption(name, dest);
    8744         770 : }
    8745             : 
    8746             : TupleDesc
    8747         450 : GetPGVariableResultDesc(const char *name)
    8748             : {
    8749             :     TupleDesc   tupdesc;
    8750             : 
    8751         450 :     if (guc_name_compare(name, "all") == 0)
    8752             :     {
    8753             :         /* need a tuple descriptor representing three TEXT columns */
    8754           0 :         tupdesc = CreateTemplateTupleDesc(3);
    8755           0 :         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
    8756             :                            TEXTOID, -1, 0);
    8757           0 :         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
    8758             :                            TEXTOID, -1, 0);
    8759           0 :         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
    8760             :                            TEXTOID, -1, 0);
    8761             :     }
    8762             :     else
    8763             :     {
    8764             :         const char *varname;
    8765             : 
    8766             :         /* Get the canonical spelling of name */
    8767         450 :         (void) GetConfigOptionByName(name, &varname, false);
    8768             : 
    8769             :         /* need a tuple descriptor representing a single TEXT column */
    8770         448 :         tupdesc = CreateTemplateTupleDesc(1);
    8771         448 :         TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
    8772             :                            TEXTOID, -1, 0);
    8773             :     }
    8774         448 :     return tupdesc;
    8775             : }
    8776             : 
    8777             : 
    8778             : /*
    8779             :  * SHOW command
    8780             :  */
    8781             : static void
    8782         766 : ShowGUCConfigOption(const char *name, DestReceiver *dest)
    8783             : {
    8784             :     TupOutputState *tstate;
    8785             :     TupleDesc   tupdesc;
    8786             :     const char *varname;
    8787             :     char       *value;
    8788             : 
    8789             :     /* Get the value and canonical spelling of name */
    8790         766 :     value = GetConfigOptionByName(name, &varname, false);
    8791             : 
    8792             :     /* need a tuple descriptor representing a single TEXT column */
    8793         766 :     tupdesc = CreateTemplateTupleDesc(1);
    8794         766 :     TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, varname,
    8795             :                               TEXTOID, -1, 0);
    8796             : 
    8797             :     /* prepare for projection of tuples */
    8798         766 :     tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
    8799             : 
    8800             :     /* Send it */
    8801         766 :     do_text_output_oneline(tstate, value);
    8802             : 
    8803         766 :     end_tup_output(tstate);
    8804         766 : }
    8805             : 
    8806             : /*
    8807             :  * SHOW ALL command
    8808             :  */
    8809             : static void
    8810           4 : ShowAllGUCConfig(DestReceiver *dest)
    8811             : {
    8812             :     int         i;
    8813             :     TupOutputState *tstate;
    8814             :     TupleDesc   tupdesc;
    8815             :     Datum       values[3];
    8816           4 :     bool        isnull[3] = {false, false, false};
    8817             : 
    8818             :     /* need a tuple descriptor representing three TEXT columns */
    8819           4 :     tupdesc = CreateTemplateTupleDesc(3);
    8820           4 :     TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "name",
    8821             :                               TEXTOID, -1, 0);
    8822           4 :     TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "setting",
    8823             :                               TEXTOID, -1, 0);
    8824           4 :     TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "description",
    8825             :                               TEXTOID, -1, 0);
    8826             : 
    8827             :     /* prepare for projection of tuples */
    8828           4 :     tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
    8829             : 
    8830        1284 :     for (i = 0; i < num_guc_variables; i++)
    8831             :     {
    8832        1280 :         struct config_generic *conf = guc_variables[i];
    8833             :         char       *setting;
    8834             : 
    8835        2536 :         if ((conf->flags & GUC_NO_SHOW_ALL) ||
    8836        1336 :             ((conf->flags & GUC_SUPERUSER_ONLY) &&
    8837          80 :              !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)))
    8838          24 :             continue;
    8839             : 
    8840             :         /* assign to the values array */
    8841        1256 :         values[0] = PointerGetDatum(cstring_to_text(conf->name));
    8842             : 
    8843        1256 :         setting = _ShowOption(conf, true);
    8844        1256 :         if (setting)
    8845             :         {
    8846        1256 :             values[1] = PointerGetDatum(cstring_to_text(setting));
    8847        1256 :             isnull[1] = false;
    8848             :         }
    8849             :         else
    8850             :         {
    8851           0 :             values[1] = PointerGetDatum(NULL);
    8852           0 :             isnull[1] = true;
    8853             :         }
    8854             : 
    8855        1256 :         values[2] = PointerGetDatum(cstring_to_text(conf->short_desc));
    8856             : 
    8857             :         /* send it to dest */
    8858        1256 :         do_tup_output(tstate, values, isnull);
    8859             : 
    8860             :         /* clean up */
    8861        1256 :         pfree(DatumGetPointer(values[0]));
    8862        1256 :         if (setting)
    8863             :         {
    8864        1256 :             pfree(setting);
    8865        1256 :             pfree(DatumGetPointer(values[1]));
    8866             :         }
    8867        1256 :         pfree(DatumGetPointer(values[2]));
    8868             :     }
    8869             : 
    8870           4 :     end_tup_output(tstate);
    8871           4 : }
    8872             : 
    8873             : /*
    8874             :  * Returns an array of modified GUC options to show in EXPLAIN. Only options
    8875             :  * related to query planning (marked with GUC_EXPLAIN), with values different
    8876             :  * from built-in defaults.
    8877             :  */
    8878             : struct config_generic **
    8879           0 : get_explain_guc_options(int *num)
    8880             : {
    8881             :     int         i;
    8882             :     struct config_generic **result;
    8883             : 
    8884           0 :     *num = 0;
    8885             : 
    8886             :     /*
    8887             :      * Allocate enough space to fit all GUC_EXPLAIN options. We may not need
    8888             :      * all the space, but there are fairly few such options so we don't waste
    8889             :      * a lot of memory.
    8890             :      */
    8891           0 :     result = palloc(sizeof(struct config_generic *) * num_guc_explain_variables);
    8892             : 
    8893           0 :     for (i = 0; i < num_guc_variables; i++)
    8894             :     {
    8895             :         bool        modified;
    8896           0 :         struct config_generic *conf = guc_variables[i];
    8897             : 
    8898             :         /* return only options visible to the user */
    8899           0 :         if ((conf->flags & GUC_NO_SHOW_ALL) ||
    8900           0 :             ((conf->flags & GUC_SUPERUSER_ONLY) &&
    8901           0 :              !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)))
    8902           0 :             continue;
    8903             : 
    8904             :         /* only parameters explicitly marked for inclusion in explain */
    8905           0 :         if (!(conf->flags & GUC_EXPLAIN))
    8906           0 :             continue;
    8907             : 
    8908             :         /* return only options that were modified (w.r.t. config file) */
    8909           0 :         modified = false;
    8910             : 
    8911           0 :         switch (conf->vartype)
    8912             :         {
    8913             :             case PGC_BOOL:
    8914             :                 {
    8915           0 :                     struct config_bool *lconf = (struct config_bool *) conf;
    8916             : 
    8917           0 :                     modified = (lconf->boot_val != *(lconf->variable));
    8918             :                 }
    8919           0 :                 break;
    8920             : 
    8921             :             case PGC_INT:
    8922             :                 {
    8923           0 :                     struct config_int *lconf = (struct config_int *) conf;
    8924             : 
    8925           0 :                     modified = (lconf->boot_val != *(lconf->variable));
    8926             :                 }
    8927           0 :                 break;
    8928             : 
    8929             :             case PGC_REAL:
    8930             :                 {
    8931           0 :                     struct config_real *lconf = (struct config_real *) conf;
    8932             : 
    8933           0 :                     modified = (lconf->boot_val != *(lconf->variable));
    8934             :                 }
    8935           0 :                 break;
    8936             : 
    8937             :             case PGC_STRING:
    8938             :                 {
    8939           0 :                     struct config_string *lconf = (struct config_string *) conf;
    8940             : 
    8941           0 :                     modified = (strcmp(lconf->boot_val, *(lconf->variable)) != 0);
    8942             :                 }
    8943           0 :                 break;
    8944             : 
    8945             :             case PGC_ENUM:
    8946             :                 {
    8947           0 :                     struct config_enum *lconf = (struct config_enum *) conf;
    8948             : 
    8949           0 :                     modified = (lconf->boot_val != *(lconf->variable));
    8950             :                 }
    8951           0 :                 break;
    8952             : 
    8953             :             default:
    8954           0 :                 elog(ERROR, "unexpected GUC type: %d", conf->vartype);
    8955             :         }
    8956             : 
    8957             :         /* skip GUC variables that match the built-in default */
    8958           0 :         if (!modified)
    8959           0 :             continue;
    8960             : 
    8961             :         /* assign to the values array */
    8962           0 :         result[*num] = conf;
    8963           0 :         *num = *num + 1;
    8964             : 
    8965             :         Assert(*num <= num_guc_explain_variables);
    8966             :     }
    8967             : 
    8968           0 :     return result;
    8969             : }
    8970             : 
    8971             : /*
    8972             :  * Return GUC variable value by name; optionally return canonical form of
    8973             :  * name.  If the GUC is unset, then throw an error unless missing_ok is true,
    8974             :  * in which case return NULL.  Return value is palloc'd (but *varname isn't).
    8975             :  */
    8976             : char *
    8977        2572 : GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
    8978             : {
    8979             :     struct config_generic *record;
    8980             : 
    8981        2572 :     record = find_option(name, false, ERROR);
    8982        2572 :     if (record == NULL)
    8983             :     {
    8984          12 :         if (missing_ok)
    8985             :         {
    8986           4 :             if (varname)
    8987           0 :                 *varname = NULL;
    8988           4 :             return NULL;
    8989             :         }
    8990             : 
    8991           8 :         ereport(ERROR,
    8992             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    8993             :                  errmsg("unrecognized configuration parameter \"%s\"", name)));
    8994             :     }
    8995             : 
    8996        2574 :     if ((record->flags & GUC_SUPERUSER_ONLY) &&
    8997          14 :         !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))
    8998           2 :         ereport(ERROR,
    8999             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    9000             :                  errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"",
    9001             :                         name)));
    9002             : 
    9003        2558 :     if (varname)
    9004        1214 :         *varname = record->name;
    9005             : 
    9006        2558 :     return _ShowOption(record, true);
    9007             : }
    9008             : 
    9009             : /*
    9010             :  * Return GUC variable value by variable number; optionally return canonical
    9011             :  * form of name.  Return value is palloc'd.
    9012             :  */
    9013             : void
    9014        8960 : GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
    9015             : {
    9016             :     char        buffer[256];
    9017             :     struct config_generic *conf;
    9018             : 
    9019             :     /* check requested variable number valid */
    9020             :     Assert((varnum >= 0) && (varnum < num_guc_variables));
    9021             : 
    9022        8960 :     conf = guc_variables[varnum];
    9023             : 
    9024        8960 :     if (noshow)
    9025             :     {
    9026       17752 :         if ((conf->flags & GUC_NO_SHOW_ALL) ||
    9027        9352 :             ((conf->flags & GUC_SUPERUSER_ONLY) &&
    9028         560 :              !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)))
    9029         168 :             *noshow = true;
    9030             :         else
    9031        8792 :             *noshow = false;
    9032             :     }
    9033             : 
    9034             :     /* first get the generic attributes */
    9035             : 
    9036             :     /* name */
    9037        8960 :     values[0] = conf->name;
    9038             : 
    9039             :     /* setting: use _ShowOption in order to avoid duplicating the logic */
    9040        8960 :     values[1] = _ShowOption(conf, false);
    9041             : 
    9042             :     /* unit, if any (NULL is fine) */
    9043        8960 :     values[2] = get_config_unit_name(conf->flags);
    9044             : 
    9045             :     /* group */
    9046        8960 :     values[3] = _(config_group_names[conf->group]);
    9047             : 
    9048             :     /* short_desc */
    9049        8960 :     values[4] = _(conf->short_desc);
    9050             : 
    9051             :     /* extra_desc */
    9052        8960 :     values[5] = _(conf->long_desc);
    9053             : 
    9054             :     /* context */
    9055        8960 :     values[6] = GucContext_Names[conf->context];
    9056             : 
    9057             :     /* vartype */
    9058        8960 :     values[7] = config_type_names[conf->vartype];
    9059             : 
    9060             :     /* source */
    9061        8960 :     values[8] = GucSource_Names[conf->source];
    9062             : 
    9063             :     /* now get the type specific attributes */
    9064        8960 :     switch (conf->vartype)
    9065             :     {
    9066             :         case PGC_BOOL:
    9067             :             {
    9068        2604 :                 struct config_bool *lconf = (struct config_bool *) conf;
    9069             : 
    9070             :                 /* min_val */
    9071        2604 :                 values[9] = NULL;
    9072             : 
    9073             :                 /* max_val */
    9074        2604 :                 values[10] = NULL;
    9075             : 
    9076             :                 /* enumvals */
    9077        2604 :                 values[11] = NULL;
    9078             : 
    9079             :                 /* boot_val */
    9080        2604 :                 values[12] = pstrdup(lconf->boot_val ? "on" : "off");
    9081             : 
    9082             :                 /* reset_val */
    9083        2604 :                 values[13] = pstrdup(lconf->reset_val ? "on" : "off");
    9084             :             }
    9085        2604 :             break;
    9086             : 
    9087             :         case PGC_INT:
    9088             :             {
    9089        2996 :                 struct config_int *lconf = (struct config_int *) conf;
    9090             : 
    9091             :                 /* min_val */
    9092        2996 :                 snprintf(buffer, sizeof(buffer), "%d", lconf->min);
    9093        2996 :                 values[9] = pstrdup(buffer);
    9094             : 
    9095             :                 /* max_val */
    9096        2996 :                 snprintf(buffer, sizeof(buffer), "%d", lconf->max);
    9097        2996 :                 values[10] = pstrdup(buffer);
    9098             : 
    9099             :                 /* enumvals */
    9100        2996 :                 values[11] = NULL;
    9101             : 
    9102             :                 /* boot_val */
    9103        2996 :                 snprintf(buffer, sizeof(buffer), "%d", lconf->boot_val);
    9104        2996 :                 values[12] = pstrdup(buffer);
    9105             : 
    9106             :                 /* reset_val */
    9107        2996 :                 snprintf(buffer, sizeof(buffer), "%d", lconf->reset_val);
    9108        2996 :                 values[13] = pstrdup(buffer);
    9109             :             }
    9110        2996 :             break;
    9111             : 
    9112             :         case PGC_REAL:
    9113             :             {
    9114         616 :                 struct config_real *lconf = (struct config_real *) conf;
    9115             : 
    9116             :                 /* min_val */
    9117         616 :                 snprintf(buffer, sizeof(buffer), "%g", lconf->min);
    9118         616 :                 values[9] = pstrdup(buffer);
    9119             : 
    9120             :                 /* max_val */
    9121         616 :                 snprintf(buffer, sizeof(buffer), "%g", lconf->max);
    9122         616 :                 values[10] = pstrdup(buffer);
    9123             : 
    9124             :                 /* enumvals */
    9125         616 :                 values[11] = NULL;
    9126             : 
    9127             :                 /* boot_val */
    9128         616 :                 snprintf(buffer, sizeof(buffer), "%g", lconf->boot_val);
    9129         616 :                 values[12] = pstrdup(buffer);
    9130             : 
    9131             :                 /* reset_val */
    9132         616 :                 snprintf(buffer, sizeof(buffer), "%g", lconf->reset_val);
    9133         616 :                 values[13] = pstrdup(buffer);
    9134             :             }
    9135         616 :             break;
    9136             : 
    9137             :         case PGC_STRING:
    9138             :             {
    9139        1904 :                 struct config_string *lconf = (struct config_string *) conf;
    9140             : 
    9141             :                 /* min_val */
    9142        1904 :                 values[9] = NULL;
    9143             : 
    9144             :                 /* max_val */
    9145        1904 :                 values[10] = NULL;
    9146             : 
    9147             :                 /* enumvals */
    9148        1904 :                 values[11] = NULL;
    9149             : 
    9150             :                 /* boot_val */
    9151        1904 :                 if (lconf->boot_val == NULL)
    9152         196 :                     values[12] = NULL;
    9153             :                 else
    9154        1708 :                     values[12] = pstrdup(lconf->boot_val);
    9155             : 
    9156             :                 /* reset_val */
    9157        1904 :                 if (lconf->reset_val == NULL)
    9158          28 :                     values[13] = NULL;
    9159             :                 else
    9160        1876 :                     values[13] = pstrdup(lconf->reset_val);
    9161             :             }
    9162        1904 :             break;
    9163             : 
    9164             :         case PGC_ENUM:
    9165             :             {
    9166         840 :                 struct config_enum *lconf = (struct config_enum *) conf;
    9167             : 
    9168             :                 /* min_val */
    9169         840 :                 values[9] = NULL;
    9170             : 
    9171             :                 /* max_val */
    9172         840 :                 values[10] = NULL;
    9173             : 
    9174             :                 /* enumvals */
    9175             : 
    9176             :                 /*
    9177             :                  * NOTE! enumvals with double quotes in them are not
    9178             :                  * supported!
    9179             :                  */
    9180         840 :                 values[11] = config_enum_get_options((struct config_enum *) conf,
    9181             :                                                      "{\"", "\"}", "\",\"");
    9182             : 
    9183             :                 /* boot_val */
    9184         840 :                 values[12] = pstrdup(config_enum_lookup_by_value(lconf,
    9185             :                                                                  lconf->boot_val));
    9186             : 
    9187             :                 /* reset_val */
    9188         840 :                 values[13] = pstrdup(config_enum_lookup_by_value(lconf,
    9189             :                                                                  lconf->reset_val));
    9190             :             }
    9191         840 :             break;
    9192             : 
    9193             :         default:
    9194             :             {
    9195             :                 /*
    9196             :                  * should never get here, but in case we do, set 'em to NULL
    9197             :                  */
    9198             : 
    9199             :                 /* min_val */
    9200           0 :                 values[9] = NULL;
    9201             : 
    9202             :                 /* max_val */
    9203           0 :                 values[10] = NULL;
    9204             : 
    9205             :                 /* enumvals */
    9206           0 :                 values[11] = NULL;
    9207             : 
    9208             :                 /* boot_val */
    9209           0 :                 values[12] = NULL;
    9210             : 
    9211             :                 /* reset_val */
    9212           0 :                 values[13] = NULL;
    9213             :             }
    9214           0 :             break;
    9215             :     }
    9216             : 
    9217             :     /*
    9218             :      * If the setting came from a config file, set the source location. For
    9219             :      * security reasons, we don't show source file/line number for
    9220             :      * insufficiently-privileged users.
    9221             :      */
    9222        9386 :     if (conf->source == PGC_S_FILE &&
    9223         426 :         is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))
    9224             :     {
    9225         426 :         values[14] = conf->sourcefile;
    9226         426 :         snprintf(buffer, sizeof(buffer), "%d", conf->sourceline);
    9227         426 :         values[15] = pstrdup(buffer);
    9228             :     }
    9229             :     else
    9230             :     {
    9231        8534 :         values[14] = NULL;
    9232        8534 :         values[15] = NULL;
    9233             :     }
    9234             : 
    9235        8960 :     values[16] = (conf->status & GUC_PENDING_RESTART) ? "t" : "f";
    9236        8960 : }
    9237             : 
    9238             : /*
    9239             :  * Return the total number of GUC variables
    9240             :  */
    9241             : int
    9242          28 : GetNumConfigOptions(void)
    9243             : {
    9244          28 :     return num_guc_variables;
    9245             : }
    9246             : 
    9247             : /*
    9248             :  * show_config_by_name - equiv to SHOW X command but implemented as
    9249             :  * a function.
    9250             :  */
    9251             : Datum
    9252         224 : show_config_by_name(PG_FUNCTION_ARGS)
    9253             : {
    9254         224 :     char       *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
    9255             :     char       *varval;
    9256             : 
    9257             :     /* Get the value */
    9258         224 :     varval = GetConfigOptionByName(varname, NULL, false);
    9259             : 
    9260             :     /* Convert to text */
    9261         220 :     PG_RETURN_TEXT_P(cstring_to_text(varval));
    9262             : }
    9263             : 
    9264             : /*
    9265             :  * show_config_by_name_missing_ok - equiv to SHOW X command but implemented as
    9266             :  * a function.  If X does not exist, suppress the error and just return NULL
    9267             :  * if missing_ok is true.
    9268             :  */
    9269             : Datum
    9270          16 : show_config_by_name_missing_ok(PG_FUNCTION_ARGS)
    9271             : {
    9272          16 :     char       *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
    9273          16 :     bool        missing_ok = PG_GETARG_BOOL(1);
    9274             :     char       *varval;
    9275             : 
    9276             :     /* Get the value */
    9277          16 :     varval = GetConfigOptionByName(varname, NULL, missing_ok);
    9278             : 
    9279             :     /* return NULL if no such variable */
    9280          12 :     if (varval == NULL)
    9281           4 :         PG_RETURN_NULL();
    9282             : 
    9283             :     /* Convert to text */
    9284           8 :     PG_RETURN_TEXT_P(cstring_to_text(varval));
    9285             : }
    9286             : 
    9287             : /*
    9288             :  * show_all_settings - equiv to SHOW ALL command but implemented as
    9289             :  * a Table Function.
    9290             :  */
    9291             : #define NUM_PG_SETTINGS_ATTS    17
    9292             : 
    9293             : Datum
    9294        8820 : show_all_settings(PG_FUNCTION_ARGS)
    9295             : {
    9296             :     FuncCallContext *funcctx;
    9297             :     TupleDesc   tupdesc;
    9298             :     int         call_cntr;
    9299             :     int         max_calls;
    9300             :     AttInMetadata *attinmeta;
    9301             :     MemoryContext oldcontext;
    9302             : 
    9303             :     /* stuff done only on the first call of the function */
    9304        8820 :     if (SRF_IS_FIRSTCALL())
    9305             :     {
    9306             :         /* create a function context for cross-call persistence */
    9307          28 :         funcctx = SRF_FIRSTCALL_INIT();
    9308             : 
    9309             :         /*
    9310             :          * switch to memory context appropriate for multiple function calls
    9311             :          */
    9312          28 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    9313             : 
    9314             :         /*
    9315             :          * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
    9316             :          * of the appropriate types
    9317             :          */
    9318          28 :         tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS);
    9319          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
    9320             :                            TEXTOID, -1, 0);
    9321          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
    9322             :                            TEXTOID, -1, 0);
    9323          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit",
    9324             :                            TEXTOID, -1, 0);
    9325          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category",
    9326             :                            TEXTOID, -1, 0);
    9327          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc",
    9328             :                            TEXTOID, -1, 0);
    9329          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc",
    9330             :                            TEXTOID, -1, 0);
    9331          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context",
    9332             :                            TEXTOID, -1, 0);
    9333          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype",
    9334             :                            TEXTOID, -1, 0);
    9335          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source",
    9336             :                            TEXTOID, -1, 0);
    9337          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val",
    9338             :                            TEXTOID, -1, 0);
    9339          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
    9340             :                            TEXTOID, -1, 0);
    9341          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
    9342             :                            TEXTARRAYOID, -1, 0);
    9343          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 13, "boot_val",
    9344             :                            TEXTOID, -1, 0);
    9345          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 14, "reset_val",
    9346             :                            TEXTOID, -1, 0);
    9347          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 15, "sourcefile",
    9348             :                            TEXTOID, -1, 0);
    9349          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 16, "sourceline",
    9350             :                            INT4OID, -1, 0);
    9351          28 :         TupleDescInitEntry(tupdesc, (AttrNumber) 17, "pending_restart",
    9352             :                            BOOLOID, -1, 0);
    9353             : 
    9354             :         /*
    9355             :          * Generate attribute metadata needed later to produce tuples from raw
    9356             :          * C strings
    9357             :          */
    9358          28 :         attinmeta = TupleDescGetAttInMetadata(tupdesc);
    9359          28 :         funcctx->attinmeta = attinmeta;
    9360             : 
    9361             :         /* total number of tuples to be returned */
    9362          28 :         funcctx->max_calls = GetNumConfigOptions();
    9363             : 
    9364          28 :         MemoryContextSwitchTo(oldcontext);
    9365             :     }
    9366             : 
    9367             :     /* stuff done on every call of the function */
    9368        8820 :     funcctx = SRF_PERCALL_SETUP();
    9369             : 
    9370        8820 :     call_cntr = funcctx->call_cntr;
    9371        8820 :     max_calls = funcctx->max_calls;
    9372        8820 :     attinmeta = funcctx->attinmeta;
    9373             : 
    9374        8820 :     if (call_cntr < max_calls)   /* do when there is more left to send */
    9375             :     {
    9376             :         char       *values[NUM_PG_SETTINGS_ATTS];
    9377             :         bool        noshow;
    9378             :         HeapTuple   tuple;
    9379             :         Datum       result;
    9380             : 
    9381             :         /*
    9382             :          * Get the next visible GUC variable name and value
    9383             :          */
    9384             :         do
    9385             :         {
    9386        8960 :             GetConfigOptionByNum(call_cntr, (const char **) values, &noshow);
    9387        8960 :             if (noshow)
    9388             :             {
    9389             :                 /* bump the counter and get the next config setting */
    9390         168 :                 call_cntr = ++funcctx->call_cntr;
    9391             : 
    9392             :                 /* make sure we haven't gone too far now */
    9393         168 :                 if (call_cntr >= max_calls)
    9394           0 :                     SRF_RETURN_DONE(funcctx);
    9395             :             }
    9396        8960 :         } while (noshow);
    9397             : 
    9398             :         /* build a tuple */
    9399        8792 :         tuple = BuildTupleFromCStrings(attinmeta, values);
    9400             : 
    9401             :         /* make the tuple into a datum */
    9402        8792 :         result = HeapTupleGetDatum(tuple);
    9403             : 
    9404        8792 :         SRF_RETURN_NEXT(funcctx, result);
    9405             :     }
    9406             :     else
    9407             :     {
    9408             :         /* do when there is no more left */
    9409          28 :         SRF_RETURN_DONE(funcctx);
    9410             :     }
    9411             : }
    9412             : 
    9413             : /*
    9414             :  * show_all_file_settings
    9415             :  *
    9416             :  * Returns a table of all parameter settings in all configuration files
    9417             :  * which includes the config file pathname, the line number, a sequence number
    9418             :  * indicating the order in which the settings were encountered, the parameter
    9419             :  * name and value, a bool showing if the value could be applied, and possibly
    9420             :  * an associated error message.  (For problems such as syntax errors, the
    9421             :  * parameter name/value might be NULL.)
    9422             :  *
    9423             :  * Note: no filtering is done here, instead we depend on the GRANT system
    9424             :  * to prevent unprivileged users from accessing this function or the view
    9425             :  * built on top of it.
    9426             :  */
    9427             : Datum
    9428           4 : show_all_file_settings(PG_FUNCTION_ARGS)
    9429             : {
    9430             : #define NUM_PG_FILE_SETTINGS_ATTS 7
    9431           4 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
    9432             :     TupleDesc   tupdesc;
    9433             :     Tuplestorestate *tupstore;
    9434             :     ConfigVariable *conf;
    9435             :     int         seqno;
    9436             :     MemoryContext per_query_ctx;
    9437             :     MemoryContext oldcontext;
    9438             : 
    9439             :     /* Check to see if caller supports us returning a tuplestore */
    9440           4 :     if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
    9441           0 :         ereport(ERROR,
    9442             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    9443             :                  errmsg("set-valued function called in context that cannot accept a set")));
    9444           4 :     if (!(rsinfo->allowedModes & SFRM_Materialize))
    9445           0 :         ereport(ERROR,
    9446             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    9447             :                  errmsg("materialize mode required, but it is not " \
    9448             :                         "allowed in this context")));
    9449             : 
    9450             :     /* Scan the config files using current context as workspace */
    9451           4 :     conf = ProcessConfigFileInternal(PGC_SIGHUP, false, DEBUG3);
    9452             : 
    9453             :     /* Switch into long-lived context to construct returned data structures */
    9454           4 :     per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
    9455           4 :     oldcontext = MemoryContextSwitchTo(per_query_ctx);
    9456             : 
    9457             :     /* Build a tuple descriptor for our result type */
    9458           4 :     tupdesc = CreateTemplateTupleDesc(NUM_PG_FILE_SETTINGS_ATTS);
    9459           4 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "sourcefile",
    9460             :                        TEXTOID, -1, 0);
    9461           4 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "sourceline",
    9462             :                        INT4OID, -1, 0);
    9463           4 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "seqno",
    9464             :                        INT4OID, -1, 0);
    9465           4 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "name",
    9466             :                        TEXTOID, -1, 0);
    9467           4 :     TupleDescInitEntry(tupdesc, (AttrNumber) 5, "setting",
    9468             :                        TEXTOID, -1, 0);
    9469           4 :     TupleDescInitEntry(tupdesc, (AttrNumber) 6, "applied",
    9470             :                        BOOLOID, -1, 0);
    9471           4 :     TupleDescInitEntry(tupdesc, (AttrNumber) 7, "error",
    9472             :                        TEXTOID, -1, 0);
    9473             : 
    9474             :     /* Build a tuplestore to return our results in */
    9475           4 :     tupstore = tuplestore_begin_heap(true, false, work_mem);
    9476           4 :     rsinfo->returnMode = SFRM_Materialize;
    9477           4 :     rsinfo->setResult = tupstore;
    9478           4 :     rsinfo->setDesc = tupdesc;
    9479             : 
    9480             :     /* The rest can be done in short-lived context */
    9481           4 :     MemoryContextSwitchTo(oldcontext);
    9482             : 
    9483             :     /* Process the results and create a tuplestore */
    9484          70 :     for (seqno = 1; conf != NULL; conf = conf->next, seqno++)
    9485             :     {
    9486             :         Datum       values[NUM_PG_FILE_SETTINGS_ATTS];
    9487             :         bool        nulls[NUM_PG_FILE_SETTINGS_ATTS];
    9488             : 
    9489          66 :         memset(values, 0, sizeof(values));
    9490          66 :         memset(nulls, 0, sizeof(nulls));
    9491             : 
    9492             :         /* sourcefile */
    9493          66 :         if (conf->filename)
    9494          66 :             values[0] = PointerGetDatum(cstring_to_text(conf->filename));
    9495             :         else
    9496           0 :             nulls[0] = true;
    9497             : 
    9498             :         /* sourceline (not meaningful if no sourcefile) */
    9499          66 :         if (conf->filename)
    9500          66 :             values[1] = Int32GetDatum(conf->sourceline);
    9501             :         else
    9502           0 :             nulls[1] = true;
    9503             : 
    9504             :         /* seqno */
    9505          66 :         values[2] = Int32GetDatum(seqno);
    9506             : 
    9507             :         /* name */
    9508          66 :         if (conf->name)
    9509          66 :             values[3] = PointerGetDatum(cstring_to_text(conf->name));
    9510             :         else
    9511           0 :             nulls[3] = true;
    9512             : 
    9513             :         /* setting */
    9514          66 :         if (conf->value)
    9515          66 :             values[4] = PointerGetDatum(cstring_to_text(conf->value));
    9516             :         else
    9517           0 :             nulls[4] = true;
    9518             : 
    9519             :         /* applied */
    9520          66 :         values[5] = BoolGetDatum(conf->applied);
    9521             : 
    9522             :         /* error */
    9523          66 :         if (conf->errmsg)
    9524           0 :             values[6] = PointerGetDatum(cstring_to_text(conf->errmsg));
    9525             :         else
    9526          66 :             nulls[6] = true;
    9527             : 
    9528             :         /* shove row into tuplestore */
    9529          66 :         tuplestore_putvalues(tupstore, tupdesc, values, nulls);
    9530             :     }
    9531             : 
    9532             :     tuplestore_donestoring(tupstore);
    9533             : 
    9534           4 :     return (Datum) 0;
    9535             : }
    9536             : 
    9537             : static char *
    9538      110062 : _ShowOption(struct config_generic *record, bool use_units)
    9539             : {
    9540             :     char        buffer[256];
    9541             :     const char *val;
    9542             : 
    9543      110062 :     switch (record->vartype)
    9544             :     {
    9545             :         case PGC_BOOL:
    9546             :             {
    9547       25708 :                 struct config_bool *conf = (struct config_bool *) record;
    9548             : 
    9549       25708 :                 if (conf->show_hook)
    9550           0 :                     val = conf->show_hook();
    9551             :                 else
    9552       25708 :                     val = *conf->variable ? "on" : "off";
    9553             :             }
    9554       25708 :             break;
    9555             : 
    9556             :         case PGC_INT:
    9557             :             {
    9558        3874 :                 struct config_int *conf = (struct config_int *) record;
    9559             : 
    9560        3874 :                 if (conf->show_hook)
    9561         430 :                     val = conf->show_hook();
    9562             :                 else
    9563             :                 {
    9564             :                     /*
    9565             :                      * Use int64 arithmetic to avoid overflows in units
    9566             :                      * conversion.
    9567             :                      */
    9568        3444 :                     int64       result = *conf->variable;
    9569             :                     const char *unit;
    9570             : 
    9571        3444 :                     if (use_units && result > 0 && (record->flags & GUC_UNIT))
    9572         300 :                         convert_int_from_base_unit(result,
    9573         300 :                                                    record->flags & GUC_UNIT,
    9574             :                                                    &result, &unit);
    9575             :                     else
    9576        3144 :                         unit = "";
    9577             : 
    9578        3444 :                     snprintf(buffer, sizeof(buffer), INT64_FORMAT "%s",
    9579             :                              result, unit);
    9580        3444 :                     val = buffer;
    9581             :                 }
    9582             :             }
    9583        3874 :             break;
    9584             : 
    9585             :         case PGC_REAL:
    9586             :             {
    9587         884 :                 struct config_real *conf = (struct config_real *) record;
    9588             : 
    9589         884 :                 if (conf->show_hook)
    9590          28 :                     val = conf->show_hook();
    9591             :                 else
    9592             :                 {
    9593         856 :                     double      result = *conf->variable;
    9594             :                     const char *unit;
    9595             : 
    9596         856 :                     if (use_units && result > 0 && (record->flags & GUC_UNIT))
    9597         180 :                         convert_real_from_base_unit(result,
    9598         180 :                                                     record->flags & GUC_UNIT,
    9599             :                                                     &result, &unit);
    9600             :                     else
    9601         676 :                         unit = "";
    9602             : 
    9603         856 :                     snprintf(buffer, sizeof(buffer), "%g%s",
    9604             :                              result, unit);
    9605         856 :                     val = buffer;
    9606             :                 }
    9607             :             }
    9608         884 :             break;
    9609             : 
    9610             :         case PGC_STRING:
    9611             :             {
    9612       62198 :                 struct config_string *conf = (struct config_string *) record;
    9613             : 
    9614       62198 :                 if (conf->show_hook)
    9615        7036 :                     val = conf->show_hook();
    9616       55162 :                 else if (*conf->variable && **conf->variable)
    9617       53068 :                     val = *conf->variable;
    9618             :                 else
    9619        2094 :                     val = "";
    9620             :             }
    9621       62198 :             break;
    9622             : 
    9623             :         case PGC_ENUM:
    9624             :             {
    9625       17398 :                 struct config_enum *conf = (struct config_enum *) record;
    9626             : 
    9627       17398 :                 if (conf->show_hook)
    9628           0 :                     val = conf->show_hook();
    9629             :                 else
    9630       17398 :                     val = config_enum_lookup_by_value(conf, *conf->variable);
    9631             :             }
    9632       17398 :             break;
    9633             : 
    9634             :         default:
    9635             :             /* just to keep compiler quiet */
    9636           0 :             val = "???";
    9637           0 :             break;
    9638             :     }
    9639             : 
    9640      110062 :     return pstrdup(val);
    9641             : }
    9642             : 
    9643             : 
    9644             : #ifdef EXEC_BACKEND
    9645             : 
    9646             : /*
    9647             :  *  These routines dump out all non-default GUC options into a binary
    9648             :  *  file that is read by all exec'ed backends.  The format is:
    9649             :  *
    9650             :  *      variable name, string, null terminated
    9651             :  *      variable value, string, null terminated
    9652             :  *      variable sourcefile, string, null terminated (empty if none)
    9653             :  *      variable sourceline, integer
    9654             :  *      variable source, integer
    9655             :  *      variable scontext, integer
    9656             :  */
    9657             : static void
    9658             : write_one_nondefault_variable(FILE *fp, struct config_generic *gconf)
    9659             : {
    9660             :     if (gconf->source == PGC_S_DEFAULT)
    9661             :         return;
    9662             : 
    9663             :     fprintf(fp, "%s", gconf->name);
    9664             :     fputc(0, fp);
    9665             : 
    9666             :     switch (gconf->vartype)
    9667             :     {
    9668             :         case PGC_BOOL:
    9669             :             {
    9670             :                 struct config_bool *conf = (struct config_bool *) gconf;
    9671             : 
    9672             :                 if (*conf->variable)
    9673             :                     fprintf(fp, "true");
    9674             :                 else
    9675             :                     fprintf(fp, "false");
    9676             :             }
    9677             :             break;
    9678             : 
    9679             :         case PGC_INT:
    9680             :             {
    9681             :                 struct config_int *conf = (struct config_int *) gconf;
    9682             : 
    9683             :                 fprintf(fp, "%d", *conf->variable);
    9684             :             }
    9685             :             break;
    9686             : 
    9687             :         case PGC_REAL:
    9688             :             {
    9689             :                 struct config_real *conf = (struct config_real *) gconf;
    9690             : 
    9691             :                 fprintf(fp, "%.17g", *conf->variable);
    9692             :             }
    9693             :             break;
    9694             : 
    9695             :         case PGC_STRING:
    9696             :             {
    9697             :                 struct config_string *conf = (struct config_string *) gconf;
    9698             : 
    9699             :                 fprintf(fp, "%s", *conf->variable);
    9700             :             }
    9701             :             break;
    9702             : 
    9703             :         case PGC_ENUM:
    9704             :             {
    9705             :                 struct config_enum *conf = (struct config_enum *) gconf;
    9706             : 
    9707             :                 fprintf(fp, "%s",
    9708             :                         config_enum_lookup_by_value(conf, *conf->variable));
    9709             :             }
    9710             :             break;
    9711             :     }
    9712             : 
    9713             :     fputc(0, fp);
    9714             : 
    9715             :     if (gconf->sourcefile)
    9716             :         fprintf(fp, "%s", gconf->sourcefile);
    9717             :     fputc(0, fp);
    9718             : 
    9719             :     fwrite(&gconf->sourceline, 1, sizeof(gconf->sourceline), fp);
    9720             :     fwrite(&gconf->source, 1, sizeof(gconf->source), fp);
    9721             :     fwrite(&gconf->scontext, 1, sizeof(gconf->scontext), fp);
    9722             : }
    9723             : 
    9724             : void
    9725             : write_nondefault_variables(GucContext context)
    9726             : {
    9727             :     int         elevel;
    9728             :     FILE       *fp;
    9729             :     int         i;
    9730             : 
    9731             :     Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
    9732             : 
    9733             :     elevel = (context == PGC_SIGHUP) ? LOG : ERROR;
    9734             : 
    9735             :     /*
    9736             :      * Open file
    9737             :      */
    9738             :     fp = AllocateFile(CONFIG_EXEC_PARAMS_NEW, "w");
    9739             :     if (!fp)
    9740             :     {
    9741             :         ereport(elevel,
    9742             :                 (errcode_for_file_access(),
    9743             :                  errmsg("could not write to file \"%s\": %m",
    9744             :                         CONFIG_EXEC_PARAMS_NEW)));
    9745             :         return;
    9746             :     }
    9747             : 
    9748             :     for (i = 0; i < num_guc_variables; i++)
    9749             :     {
    9750             :         write_one_nondefault_variable(fp, guc_variables[i]);
    9751             :     }
    9752             : 
    9753             :     if (FreeFile(fp))
    9754             :     {
    9755             :         ereport(elevel,
    9756             :                 (errcode_for_file_access(),
    9757             :                  errmsg("could not write to file \"%s\": %m",
    9758             :                         CONFIG_EXEC_PARAMS_NEW)));
    9759             :         return;
    9760             :     }
    9761             : 
    9762             :     /*
    9763             :      * Put new file in place.  This could delay on Win32, but we don't hold
    9764             :      * any exclusive locks.
    9765             :      */
    9766             :     rename(CONFIG_EXEC_PARAMS_NEW, CONFIG_EXEC_PARAMS);
    9767             : }
    9768             : 
    9769             : 
    9770             : /*
    9771             :  *  Read string, including null byte from file
    9772             :  *
    9773             :  *  Return NULL on EOF and nothing read
    9774             :  */
    9775             : static char *
    9776             : read_string_with_null(FILE *fp)
    9777             : {
    9778             :     int         i = 0,
    9779             :                 ch,
    9780             :                 maxlen = 256;
    9781             :     char       *str = NULL;
    9782             : 
    9783             :     do
    9784             :     {
    9785             :         if ((ch = fgetc(fp)) == EOF)
    9786             :         {
    9787             :             if (i == 0)
    9788             :                 return NULL;
    9789             :             else
    9790             :                 elog(FATAL, "invalid format of exec config params file");
    9791             :         }
    9792             :         if (i == 0)
    9793             :             str = guc_malloc(FATAL, maxlen);
    9794             :         else if (i == maxlen)
    9795             :             str = guc_realloc(FATAL, str, maxlen *= 2);
    9796             :         str[i++] = ch;
    9797             :     } while (ch != 0);
    9798             : 
    9799             :     return str;
    9800             : }
    9801             : 
    9802             : 
    9803             : /*
    9804             :  *  This routine loads a previous postmaster dump of its non-default
    9805             :  *  settings.
    9806             :  */
    9807             : void
    9808             : read_nondefault_variables(void)
    9809             : {
    9810             :     FILE       *fp;
    9811             :     char       *varname,
    9812             :                *varvalue,
    9813             :                *varsourcefile;
    9814             :     int         varsourceline;
    9815             :     GucSource   varsource;
    9816             :     GucContext  varscontext;
    9817             : 
    9818             :     /*
    9819             :      * Assert that PGC_BACKEND/PGC_SU_BACKEND case in set_config_option() will
    9820             :      * do the right thing.
    9821             :      */
    9822             :     Assert(IsInitProcessingMode());
    9823             : 
    9824             :     /*
    9825             :      * Open file
    9826             :      */
    9827             :     fp = AllocateFile(CONFIG_EXEC_PARAMS, "r");
    9828             :     if (!fp)
    9829             :     {
    9830             :         /* File not found is fine */
    9831             :         if (errno != ENOENT)
    9832             :             ereport(FATAL,
    9833             :                     (errcode_for_file_access(),
    9834             :                      errmsg("could not read from file \"%s\": %m",
    9835             :                             CONFIG_EXEC_PARAMS)));
    9836             :         return;
    9837             :     }
    9838             : 
    9839             :     for (;;)
    9840             :     {
    9841             :         struct config_generic *record;
    9842             : 
    9843             :         if ((varname = read_string_with_null(fp)) == NULL)
    9844             :             break;
    9845             : 
    9846             :         if ((record = find_option(varname, true, FATAL)) == NULL)
    9847             :             elog(FATAL, "failed to locate variable \"%s\" in exec config params file", varname);
    9848             : 
    9849             :         if ((varvalue = read_string_with_null(fp)) == NULL)
    9850             :             elog(FATAL, "invalid format of exec config params file");
    9851             :         if ((varsourcefile = read_string_with_null(fp)) == NULL)
    9852             :             elog(FATAL, "invalid format of exec config params file");
    9853             :         if (fread(&varsourceline, 1, sizeof(varsourceline), fp) != sizeof(varsourceline))
    9854             :             elog(FATAL, "invalid format of exec config params file");
    9855             :         if (fread(&varsource, 1, sizeof(varsource), fp) != sizeof(varsource))
    9856             :             elog(FATAL, "invalid format of exec config params file");
    9857             :         if (fread(&varscontext, 1, sizeof(varscontext), fp) != sizeof(varscontext))
    9858             :             elog(FATAL, "invalid format of exec config params file");
    9859             : 
    9860             :         (void) set_config_option(varname, varvalue,
    9861             :                                  varscontext, varsource,
    9862             :                                  GUC_ACTION_SET, true, 0, true);
    9863             :         if (varsourcefile[0])
    9864             :             set_config_sourcefile(varname, varsourcefile, varsourceline);
    9865             : 
    9866             :         free(varname);
    9867             :         free(varvalue);
    9868             :         free(varsourcefile);
    9869             :     }
    9870             : 
    9871             :     FreeFile(fp);
    9872             : }
    9873             : #endif                          /* EXEC_BACKEND */
    9874             : 
    9875             : /*
    9876             :  * can_skip_gucvar:
    9877             :  * When serializing, determine whether to skip this GUC.  When restoring, the
    9878             :  * negation of this test determines whether to restore the compiled-in default
    9879             :  * value before processing serialized values.
    9880             :  *
    9881             :  * A PGC_S_DEFAULT setting on the serialize side will typically match new
    9882             :  * postmaster children, but that can be false when got_SIGHUP == true and the
    9883             :  * pending configuration change modifies this setting.  Nonetheless, we omit
    9884             :  * PGC_S_DEFAULT settings from serialization and make up for that by restoring
    9885             :  * defaults before applying serialized values.
    9886             :  *
    9887             :  * PGC_POSTMASTER variables always have the same value in every child of a
    9888             :  * particular postmaster.  Most PGC_INTERNAL variables are compile-time
    9889             :  * constants; a few, like server_encoding and lc_ctype, are handled specially
    9890             :  * outside the serialize/restore procedure.  Therefore, SerializeGUCState()
    9891             :  * never sends these, and RestoreGUCState() never changes them.
    9892             :  *
    9893             :  * Role is a special variable in the sense that its current value can be an
    9894             :  * invalid value and there are multiple ways by which that can happen (like
    9895             :  * after setting the role, someone drops it).  So we handle it outside of
    9896             :  * serialize/restore machinery.
    9897             :  */
    9898             : static bool
    9899      841980 : can_skip_gucvar(struct config_generic *gconf)
    9900             : {
    9901     1541180 :     return gconf->context == PGC_POSTMASTER ||
    9902     1559076 :         gconf->context == PGC_INTERNAL || gconf->source == PGC_S_DEFAULT ||
    9903       64624 :         strcmp(gconf->name, "role") == 0;
    9904             : }
    9905             : 
    9906             : /*
    9907             :  * estimate_variable_size:
    9908             :  *      Compute space needed for dumping the given GUC variable.
    9909             :  *
    9910             :  * It's OK to overestimate, but not to underestimate.
    9911             :  */
    9912             : static Size
    9913      158840 : estimate_variable_size(struct config_generic *gconf)
    9914             : {
    9915             :     Size        size;
    9916      158840 :     Size        valsize = 0;
    9917             : 
    9918      158840 :     if (can_skip_gucvar(gconf))
    9919      144336 :         return 0;
    9920             : 
    9921             :     /* Name, plus trailing zero byte. */
    9922       14504 :     size = strlen(gconf->name) + 1;
    9923             : 
    9924             :     /* Get the maximum display length of the GUC value. */
    9925       14504 :     switch (gconf->vartype)
    9926             :     {
    9927             :         case PGC_BOOL:
    9928             :             {
    9929        2782 :                 valsize = 5;    /* max(strlen('true'), strlen('false')) */
    9930             :             }
    9931        2782 :             break;
    9932             : 
    9933             :         case PGC_INT:
    9934             :             {
    9935        3296 :                 struct config_int *conf = (struct config_int *) gconf;
    9936             : 
    9937             :                 /*
    9938             :                  * Instead of getting the exact display length, use max
    9939             :                  * length.  Also reduce the max length for typical ranges of
    9940             :                  * small values.  Maximum value is 2147483647, i.e. 10 chars.
    9941             :                  * Include one byte for sign.
    9942             :                  */
    9943        3296 :                 if (Abs(*conf->variable) < 1000)
    9944        2510 :                     valsize = 3 + 1;
    9945             :                 else
    9946         786 :                     valsize = 10 + 1;
    9947             :             }
    9948        3296 :             break;
    9949             : 
    9950             :         case PGC_REAL:
    9951             :             {
    9952             :                 /*
    9953             :                  * We are going to print it with %e with REALTYPE_PRECISION
    9954             :                  * fractional digits.  Account for sign, leading digit,
    9955             :                  * decimal point, and exponent with up to 3 digits.  E.g.
    9956             :                  * -3.99329042340000021e+110
    9957             :                  */
    9958         796 :                 valsize = 1 + 1 + 1 + REALTYPE_PRECISION + 5;
    9959             :             }
    9960         796 :             break;
    9961             : 
    9962             :         case PGC_STRING:
    9963             :             {
    9964        6136 :                 struct config_string *conf = (struct config_string *) gconf;
    9965             : 
    9966             :                 /*
    9967             :                  * If the value is NULL, we transmit it as an empty string.
    9968             :                  * Although this is not physically the same value, GUC
    9969             :                  * generally treats a NULL the same as empty string.
    9970             :                  */
    9971        6136 :                 if (*conf->variable)
    9972        6136 :                     valsize = strlen(*conf->variable);
    9973             :                 else
    9974           0 :                     valsize = 0;
    9975             :             }
    9976        6136 :             break;
    9977             : 
    9978             :         case PGC_ENUM:
    9979             :             {
    9980        1494 :                 struct config_enum *conf = (struct config_enum *) gconf;
    9981             : 
    9982        1494 :                 valsize = strlen(config_enum_lookup_by_value(conf, *conf->variable));
    9983             :             }
    9984        1494 :             break;
    9985             :     }
    9986             : 
    9987             :     /* Allow space for terminating zero-byte for value */
    9988       14504 :     size = add_size(size, valsize + 1);
    9989             : 
    9990       14504 :     if (gconf->sourcefile)
    9991        6410 :         size = add_size(size, strlen(gconf->sourcefile));
    9992             : 
    9993             :     /* Allow space for terminating zero-byte for sourcefile */
    9994       14504 :     size = add_size(size, 1);
    9995             : 
    9996             :     /* Include line whenever file is nonempty. */
    9997       14504 :     if (gconf->sourcefile && gconf->sourcefile[0])
    9998        6410 :         size = add_size(size, sizeof(gconf->sourceline));
    9999             : 
   10000       14504 :     size = add_size(size, sizeof(gconf->source));
   10001       14504 :     size = add_size(size, sizeof(gconf->scontext));
   10002             : 
   10003       14504 :     return size;
   10004             : }
   10005             : 
   10006             : /*
   10007             :  * EstimateGUCStateSpace:
   10008             :  * Returns the size needed to store the GUC state for the current process
   10009             :  */
   10010             : Size
   10011         490 : EstimateGUCStateSpace(void)
   10012             : {
   10013             :     Size        size;
   10014             :     int         i;
   10015             : 
   10016             :     /* Add space reqd for saving the data size of the guc state */
   10017         490 :     size = sizeof(Size);
   10018             : 
   10019             :     /* Add up the space needed for each GUC variable */
   10020      159330 :     for (i = 0; i < num_guc_variables; i++)
   10021      158840 :         size = add_size(size,
   10022      158840 :                         estimate_variable_size(guc_variables[i]));
   10023             : 
   10024         490 :     return size;
   10025             : }
   10026             : 
   10027             : /*
   10028             :  * do_serialize:
   10029             :  * Copies the formatted string into the destination.  Moves ahead the
   10030             :  * destination pointer, and decrements the maxbytes by that many bytes. If
   10031             :  * maxbytes is not sufficient to copy the string, error out.
   10032             :  */
   10033             : static void
   10034       43512 : do_serialize(char **destptr, Size *maxbytes, const char *fmt,...)
   10035             : {
   10036             :     va_list     vargs;
   10037             :     int         n;
   10038             : 
   10039       43512 :     if (*maxbytes <= 0)
   10040           0 :         elog(ERROR, "not enough space to serialize GUC state");
   10041             : 
   10042       43512 :     va_start(vargs, fmt);
   10043       43512 :     n = vsnprintf(*destptr, *maxbytes, fmt, vargs);
   10044       43512 :     va_end(vargs);
   10045             : 
   10046       43512 :     if (n < 0)
   10047             :     {
   10048             :         /* Shouldn't happen. Better show errno description. */
   10049           0 :         elog(ERROR, "vsnprintf failed: %m with format string \"%s\"", fmt);
   10050             :     }
   10051       43512 :     if (n >= *maxbytes)
   10052             :     {
   10053             :         /* This shouldn't happen either, really. */
   10054           0 :         elog(ERROR, "not enough space to serialize GUC state");
   10055             :     }
   10056             : 
   10057             :     /* Shift the destptr ahead of the null terminator */
   10058       43512 :     *destptr += n + 1;
   10059       43512 :     *maxbytes -= n + 1;
   10060       43512 : }
   10061             : 
   10062             : /* Binary copy version of do_serialize() */
   10063             : static void
   10064       35418 : do_serialize_binary(char **destptr, Size *maxbytes, void *val, Size valsize)
   10065             : {
   10066       35418 :     if (valsize > *maxbytes)
   10067           0 :         elog(ERROR, "not enough space to serialize GUC state");
   10068             : 
   10069       35418 :     memcpy(*destptr, val, valsize);
   10070       35418 :     *destptr += valsize;
   10071       35418 :     *maxbytes -= valsize;
   10072       35418 : }
   10073             : 
   10074             : /*
   10075             :  * serialize_variable:
   10076             :  * Dumps name, value and other information of a GUC variable into destptr.
   10077             :  */
   10078             : static void
   10079      158840 : serialize_variable(char **destptr, Size *maxbytes,
   10080             :                    struct config_generic *gconf)
   10081             : {
   10082      158840 :     if (can_skip_gucvar(gconf))
   10083      144336 :         return;
   10084             : 
   10085       14504 :     do_serialize(destptr, maxbytes, "%s", gconf->name);
   10086             : 
   10087       14504 :     switch (gconf->vartype)
   10088             :     {
   10089             :         case PGC_BOOL:
   10090             :             {
   10091        2782 :                 struct config_bool *conf = (struct config_bool *) gconf;
   10092             : 
   10093        2782 :                 do_serialize(destptr, maxbytes,
   10094        2782 :                              (*conf->variable ? "true" : "false"));
   10095             :             }
   10096        2782 :             break;
   10097             : 
   10098             :         case PGC_INT:
   10099             :             {
   10100        3296 :                 struct config_int *conf = (struct config_int *) gconf;
   10101             : 
   10102        3296 :                 do_serialize(destptr, maxbytes, "%d", *conf->variable);
   10103             :             }
   10104        3296 :             break;
   10105             : 
   10106             :         case PGC_REAL:
   10107             :             {
   10108         796 :                 struct config_real *conf = (struct config_real *) gconf;
   10109             : 
   10110         796 :                 do_serialize(destptr, maxbytes, "%.*e",
   10111         796 :                              REALTYPE_PRECISION, *conf->variable);
   10112             :             }
   10113         796 :             break;
   10114             : 
   10115             :         case PGC_STRING:
   10116             :             {
   10117        6136 :                 struct config_string *conf = (struct config_string *) gconf;
   10118             : 
   10119             :                 /* NULL becomes empty string, see estimate_variable_size() */
   10120       12272 :                 do_serialize(destptr, maxbytes, "%s",
   10121       12272 :                              *conf->variable ? *conf->variable : "");
   10122             :             }
   10123        6136 :             break;
   10124             : 
   10125             :         case PGC_ENUM:
   10126             :             {
   10127        1494 :                 struct config_enum *conf = (struct config_enum *) gconf;
   10128             : 
   10129        1494 :                 do_serialize(destptr, maxbytes, "%s",
   10130        1494 :                              config_enum_lookup_by_value(conf, *conf->variable));
   10131             :             }
   10132        1494 :             break;
   10133             :     }
   10134             : 
   10135       14504 :     do_serialize(destptr, maxbytes, "%s",
   10136       14504 :                  (gconf->sourcefile ? gconf->sourcefile : ""));
   10137             : 
   10138       14504 :     if (gconf->sourcefile && gconf->sourcefile[0])
   10139        6410 :         do_serialize_binary(destptr, maxbytes, &gconf->sourceline,
   10140             :                             sizeof(gconf->sourceline));
   10141             : 
   10142       14504 :     do_serialize_binary(destptr, maxbytes, &gconf->source,
   10143             :                         sizeof(gconf->source));
   10144       14504 :     do_serialize_binary(destptr, maxbytes, &gconf->scontext,
   10145             :                         sizeof(gconf->scontext));
   10146             : }
   10147             : 
   10148             : /*
   10149             :  * SerializeGUCState:
   10150             :  * Dumps the complete GUC state onto the memory location at start_address.
   10151             :  */
   10152             : void
   10153         490 : SerializeGUCState(Size maxsize, char *start_address)
   10154             : {
   10155             :     char       *curptr;
   10156             :     Size        actual_size;
   10157             :     Size        bytes_left;
   10158             :     int         i;
   10159             : 
   10160             :     /* Reserve space for saving the actual size of the guc state */
   10161             :     Assert(maxsize > sizeof(actual_size));
   10162         490 :     curptr = start_address + sizeof(actual_size);
   10163         490 :     bytes_left = maxsize - sizeof(actual_size);
   10164             : 
   10165      159330 :     for (i = 0; i < num_guc_variables; i++)
   10166      158840 :         serialize_variable(&curptr, &bytes_left, guc_variables[i]);
   10167             : 
   10168             :     /* Store actual size without assuming alignment of start_address. */
   10169         490 :     actual_size = maxsize - bytes_left - sizeof(actual_size);
   10170         490 :     memcpy(start_address, &actual_size, sizeof(actual_size));
   10171         490 : }
   10172             : 
   10173             : /*
   10174             :  * read_gucstate:
   10175             :  * Actually it does not read anything, just returns the srcptr. But it does
   10176             :  * move the srcptr past the terminating zero byte, so that the caller is ready
   10177             :  * to read the next string.
   10178             :  */
   10179             : static char *
   10180      150342 : read_gucstate(char **srcptr, char *srcend)
   10181             : {
   10182      150342 :     char       *retptr = *srcptr;
   10183             :     char       *ptr;
   10184             : 
   10185      150342 :     if (*srcptr >= srcend)
   10186           0 :         elog(ERROR, "incomplete GUC state");
   10187             : 
   10188             :     /* The string variables are all null terminated */
   10189      150342 :     for (ptr = *srcptr; ptr < srcend && *ptr != '\0'; ptr++)
   10190             :         ;
   10191             : 
   10192      150342 :     if (ptr >= srcend)
   10193           0 :         elog(ERROR, "could not find null terminator in GUC state");
   10194             : 
   10195             :     /* Set the new position to the byte following the terminating NUL */
   10196      150342 :     *srcptr = ptr + 1;
   10197             : 
   10198      150342 :     return retptr;
   10199             : }
   10200             : 
   10201             : /* Binary read version of read_gucstate(). Copies into dest */
   10202             : static void
   10203      121296 : read_gucstate_binary(char **srcptr, char *srcend, void *dest, Size size)
   10204             : {
   10205      121296 :     if (*srcptr + size > srcend)
   10206           0 :         elog(ERROR, "incomplete GUC state");
   10207             : 
   10208      121296 :     memcpy(dest, *srcptr, size);
   10209      121296 :     *srcptr += size;
   10210      121296 : }
   10211             : 
   10212             : /*
   10213             :  * RestoreGUCState:
   10214             :  * Reads the GUC state at the specified address and updates the GUCs with the
   10215             :  * values read from the GUC state.
   10216             :  */
   10217             : void
   10218        1616 : RestoreGUCState(void *gucstate)
   10219             : {
   10220             :     char       *varname,
   10221             :                *varvalue,
   10222             :                *varsourcefile;
   10223             :     int         varsourceline;
   10224             :     GucSource   varsource;
   10225             :     GucContext  varscontext;
   10226        1616 :     char       *srcptr = (char *) gucstate;
   10227             :     char       *srcend;
   10228             :     Size        len;
   10229             :     int         i;
   10230             : 
   10231             :     /* See comment at can_skip_gucvar(). */
   10232      525916 :     for (i = 0; i < num_guc_variables; i++)
   10233      524300 :         if (!can_skip_gucvar(guc_variables[i]))
   10234       35608 :             InitializeOneGUCOption(guc_variables[i]);
   10235             : 
   10236             :     /* First item is the length of the subsequent data */
   10237        1616 :     memcpy(&len, gucstate, sizeof(len));
   10238             : 
   10239        1616 :     srcptr += sizeof(len);
   10240        1616 :     srcend = srcptr + len;
   10241             : 
   10242       53346 :     while (srcptr < srcend)
   10243             :     {
   10244             :         int         result;
   10245             : 
   10246       50114 :         varname = read_gucstate(&srcptr, srcend);
   10247       50114 :         varvalue = read_gucstate(&srcptr, srcend);
   10248       50114 :         varsourcefile = read_gucstate(&srcptr, srcend);
   10249       50114 :         if (varsourcefile[0])
   10250       21068 :             read_gucstate_binary(&srcptr, srcend,
   10251             :                                  &varsourceline, sizeof(varsourceline));
   10252             :         else
   10253       29046 :             varsourceline = 0;
   10254       50114 :         read_gucstate_binary(&srcptr, srcend,
   10255             :                              &varsource, sizeof(varsource));
   10256       50114 :         read_gucstate_binary(&srcptr, srcend,
   10257             :                              &varscontext, sizeof(varscontext));
   10258             : 
   10259       50114 :         result = set_config_option(varname, varvalue, varscontext, varsource,
   10260             :                                    GUC_ACTION_SET, true, ERROR, true);
   10261       50114 :         if (result <= 0)
   10262           0 :             ereport(ERROR,
   10263             :                     (errcode(ERRCODE_INTERNAL_ERROR),
   10264             :                      errmsg("parameter \"%s\" could not be set", varname)));
   10265       50114 :         if (varsourcefile[0])
   10266       21068 :             set_config_sourcefile(varname, varsourcefile, varsourceline);
   10267             :     }
   10268        1616 : }
   10269             : 
   10270             : /*
   10271             :  * A little "long argument" simulation, although not quite GNU
   10272             :  * compliant. Takes a string of the form "some-option=some value" and
   10273             :  * returns name = "some_option" and value = "some value" in malloc'ed
   10274             :  * storage. Note that '-' is converted to '_' in the option name. If
   10275             :  * there is no '=' in the input string then value will be NULL.
   10276             :  */
   10277             : void
   10278       32206 : ParseLongOption(const char *string, char **name, char **value)
   10279             : {
   10280             :     size_t      equal_pos;
   10281             :     char       *cp;
   10282             : 
   10283             :     AssertArg(string);
   10284             :     AssertArg(name);
   10285             :     AssertArg(value);
   10286             : 
   10287       32206 :     equal_pos = strcspn(string, "=");
   10288             : 
   10289       32206 :     if (string[equal_pos] == '=')
   10290             :     {
   10291       32206 :         *name = guc_malloc(FATAL, equal_pos + 1);
   10292       32206 :         strlcpy(*name, string, equal_pos + 1);
   10293             : 
   10294       32206 :         *value = guc_strdup(FATAL, &string[equal_pos + 1]);
   10295             :     }
   10296             :     else
   10297             :     {
   10298             :         /* no equal sign in string */
   10299           0 :         *name = guc_strdup(FATAL, string);
   10300           0 :         *value = NULL;
   10301             :     }
   10302             : 
   10303      441858 :     for (cp = *name; *cp; cp++)
   10304      409652 :         if (*cp == '-')
   10305         524 :             *cp = '_';
   10306       32206 : }
   10307             : 
   10308             : 
   10309             : /*
   10310             :  * Handle options fetched from pg_db_role_setting.setconfig,
   10311             :  * pg_proc.proconfig, etc.  Caller must specify proper context/source/action.
   10312             :  *
   10313             :  * The array parameter must be an array of TEXT (it must not be NULL).
   10314             :  */
   10315             : void
   10316        4342 : ProcessGUCArray(ArrayType *array,
   10317             :                 GucContext context, GucSource source, GucAction action)
   10318             : {
   10319             :     int         i;
   10320             : 
   10321             :     Assert(array != NULL);
   10322             :     Assert(ARR_ELEMTYPE(array) == TEXTOID);
   10323             :     Assert(ARR_NDIM(array) == 1);
   10324             :     Assert(ARR_LBOUND(array)[0] == 1);
   10325             : 
   10326       30122 :     for (i = 1; i <= ARR_DIMS(array)[0]; i++)
   10327             :     {
   10328             :         Datum       d;
   10329             :         bool        isnull;
   10330             :         char       *s;
   10331             :         char       *name;
   10332             :         char       *value;
   10333             : 
   10334       25788 :         d = array_ref(array, 1, &i,
   10335             :                       -1 /* varlenarray */ ,
   10336             :                       -1 /* TEXT's typlen */ ,
   10337             :                       false /* TEXT's typbyval */ ,
   10338             :                       'i' /* TEXT's typalign */ ,
   10339             :                       &isnull);
   10340             : 
   10341       25788 :         if (isnull)
   10342           0 :             continue;
   10343             : 
   10344       25788 :         s = TextDatumGetCString(d);
   10345             : 
   10346       25788 :         ParseLongOption(s, &name, &value);
   10347       25788 :         if (!value)
   10348             :         {
   10349           0 :             ereport(WARNING,
   10350             :                     (errcode(ERRCODE_SYNTAX_ERROR),
   10351             :                      errmsg("could not parse setting for parameter \"%s\"",
   10352             :                             name)));
   10353           0 :             free(name);
   10354           0 :             continue;
   10355             :         }
   10356             : 
   10357       25788 :         (void) set_config_option(name, value,
   10358             :                                  context, source,
   10359             :                                  action, true, 0, false);
   10360             : 
   10361       25780 :         free(name);
   10362       25780 :         if (value)
   10363       25780 :             free(value);
   10364       25780 :         pfree(s);
   10365             :     }
   10366        4334 : }
   10367             : 
   10368             : 
   10369             : /*
   10370             :  * Add an entry to an option array.  The array parameter may be NULL
   10371             :  * to indicate the current table entry is NULL.
   10372             :  */
   10373             : ArrayType *
   10374         910 : GUCArrayAdd(ArrayType *array, const char *name, const char *value)
   10375             : {
   10376             :     struct config_generic *record;
   10377             :     Datum       datum;
   10378             :     char       *newval;
   10379             :     ArrayType  *a;
   10380             : 
   10381             :     Assert(name);
   10382             :     Assert(value);
   10383             : 
   10384             :     /* test if the option is valid and we're allowed to set it */
   10385         910 :     (void) validate_option_array_item(name, value, false);
   10386             : 
   10387             :     /* normalize name (converts obsolete GUC names to modern spellings) */
   10388         910 :     record = find_option(name, false, WARNING);
   10389         910 :     if (record)
   10390         910 :         name = record->name;
   10391             : 
   10392             :     /* build new item for array */
   10393         910 :     newval = psprintf("%s=%s", name, value);
   10394         910 :     datum = CStringGetTextDatum(newval);
   10395             : 
   10396         910 :     if (array)
   10397             :     {
   10398             :         int         index;
   10399             :         bool        isnull;
   10400             :         int         i;
   10401             : 
   10402             :         Assert(ARR_ELEMTYPE(array) == TEXTOID);
   10403             :         Assert(ARR_NDIM(array) == 1);
   10404             :         Assert(ARR_LBOUND(array)[0] == 1);
   10405             : 
   10406         712 :         index = ARR_DIMS(array)[0] + 1; /* add after end */
   10407             : 
   10408        2812 :         for (i = 1; i <= ARR_DIMS(array)[0]; i++)
   10409             :         {
   10410             :             Datum       d;
   10411             :             char       *current;
   10412             : 
   10413        2108 :             d = array_ref(array, 1, &i,
   10414             :                           -1 /* varlenarray */ ,
   10415             :                           -1 /* TEXT's typlen */ ,
   10416             :                           false /* TEXT's typbyval */ ,
   10417             :                           'i' /* TEXT's typalign */ ,
   10418             :                           &isnull);
   10419        2108 :             if (isnull)
   10420           0 :                 continue;
   10421        2108 :             current = TextDatumGetCString(d);
   10422             : 
   10423             :             /* check for match up through and including '=' */
   10424        2108 :             if (strncmp(current, newval, strlen(name) + 1) == 0)
   10425             :             {
   10426           8 :                 index = i;
   10427           8 :                 break;
   10428             :             }
   10429             :         }
   10430             : 
   10431         712 :         a = array_set(array, 1, &index,
   10432             :                       datum,
   10433             :                       false,
   10434             :                       -1 /* varlena array */ ,
   10435             :                       -1 /* TEXT's typlen */ ,
   10436             :                       false /* TEXT's typbyval */ ,
   10437             :                       'i' /* TEXT's typalign */ );
   10438             :     }
   10439             :     else
   10440         198 :         a = construct_array(&datum, 1,
   10441             :                             TEXTOID,
   10442             :                             -1, false, 'i');
   10443             : 
   10444         910 :     return a;
   10445             : }
   10446             : 
   10447             : 
   10448             : /*
   10449             :  * Delete an entry from an option array.  The array parameter may be NULL
   10450             :  * to indicate the current table entry is NULL.  Also, if the return value
   10451             :  * is NULL then a null should be stored.
   10452             :  */
   10453             : ArrayType *
   10454          20 : GUCArrayDelete(ArrayType *array, const char *name)
   10455             : {
   10456             :     struct config_generic *record;
   10457             :     ArrayType  *newarray;
   10458             :     int         i;
   10459             :     int         index;
   10460             : 
   10461             :     Assert(name);
   10462             : 
   10463             :     /* test if the option is valid and we're allowed to set it */
   10464          20 :     (void) validate_option_array_item(name, NULL, false);
   10465             : 
   10466             :     /* normalize name (converts obsolete GUC names to modern spellings) */
   10467          20 :     record = find_option(name, false, WARNING);
   10468          20 :     if (record)
   10469          20 :         name = record->name;
   10470             : 
   10471             :     /* if array is currently null, then surely nothing to delete */
   10472          20 :     if (!array)
   10473           0 :         return NULL;
   10474             : 
   10475          20 :     newarray = NULL;
   10476          20 :     index = 1;
   10477             : 
   10478          40 :     for (i = 1; i <= ARR_DIMS(array)[0]; i++)
   10479             :     {
   10480             :         Datum       d;
   10481             :         char       *val;
   10482             :         bool        isnull;
   10483             : 
   10484          20 :         d = array_ref(array, 1, &i,
   10485             :                       -1 /* varlenarray */ ,
   10486             :                       -1 /* TEXT's typlen */ ,
   10487             :                       false /* TEXT's typbyval */ ,
   10488             :                       'i' /* TEXT's typalign */ ,
   10489             :                       &isnull);
   10490          20 :         if (isnull)
   10491          20 :             continue;
   10492          20 :         val = TextDatumGetCString(d);
   10493             : 
   10494             :         /* ignore entry if it's what we want to delete */
   10495          20 :         if (strncmp(val, name, strlen(name)) == 0
   10496          20 :             && val[strlen(name)] == '=')
   10497          20 :             continue;
   10498             : 
   10499             :         /* else add it to the output array */
   10500           0 :         if (newarray)
   10501           0 :             newarray = array_set(newarray, 1, &index,
   10502             :                                  d,
   10503             :                                  false,
   10504             :                                  -1 /* varlenarray */ ,
   10505             :                                  -1 /* TEXT's typlen */ ,
   10506             :                                  false /* TEXT's typbyval */ ,
   10507             :                                  'i' /* TEXT's typalign */ );
   10508             :         else
   10509           0 :             newarray = construct_array(&d, 1,
   10510             :                                        TEXTOID,
   10511             :                                        -1, false, 'i');
   10512             : 
   10513           0 :         index++;
   10514             :     }
   10515             : 
   10516          20 :     return newarray;
   10517             : }
   10518             : 
   10519             : 
   10520             : /*
   10521             :  * Given a GUC array, delete all settings from it that our permission
   10522             :  * level allows: if superuser, delete them all; if regular user, only
   10523             :  * those that are PGC_USERSET
   10524             :  */
   10525             : ArrayType *
   10526           0 : GUCArrayReset(ArrayType *array)
   10527             : {
   10528             :     ArrayType  *newarray;
   10529             :     int         i;
   10530             :     int         index;
   10531             : 
   10532             :     /* if array is currently null, nothing to do */
   10533           0 :     if (!array)
   10534           0 :         return NULL;
   10535             : 
   10536             :     /* if we're superuser, we can delete everything, so just do it */
   10537           0 :     if (superuser())
   10538           0 :         return NULL;
   10539             : 
   10540           0 :     newarray = NULL;
   10541           0 :     index = 1;
   10542             : 
   10543           0 :     for (i = 1; i <= ARR_DIMS(array)[0]; i++)
   10544             :     {
   10545             :         Datum       d;
   10546             :         char       *val;
   10547             :         char       *eqsgn;
   10548             :         bool        isnull;
   10549             : 
   10550           0 :         d = array_ref(array, 1, &i,
   10551             :                       -1 /* varlenarray */ ,
   10552             :                       -1 /* TEXT's typlen */ ,
   10553             :                       false /* TEXT's typbyval */ ,
   10554             :                       'i' /* TEXT's typalign */ ,
   10555             :                       &isnull);
   10556           0 :         if (isnull)
   10557           0 :             continue;
   10558           0 :         val = TextDatumGetCString(d);
   10559             : 
   10560           0 :         eqsgn = strchr(val, '=');
   10561           0 :         *eqsgn = '\0';
   10562             : 
   10563             :         /* skip if we have permission to delete it */
   10564           0 :         if (validate_option_array_item(val, NULL, true))
   10565           0 :             continue;
   10566             : 
   10567             :         /* else add it to the output array */
   10568           0 :         if (newarray)
   10569           0 :             newarray = array_set(newarray, 1, &index,
   10570             :                                  d,
   10571             :                                  false,
   10572             :                                  -1 /* varlenarray */ ,
   10573             :                                  -1 /* TEXT's typlen */ ,
   10574             :                                  false /* TEXT's typbyval */ ,
   10575             :                                  'i' /* TEXT's typalign */ );
   10576             :         else
   10577           0 :             newarray = construct_array(&d, 1,
   10578             :                                        TEXTOID,
   10579             :                                        -1, false, 'i');
   10580             : 
   10581           0 :         index++;
   10582           0 :         pfree(val);
   10583             :     }
   10584             : 
   10585           0 :     return newarray;
   10586             : }
   10587             : 
   10588             : /*
   10589             :  * Validate a proposed option setting for GUCArrayAdd/Delete/Reset.
   10590             :  *
   10591             :  * name is the option name.  value is the proposed value for the Add case,
   10592             :  * or NULL for the Delete/Reset cases.  If skipIfNoPermissions is true, it's
   10593             :  * not an error to have no permissions to set the option.
   10594             :  *
   10595             :  * Returns true if OK, false if skipIfNoPermissions is true and user does not
   10596             :  * have permission to change this option (all other error cases result in an
   10597             :  * error being thrown).
   10598             :  */
   10599             : static bool
   10600         930 : validate_option_array_item(const char *name, const char *value,
   10601             :                            bool skipIfNoPermissions)
   10602             : 
   10603             : {
   10604             :     struct config_generic *gconf;
   10605             : 
   10606             :     /*
   10607             :      * There are three cases to consider:
   10608             :      *
   10609             :      * name is a known GUC variable.  Check the value normally, check
   10610             :      * permissions normally (i.e., allow if variable is USERSET, or if it's
   10611             :      * SUSET and user is superuser).
   10612             :      *
   10613             :      * name is not known, but exists or can be created as a placeholder (i.e.,
   10614             :      * it has a prefixed name).  We allow this case if you're a superuser,
   10615             :      * otherwise not.  Superusers are assumed to know what they're doing. We
   10616             :      * can't allow it for other users, because when the placeholder is
   10617             :      * resolved it might turn out to be a SUSET variable;
   10618             :      * define_custom_variable assumes we checked that.
   10619             :      *
   10620             :      * name is not known and can't be created as a placeholder.  Throw error,
   10621             :      * unless skipIfNoPermissions is true, in which case return false.
   10622             :      */
   10623         930 :     gconf = find_option(name, true, WARNING);
   10624         930 :     if (!gconf)
   10625             :     {
   10626             :         /* not known, failed to make a placeholder */
   10627           0 :         if (skipIfNoPermissions)
   10628           0 :             return false;
   10629           0 :         ereport(ERROR,
   10630             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
   10631             :                  errmsg("unrecognized configuration parameter \"%s\"",
   10632             :                         name)));
   10633             :     }
   10634             : 
   10635         930 :     if (gconf->flags & GUC_CUSTOM_PLACEHOLDER)
   10636             :     {
   10637             :         /*
   10638             :          * We cannot do any meaningful check on the value, so only permissions
   10639             :          * are useful to check.
   10640             :          */
   10641           0 :         if (superuser())
   10642           0 :             return true;
   10643           0 :         if (skipIfNoPermissions)
   10644           0 :             return false;
   10645           0 :         ereport(ERROR,
   10646             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
   10647             :                  errmsg("permission denied to set parameter \"%s\"", name)));
   10648             :     }
   10649             : 
   10650             :     /* manual permissions check so we can avoid an error being thrown */
   10651         930 :     if (gconf->context == PGC_USERSET)
   10652             :          /* ok */ ;
   10653         136 :     else if (gconf->context == PGC_SUSET && superuser())
   10654             :          /* ok */ ;
   10655           0 :     else if (skipIfNoPermissions)
   10656           0 :         return false;
   10657             :     /* if a permissions error should be thrown, let set_config_option do it */
   10658             : 
   10659             :     /* test for permissions and valid option value */
   10660         930 :     (void) set_config_option(name, value,
   10661         930 :                              superuser() ? PGC_SUSET : PGC_USERSET,
   10662             :                              PGC_S_TEST, GUC_ACTION_SET, false, 0, false);
   10663             : 
   10664         930 :     return true;
   10665             : }
   10666             : 
   10667             : 
   10668             : /*
   10669             :  * Called by check_hooks that want to override the normal
   10670             :  * ERRCODE_INVALID_PARAMETER_VALUE SQLSTATE for check hook failures.
   10671             :  *
   10672             :  * Note that GUC_check_errmsg() etc are just macros that result in a direct
   10673             :  * assignment to the associated variables.  That is ugly, but forced by the
   10674             :  * limitations of C's macro mechanisms.
   10675             :  */
   10676             : void
   10677          18 : GUC_check_errcode(int sqlerrcode)
   10678             : {
   10679          18 :     GUC_check_errcode_value = sqlerrcode;
   10680          18 : }
   10681             : 
   10682             : 
   10683             : /*
   10684             :  * Convenience functions to manage calling a variable's check_hook.
   10685             :  * These mostly take care of the protocol for letting check hooks supply
   10686             :  * portions of the error report on failure.
   10687             :  */
   10688             : 
   10689             : static bool
   10690      235844 : call_bool_check_hook(struct config_bool *conf, bool *newval, void **extra,
   10691             :                      GucSource source, int elevel)
   10692             : {
   10693             :     /* Quick success if no hook */
   10694      235844 :     if (!conf->check_hook)
   10695      208076 :         return true;
   10696             : 
   10697             :     /* Reset variables that might be set by hook */
   10698       27768 :     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
   10699       27768 :     GUC_check_errmsg_string = NULL;
   10700       27768 :     GUC_check_errdetail_string = NULL;
   10701       27768 :     GUC_check_errhint_string = NULL;
   10702             : 
   10703       27768 :     if (!conf->check_hook(newval, extra, source))
   10704             :     {
   10705          16 :         ereport(elevel,
   10706             :                 (errcode(GUC_check_errcode_value),
   10707             :                  GUC_check_errmsg_string ?
   10708             :                  errmsg_internal("%s", GUC_check_errmsg_string) :
   10709             :                  errmsg("invalid value for parameter \"%s\": %d",
   10710             :                         conf->gen.name, (int) *newval),
   10711             :                  GUC_check_errdetail_string ?
   10712             :                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
   10713             :                  GUC_check_errhint_string ?
   10714             :                  errhint("%s", GUC_check_errhint_string) : 0));
   10715             :         /* Flush any strings created in ErrorContext */
   10716           0 :         FlushErrorState();
   10717           0 :         return false;
   10718             :     }
   10719             : 
   10720       27752 :     return true;
   10721             : }
   10722             : 
   10723             : static bool
   10724      242306 : call_int_check_hook(struct config_int *conf, int *newval, void **extra,
   10725             :                     GucSource source, int elevel)
   10726             : {
   10727             :     /* Quick success if no hook */
   10728      242306 :     if (!conf->check_hook)
   10729      215362 :         return true;
   10730             : 
   10731             :     /* Reset variables that might be set by hook */
   10732       26944 :     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
   10733       26944 :     GUC_check_errmsg_string = NULL;
   10734       26944 :     GUC_check_errdetail_string = NULL;
   10735       26944 :     GUC_check_errhint_string = NULL;
   10736             : 
   10737       26944 :     if (!conf->check_hook(newval, extra, source))
   10738             :     {
   10739           0 :         ereport(elevel,
   10740             :                 (errcode(GUC_check_errcode_value),
   10741             :                  GUC_check_errmsg_string ?
   10742             :                  errmsg_internal("%s", GUC_check_errmsg_string) :
   10743             :                  errmsg("invalid value for parameter \"%s\": %d",
   10744             :                         conf->gen.name, *newval),
   10745             :                  GUC_check_errdetail_string ?
   10746             :                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
   10747             :                  GUC_check_errhint_string ?
   10748             :                  errhint("%s", GUC_check_errhint_string) : 0));
   10749             :         /* Flush any strings created in ErrorContext */
   10750           0 :         FlushErrorState();
   10751           0 :         return false;
   10752             :     }
   10753             : 
   10754       26944 :     return true;
   10755             : }
   10756             : 
   10757             : static bool
   10758       44168 : call_real_check_hook(struct config_real *conf, double *newval, void **extra,
   10759             :                      GucSource source, int elevel)
   10760             : {
   10761             :     /* Quick success if no hook */
   10762       44168 :     if (!conf->check_hook)
   10763       42306 :         return true;
   10764             : 
   10765             :     /* Reset variables that might be set by hook */
   10766        1862 :     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
   10767        1862 :     GUC_check_errmsg_string = NULL;
   10768        1862 :     GUC_check_errdetail_string = NULL;
   10769        1862 :     GUC_check_errhint_string = NULL;
   10770             : 
   10771        1862 :     if (!conf->check_hook(newval, extra, source))
   10772             :     {
   10773           0 :         ereport(elevel,
   10774             :                 (errcode(GUC_check_errcode_value),
   10775             :                  GUC_check_errmsg_string ?
   10776             :                  errmsg_internal("%s", GUC_check_errmsg_string) :
   10777             :                  errmsg("invalid value for parameter \"%s\": %g",
   10778             :                         conf->gen.name, *newval),
   10779             :                  GUC_check_errdetail_string ?
   10780             :                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
   10781             :                  GUC_check_errhint_string ?
   10782             :                  errhint("%s", GUC_check_errhint_string) : 0));
   10783             :         /* Flush any strings created in ErrorContext */
   10784           0 :         FlushErrorState();
   10785           0 :         return false;
   10786             :     }
   10787             : 
   10788        1862 :     return true;
   10789             : }
   10790             : 
   10791             : static bool
   10792      284328 : call_string_check_hook(struct config_string *conf, char **newval, void **extra,
   10793             :                        GucSource source, int elevel)
   10794             : {
   10795             :     /* Quick success if no hook */
   10796      284328 :     if (!conf->check_hook)
   10797      106306 :         return true;
   10798             : 
   10799             :     /* Reset variables that might be set by hook */
   10800      178022 :     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
   10801      178022 :     GUC_check_errmsg_string = NULL;
   10802      178022 :     GUC_check_errdetail_string = NULL;
   10803      178022 :     GUC_check_errhint_string = NULL;
   10804             : 
   10805      178022 :     if (!conf->check_hook(newval, extra, source))
   10806             :     {
   10807          16 :         ereport(elevel,
   10808             :                 (errcode(GUC_check_errcode_value),
   10809             :                  GUC_check_errmsg_string ?
   10810             :                  errmsg_internal("%s", GUC_check_errmsg_string) :
   10811             :                  errmsg("invalid value for parameter \"%s\": \"%s\"",
   10812             :                         conf->gen.name, *newval ? *newval : ""),
   10813             :                  GUC_check_errdetail_string ?
   10814             :                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
   10815             :                  GUC_check_errhint_string ?
   10816             :                  errhint("%s", GUC_check_errhint_string) : 0));
   10817             :         /* Flush any strings created in ErrorContext */
   10818           0 :         FlushErrorState();
   10819           0 :         return false;
   10820             :     }
   10821             : 
   10822      178002 :     return true;
   10823             : }
   10824             : 
   10825             : static bool
   10826       90728 : call_enum_check_hook(struct config_enum *conf, int *newval, void **extra,
   10827             :                      GucSource source, int elevel)
   10828             : {
   10829             :     /* Quick success if no hook */
   10830       90728 :     if (!conf->check_hook)
   10831       78864 :         return true;
   10832             : 
   10833             :     /* Reset variables that might be set by hook */
   10834       11864 :     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
   10835       11864 :     GUC_check_errmsg_string = NULL;
   10836       11864 :     GUC_check_errdetail_string = NULL;
   10837       11864 :     GUC_check_errhint_string = NULL;
   10838             : 
   10839       11864 :     if (!conf->check_hook(newval, extra, source))
   10840             :     {
   10841           2 :         ereport(elevel,
   10842             :                 (errcode(GUC_check_errcode_value),
   10843             :                  GUC_check_errmsg_string ?
   10844             :                  errmsg_internal("%s", GUC_check_errmsg_string) :
   10845             :                  errmsg("invalid value for parameter \"%s\": \"%s\"",
   10846             :                         conf->gen.name,
   10847             :                         config_enum_lookup_by_value(conf, *newval)),
   10848             :                  GUC_check_errdetail_string ?
   10849             :                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
   10850             :                  GUC_check_errhint_string ?
   10851             :                  errhint("%s", GUC_check_errhint_string) : 0));
   10852             :         /* Flush any strings created in ErrorContext */
   10853           0 :         FlushErrorState();
   10854           0 :         return false;
   10855             :     }
   10856             : 
   10857       11862 :     return true;
   10858             : }
   10859             : 
   10860             : 
   10861             : /*
   10862             :  * check_hook, assign_hook and show_hook subroutines
   10863             :  */
   10864             : 
   10865             : static bool
   10866        1862 : check_wal_consistency_checking(char **newval, void **extra, GucSource source)
   10867             : {
   10868             :     char       *rawstring;
   10869             :     List       *elemlist;
   10870             :     ListCell   *l;
   10871             :     bool        newwalconsistency[RM_MAX_ID + 1];
   10872             : 
   10873             :     /* Initialize the array */
   10874        1862 :     MemSet(newwalconsistency, 0, (RM_MAX_ID + 1) * sizeof(bool));
   10875             : 
   10876             :     /* Need a modifiable copy of string */
   10877        1862 :     rawstring = pstrdup(*newval);
   10878             : 
   10879             :     /* Parse string into list of identifiers */
   10880        1862 :     if (!SplitIdentifierString(rawstring, ',', &elemlist))
   10881             :     {
   10882             :         /* syntax error in list */
   10883           0 :         GUC_check_errdetail("List syntax is invalid.");
   10884           0 :         pfree(rawstring);
   10885           0 :         list_free(elemlist);
   10886           0 :         return false;
   10887             :     }
   10888             : 
   10889        1862 :     foreach(l, elemlist)
   10890             :     {
   10891           0 :         char       *tok = (char *) lfirst(l);
   10892           0 :         bool        found = false;
   10893             :         RmgrId      rmid;
   10894             : 
   10895             :         /* Check for 'all'. */
   10896           0 :         if (pg_strcasecmp(tok, "all") == 0)
   10897             :         {
   10898           0 :             for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
   10899           0 :                 if (RmgrTable[rmid].rm_mask != NULL)
   10900           0 :                     newwalconsistency[rmid] = true;
   10901           0 :             found = true;
   10902             :         }
   10903             :         else
   10904             :         {
   10905             :             /*
   10906             :              * Check if the token matches with any individual resource
   10907             :              * manager.
   10908             :              */
   10909           0 :             for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
   10910             :             {
   10911           0 :                 if (pg_strcasecmp(tok, RmgrTable[rmid].rm_name) == 0 &&
   10912           0 :                     RmgrTable[rmid].rm_mask != NULL)
   10913             :                 {
   10914           0 :                     newwalconsistency[rmid] = true;
   10915           0 :                     found = true;
   10916             :                 }
   10917             :             }
   10918             :         }
   10919             : 
   10920             :         /* If a valid resource manager is found, check for the next one. */
   10921           0 :         if (!found)
   10922             :         {
   10923           0 :             GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
   10924           0 :             pfree(rawstring);
   10925           0 :             list_free(elemlist);
   10926           0 :             return false;
   10927             :         }
   10928             :     }
   10929             : 
   10930        1862 :     pfree(rawstring);
   10931        1862 :     list_free(elemlist);
   10932             : 
   10933             :     /* assign new value */
   10934        1862 :     *extra = guc_malloc(ERROR, (RM_MAX_ID + 1) * sizeof(bool));
   10935        1862 :     memcpy(*extra, newwalconsistency, (RM_MAX_ID + 1) * sizeof(bool));
   10936        1862 :     return true;
   10937             : }
   10938             : 
   10939             : static void
   10940        1862 : assign_wal_consistency_checking(const char *newval, void *extra)
   10941             : {
   10942        1862 :     wal_consistency_checking = (bool *) extra;
   10943        1862 : }
   10944             : 
   10945             : static bool
   10946        1862 : check_log_destination(char **newval, void **extra, GucSource source)
   10947             : {
   10948             :     char       *rawstring;
   10949             :     List       *elemlist;
   10950             :     ListCell   *l;
   10951        1862 :     int         newlogdest = 0;
   10952             :     int        *myextra;
   10953             : 
   10954             :     /* Need a modifiable copy of string */
   10955        1862 :     rawstring = pstrdup(*newval);
   10956             : 
   10957             :     /* Parse string into list of identifiers */
   10958        1862 :     if (!SplitIdentifierString(rawstring, ',', &elemlist))
   10959             :     {
   10960             :         /* syntax error in list */
   10961           0 :         GUC_check_errdetail("List syntax is invalid.");
   10962           0 :         pfree(rawstring);
   10963           0 :         list_free(elemlist);
   10964           0 :         return false;
   10965             :     }
   10966             : 
   10967        3724 :     foreach(l, elemlist)
   10968             :     {
   10969        1862 :         char       *tok = (char *) lfirst(l);
   10970             : 
   10971        1862 :         if (pg_strcasecmp(tok, "stderr") == 0)
   10972        1862 :             newlogdest |= LOG_DESTINATION_STDERR;
   10973           0 :         else if (pg_strcasecmp(tok, "csvlog") == 0)
   10974           0 :             newlogdest |= LOG_DESTINATION_CSVLOG;
   10975             : #ifdef HAVE_SYSLOG
   10976           0 :         else if (pg_strcasecmp(tok, "syslog") == 0)
   10977           0 :             newlogdest |= LOG_DESTINATION_SYSLOG;
   10978             : #endif
   10979             : #ifdef WIN32
   10980             :         else if (pg_strcasecmp(tok, "eventlog") == 0)
   10981             :             newlogdest |= LOG_DESTINATION_EVENTLOG;
   10982             : #endif
   10983             :         else
   10984             :         {
   10985           0 :             GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
   10986           0 :             pfree(rawstring);
   10987           0 :             list_free(elemlist);
   10988           0 :             return false;
   10989             :         }
   10990             :     }
   10991             : 
   10992        1862 :     pfree(rawstring);
   10993        1862 :     list_free(elemlist);
   10994             : 
   10995        1862 :     myextra = (int *) guc_malloc(ERROR, sizeof(int));
   10996        1862 :     *myextra = newlogdest;
   10997        1862 :     *extra = (void *) myextra;
   10998             : 
   10999        1862 :     return true;
   11000             : }
   11001             : 
   11002             : static void
   11003        1862 : assign_log_destination(const char *newval, void *extra)
   11004             : {
   11005        1862 :     Log_destination = *((int *) extra);
   11006        1862 : }
   11007             : 
   11008             : static void
   11009        1862 : assign_syslog_facility(int newval, void *extra)
   11010             : {
   11011             : #ifdef HAVE_SYSLOG
   11012        1862 :     set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
   11013             :                           newval);
   11014             : #endif
   11015             :     /* Without syslog support, just ignore it */
   11016        1862 : }
   11017             : 
   11018             : static void
   11019        1862 : assign_syslog_ident(const char *newval, void *extra)
   11020             : {
   11021             : #ifdef HAVE_SYSLOG
   11022        1862 :     set_syslog_parameters(newval, syslog_facility);
   11023             : #endif
   11024             :     /* Without syslog support, it will always be set to "none", so ignore */
   11025        1862 : }
   11026             : 
   11027             : 
   11028             : static void
   11029        2010 : assign_session_replication_role(int newval, void *extra)
   11030             : {
   11031             :     /*
   11032             :      * Must flush the plan cache when changing replication role; but don't
   11033             :      * flush unnecessarily.
   11034             :      */
   11035        2010 :     if (SessionReplicationRole != newval)
   11036         148 :         ResetPlanCache();
   11037        2010 : }
   11038             : 
   11039             : static bool
   11040        1862 : check_temp_buffers(int *newval, void **extra, GucSource source)
   11041             : {
   11042             :     /*
   11043             :      * Once local buffers have been initialized, it's too late to change this.
   11044             :      */
   11045        1862 :     if (NLocBuffer && NLocBuffer != *newval)
   11046             :     {
   11047           0 :         GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session.");
   11048           0 :         return false;
   11049             :     }
   11050        1862 :     return true;
   11051             : }
   11052             : 
   11053             : static bool
   11054        1862 : check_bonjour(bool *newval, void **extra, GucSource source)
   11055             : {
   11056             : #ifndef USE_BONJOUR
   11057        1862 :     if (*newval)
   11058             :     {
   11059           0 :         GUC_check_errmsg("Bonjour is not supported by this build");
   11060           0 :         return false;
   11061             :     }
   11062             : #endif
   11063        1862 :     return true;
   11064             : }
   11065             : 
   11066             : static bool
   11067        1882 : check_ssl(bool *newval, void **extra, GucSource source)
   11068             : {
   11069             : #ifndef USE_SSL
   11070             :     if (*newval)
   11071             :     {
   11072             :         GUC_check_errmsg("SSL is not supported by this build");
   11073             :         return false;
   11074             :     }
   11075             : #endif
   11076        1882 :     return true;
   11077             : }
   11078             : 
   11079             : static bool
   11080        5586 : check_stage_log_stats(bool *newval, void **extra, GucSource source)
   11081             : {
   11082        5586 :     if (*newval && log_statement_stats)
   11083             :     {
   11084           0 :         GUC_check_errdetail("Cannot enable parameter when \"log_statement_stats\" is true.");
   11085           0 :         return false;
   11086             :     }
   11087        5586 :     return true;
   11088             : }
   11089             : 
   11090             : static bool
   11091        1862 : check_log_stats(bool *newval, void **extra, GucSource source)
   11092             : {
   11093        1862 :     if (*newval &&
   11094           0 :         (log_parser_stats || log_planner_stats || log_executor_stats))
   11095             :     {
   11096           0 :         GUC_check_errdetail("Cannot enable \"log_statement_stats\" when "
   11097             :                             "\"log_parser_stats\", \"log_planner_stats\", "
   11098             :                             "or \"log_executor_stats\" is true.");
   11099           0 :         return false;
   11100             :     }
   11101        1862 :     return true;
   11102             : }
   11103             : 
   11104             : static bool
   11105        6188 : check_canonical_path(char **newval, void **extra, GucSource source)
   11106             : {
   11107             :     /*
   11108             :      * Since canonicalize_path never enlarges the string, we can just modify
   11109             :      * newval in-place.  But watch out for NULL, which is the default value
   11110             :      * for external_pid_file.
   11111             :      */
   11112        6188 :     if (*newval)
   11113        4326 :         canonicalize_path(*newval);
   11114        6188 :     return true;
   11115             : }
   11116             : 
   11117             : static bool
   11118       11568 : check_timezone_abbreviations(char **newval, void **extra, GucSource source)
   11119             : {
   11120             :     /*
   11121             :      * The boot_val given above for timezone_abbreviations is NULL. When we
   11122             :      * see this we just do nothing.  If this value isn't overridden from the
   11123             :      * config file then pg_timezone_abbrev_initialize() will eventually
   11124             :      * replace it with "Default".  This hack has two purposes: to avoid
   11125             :      * wasting cycles loading values that might soon be overridden from the
   11126             :      * config file, and to avoid trying to read the timezone abbrev files
   11127             :      * during InitializeGUCOptions().  The latter doesn't work in an
   11128             :      * EXEC_BACKEND subprocess because my_exec_path hasn't been set yet and so
   11129             :      * we can't locate PGSHAREDIR.
   11130             :      */
   11131       11568 :     if (*newval == NULL)
   11132             :     {
   11133             :         Assert(source == PGC_S_DEFAULT);
   11134        3478 :         return true;
   11135             :     }
   11136             : 
   11137             :     /* OK, load the file and produce a malloc'd TimeZoneAbbrevTable */
   11138        8090 :     *extra = load_tzoffsets(*newval);
   11139             : 
   11140             :     /* tzparser.c returns NULL on failure, reporting via GUC_check_errmsg */
   11141        8090 :     if (!*extra)
   11142           0 :         return false;
   11143             : 
   11144        8090 :     return true;
   11145             : }
   11146             : 
   11147             : static void
   11148       11428 : assign_timezone_abbreviations(const char *newval, void *extra)
   11149             : {
   11150             :     /* Do nothing for the boot_val default of NULL */
   11151       11428 :     if (!extra)
   11152        3478 :         return;
   11153             : 
   11154        7950 :     InstallTimeZoneAbbrevs((TimeZoneAbbrevTable *) extra);
   11155             : }
   11156             : 
   11157             : /*
   11158             :  * pg_timezone_abbrev_initialize --- set default value if not done already
   11159             :  *
   11160             :  * This is called after initial loading of postgresql.conf.  If no
   11161             :  * timezone_abbreviations setting was found therein, select default.
   11162             :  * If a non-default value is already installed, nothing will happen.
   11163             :  *
   11164             :  * This can also be called from ProcessConfigFile to establish the default
   11165             :  * value after a postgresql.conf entry for it is removed.
   11166             :  */
   11167             : static void
   11168        2044 : pg_timezone_abbrev_initialize(void)
   11169             : {
   11170        2044 :     SetConfigOption("timezone_abbreviations", "Default",
   11171             :                     PGC_POSTMASTER, PGC_S_DYNAMIC_DEFAULT);
   11172        2044 : }
   11173             : 
   11174             : static const char *
   11175          32 : show_archive_command(void)
   11176             : {
   11177          32 :     if (XLogArchivingActive())
   11178           0 :         return XLogArchiveCommand;
   11179             :     else
   11180          32 :         return "(disabled)";
   11181             : }
   11182             : 
   11183             : static void
   11184        1862 : assign_tcp_keepalives_idle(int newval, void *extra)
   11185             : {
   11186             :     /*
   11187             :      * The kernel API provides no way to test a value without setting it; and
   11188             :      * once we set it we might fail to unset it.  So there seems little point
   11189             :      * in fully implementing the check-then-assign GUC API for these
   11190             :      * variables.  Instead we just do the assignment on demand.  pqcomm.c
   11191             :      * reports any problems via elog(LOG).
   11192             :      *
   11193             :      * This approach means that the GUC value might have little to do with the
   11194             :      * actual kernel value, so we use a show_hook that retrieves the kernel
   11195             :      * value rather than trusting GUC's copy.
   11196             :      */
   11197        1862 :     (void) pq_setkeepalivesidle(newval, MyProcPort);
   11198        1862 : }
   11199             : 
   11200             : static const char *
   11201          32 : show_tcp_keepalives_idle(void)
   11202             : {
   11203             :     /* See comments in assign_tcp_keepalives_idle */
   11204             :     static char nbuf[16];
   11205             : 
   11206          32 :     snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
   11207          32 :     return nbuf;
   11208             : }
   11209             : 
   11210             : static void
   11211        1862 : assign_tcp_keepalives_interval(int newval, void *extra)
   11212             : {
   11213             :     /* See comments in assign_tcp_keepalives_idle */
   11214        1862 :     (void) pq_setkeepalivesinterval(newval, MyProcPort);
   11215        1862 : }
   11216             : 
   11217             : static const char *
   11218          32 : show_tcp_keepalives_interval(void)
   11219             : {
   11220             :     /* See comments in assign_tcp_keepalives_idle */
   11221             :     static char nbuf[16];
   11222             : 
   11223          32 :     snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
   11224          32 :     return nbuf;
   11225             : }
   11226             : 
   11227             : static void
   11228        1862 : assign_tcp_keepalives_count(int newval, void *extra)
   11229             : {
   11230             :     /* See comments in assign_tcp_keepalives_idle */
   11231        1862 :     (void) pq_setkeepalivescount(newval, MyProcPort);
   11232        1862 : }
   11233             : 
   11234             : static const char *
   11235          32 : show_tcp_keepalives_count(void)
   11236             : {
   11237             :     /* See comments in assign_tcp_keepalives_idle */
   11238             :     static char nbuf[16];
   11239             : 
   11240          32 :     snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
   11241          32 :     return nbuf;
   11242             : }
   11243             : 
   11244             : static void
   11245        1862 : assign_tcp_user_timeout(int newval, void *extra)
   11246             : {
   11247             :     /* See comments in assign_tcp_keepalives_idle */
   11248        1862 :     (void) pq_settcpusertimeout(newval, MyProcPort);
   11249        1862 : }
   11250             : 
   11251             : static const char *
   11252          32 : show_tcp_user_timeout(void)
   11253             : {
   11254             :     /* See comments in assign_tcp_keepalives_idle */
   11255             :     static char nbuf[16];
   11256             : 
   11257          32 :     snprintf(nbuf, sizeof(nbuf), "%d", pq_gettcpusertimeout(MyProcPort));
   11258          32 :     return nbuf;
   11259             : }
   11260             : 
   11261             : static bool
   11262        3912 : check_maxconnections(int *newval, void **extra, GucSource source)
   11263             : {
   11264        7824 :     if (*newval + autovacuum_max_workers + 1 +
   11265        3912 :         max_worker_processes + max_wal_senders > MAX_BACKENDS)
   11266           0 :         return false;
   11267        3912 :     return true;
   11268             : }
   11269             : 
   11270             : static bool
   11271        1862 : check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
   11272             : {
   11273        3724 :     if (MaxConnections + *newval + 1 +
   11274        1862 :         max_worker_processes + max_wal_senders > MAX_BACKENDS)
   11275           0 :         return false;
   11276        1862 :     return true;
   11277             : }
   11278             : 
   11279             : static bool
   11280        2460 : check_max_wal_senders(int *newval, void **extra, GucSource source)
   11281             : {
   11282        4920 :     if (MaxConnections + autovacuum_max_workers + 1 +
   11283        2460 :         max_worker_processes + *newval > MAX_BACKENDS)
   11284           0 :         return false;
   11285        2460 :     return true;
   11286             : }
   11287             : 
   11288             : static bool
   11289        1862 : check_autovacuum_work_mem(int *newval, void **extra, GucSource source)
   11290             : {
   11291             :     /*
   11292             :      * -1 indicates fallback.
   11293             :      *
   11294             :      * If we haven't yet changed the boot_val default of -1, just let it be.
   11295             :      * Autovacuum will look to maintenance_work_mem instead.
   11296             :