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