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