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