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

Generated by: LCOV version 1.11