Header And Logo

PostgreSQL
| The world's most advanced open source database.

guc.c

Go to the documentation of this file.
00001 /*--------------------------------------------------------------------
00002  * guc.c
00003  *
00004  * Support for grand unified configuration scheme, including SET
00005  * command, configuration file, and command line options.
00006  * See src/backend/utils/misc/README for more information.
00007  *
00008  *
00009  * Copyright (c) 2000-2013, PostgreSQL Global Development Group
00010  * Written by Peter Eisentraut <[email protected]>.
00011  *
00012  * IDENTIFICATION
00013  *    src/backend/utils/misc/guc.c
00014  *
00015  *--------------------------------------------------------------------
00016  */
00017 #include "postgres.h"
00018 
00019 #include <ctype.h>
00020 #include <float.h>
00021 #include <math.h>
00022 #include <limits.h>
00023 #include <unistd.h>
00024 #include <sys/stat.h>
00025 #ifdef HAVE_SYSLOG
00026 #include <syslog.h>
00027 #endif
00028 
00029 #include "access/gin.h"
00030 #include "access/transam.h"
00031 #include "access/twophase.h"
00032 #include "access/xact.h"
00033 #include "catalog/namespace.h"
00034 #include "commands/async.h"
00035 #include "commands/prepare.h"
00036 #include "commands/vacuum.h"
00037 #include "commands/variable.h"
00038 #include "commands/trigger.h"
00039 #include "funcapi.h"
00040 #include "libpq/auth.h"
00041 #include "libpq/be-fsstubs.h"
00042 #include "libpq/libpq.h"
00043 #include "libpq/pqformat.h"
00044 #include "miscadmin.h"
00045 #include "optimizer/cost.h"
00046 #include "optimizer/geqo.h"
00047 #include "optimizer/paths.h"
00048 #include "optimizer/planmain.h"
00049 #include "parser/parse_expr.h"
00050 #include "parser/parse_type.h"
00051 #include "parser/parser.h"
00052 #include "parser/scansup.h"
00053 #include "pgstat.h"
00054 #include "postmaster/autovacuum.h"
00055 #include "postmaster/bgworker.h"
00056 #include "postmaster/bgwriter.h"
00057 #include "postmaster/postmaster.h"
00058 #include "postmaster/syslogger.h"
00059 #include "postmaster/walwriter.h"
00060 #include "replication/syncrep.h"
00061 #include "replication/walreceiver.h"
00062 #include "replication/walsender.h"
00063 #include "storage/bufmgr.h"
00064 #include "storage/standby.h"
00065 #include "storage/fd.h"
00066 #include "storage/proc.h"
00067 #include "storage/predicate.h"
00068 #include "tcop/tcopprot.h"
00069 #include "tsearch/ts_cache.h"
00070 #include "utils/builtins.h"
00071 #include "utils/bytea.h"
00072 #include "utils/guc_tables.h"
00073 #include "utils/memutils.h"
00074 #include "utils/pg_locale.h"
00075 #include "utils/plancache.h"
00076 #include "utils/portal.h"
00077 #include "utils/ps_status.h"
00078 #include "utils/snapmgr.h"
00079 #include "utils/tzparser.h"
00080 #include "utils/xml.h"
00081 
00082 #ifndef PG_KRB_SRVTAB
00083 #define PG_KRB_SRVTAB ""
00084 #endif
00085 #ifndef PG_KRB_SRVNAM
00086 #define PG_KRB_SRVNAM ""
00087 #endif
00088 
00089 #define CONFIG_FILENAME "postgresql.conf"
00090 #define HBA_FILENAME    "pg_hba.conf"
00091 #define IDENT_FILENAME  "pg_ident.conf"
00092 
00093 #ifdef EXEC_BACKEND
00094 #define CONFIG_EXEC_PARAMS "global/config_exec_params"
00095 #define CONFIG_EXEC_PARAMS_NEW "global/config_exec_params.new"
00096 #endif
00097 
00098 /* upper limit for GUC variables measured in kilobytes of memory */
00099 /* note that various places assume the byte size fits in a "long" variable */
00100 #if SIZEOF_SIZE_T > 4 && SIZEOF_LONG > 4
00101 #define MAX_KILOBYTES   INT_MAX
00102 #else
00103 #define MAX_KILOBYTES   (INT_MAX / 1024)
00104 #endif
00105 
00106 #define KB_PER_MB (1024)
00107 #define KB_PER_GB (1024*1024)
00108 
00109 #define MS_PER_S 1000
00110 #define S_PER_MIN 60
00111 #define MS_PER_MIN (1000 * 60)
00112 #define MIN_PER_H 60
00113 #define S_PER_H (60 * 60)
00114 #define MS_PER_H (1000 * 60 * 60)
00115 #define MIN_PER_D (60 * 24)
00116 #define S_PER_D (60 * 60 * 24)
00117 #define MS_PER_D (1000 * 60 * 60 * 24)
00118 
00119 /* XXX these should appear in other modules' header files */
00120 extern bool Log_disconnections;
00121 extern int  CommitDelay;
00122 extern int  CommitSiblings;
00123 extern char *default_tablespace;
00124 extern char *temp_tablespaces;
00125 extern bool ignore_checksum_failure;
00126 extern bool synchronize_seqscans;
00127 extern int  ssl_renegotiation_limit;
00128 extern char *SSLCipherSuites;
00129 
00130 #ifdef TRACE_SORT
00131 extern bool trace_sort;
00132 #endif
00133 #ifdef TRACE_SYNCSCAN
00134 extern bool trace_syncscan;
00135 #endif
00136 #ifdef DEBUG_BOUNDED_SORT
00137 extern bool optimize_bounded_sort;
00138 #endif
00139 
00140 static int  GUC_check_errcode_value;
00141 
00142 /* global variables for check hook support */
00143 char       *GUC_check_errmsg_string;
00144 char       *GUC_check_errdetail_string;
00145 char       *GUC_check_errhint_string;
00146 
00147 
00148 static void set_config_sourcefile(const char *name, char *sourcefile,
00149                       int sourceline);
00150 static bool call_bool_check_hook(struct config_bool * conf, bool *newval,
00151                      void **extra, GucSource source, int elevel);
00152 static bool call_int_check_hook(struct config_int * conf, int *newval,
00153                     void **extra, GucSource source, int elevel);
00154 static bool call_real_check_hook(struct config_real * conf, double *newval,
00155                      void **extra, GucSource source, int elevel);
00156 static bool call_string_check_hook(struct config_string * conf, char **newval,
00157                        void **extra, GucSource source, int elevel);
00158 static bool call_enum_check_hook(struct config_enum * conf, int *newval,
00159                      void **extra, GucSource source, int elevel);
00160 
00161 static bool check_log_destination(char **newval, void **extra, GucSource source);
00162 static void assign_log_destination(const char *newval, void *extra);
00163 
00164 #ifdef HAVE_SYSLOG
00165 static int  syslog_facility = LOG_LOCAL0;
00166 #else
00167 static int  syslog_facility = 0;
00168 #endif
00169 
00170 static void assign_syslog_facility(int newval, void *extra);
00171 static void assign_syslog_ident(const char *newval, void *extra);
00172 static void assign_session_replication_role(int newval, void *extra);
00173 static bool check_temp_buffers(int *newval, void **extra, GucSource source);
00174 static bool check_phony_autocommit(bool *newval, void **extra, GucSource source);
00175 static bool check_debug_assertions(bool *newval, void **extra, GucSource source);
00176 static bool check_bonjour(bool *newval, void **extra, GucSource source);
00177 static bool check_ssl(bool *newval, void **extra, GucSource source);
00178 static bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
00179 static bool check_log_stats(bool *newval, void **extra, GucSource source);
00180 static bool check_canonical_path(char **newval, void **extra, GucSource source);
00181 static bool check_timezone_abbreviations(char **newval, void **extra, GucSource source);
00182 static void assign_timezone_abbreviations(const char *newval, void *extra);
00183 static void pg_timezone_abbrev_initialize(void);
00184 static const char *show_archive_command(void);
00185 static void assign_tcp_keepalives_idle(int newval, void *extra);
00186 static void assign_tcp_keepalives_interval(int newval, void *extra);
00187 static void assign_tcp_keepalives_count(int newval, void *extra);
00188 static const char *show_tcp_keepalives_idle(void);
00189 static const char *show_tcp_keepalives_interval(void);
00190 static const char *show_tcp_keepalives_count(void);
00191 static bool check_maxconnections(int *newval, void **extra, GucSource source);
00192 static bool check_autovacuum_max_workers(int *newval, void **extra, GucSource source);
00193 static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
00194 static void assign_effective_io_concurrency(int newval, void *extra);
00195 static void assign_pgstat_temp_directory(const char *newval, void *extra);
00196 static bool check_application_name(char **newval, void **extra, GucSource source);
00197 static void assign_application_name(const char *newval, void *extra);
00198 static const char *show_unix_socket_permissions(void);
00199 static const char *show_log_file_mode(void);
00200 
00201 static char *config_enum_get_options(struct config_enum * record,
00202                         const char *prefix, const char *suffix,
00203                         const char *separator);
00204 
00205 
00206 /*
00207  * Options for enum values defined in this module.
00208  *
00209  * NOTE! Option values may not contain double quotes!
00210  */
00211 
00212 static const struct config_enum_entry bytea_output_options[] = {
00213     {"escape", BYTEA_OUTPUT_ESCAPE, false},
00214     {"hex", BYTEA_OUTPUT_HEX, false},
00215     {NULL, 0, false}
00216 };
00217 
00218 /*
00219  * We have different sets for client and server message level options because
00220  * they sort slightly different (see "log" level)
00221  */
00222 static const struct config_enum_entry client_message_level_options[] = {
00223     {"debug", DEBUG2, true},
00224     {"debug5", DEBUG5, false},
00225     {"debug4", DEBUG4, false},
00226     {"debug3", DEBUG3, false},
00227     {"debug2", DEBUG2, false},
00228     {"debug1", DEBUG1, false},
00229     {"log", LOG, false},
00230     {"info", INFO, true},
00231     {"notice", NOTICE, false},
00232     {"warning", WARNING, false},
00233     {"error", ERROR, false},
00234     {"fatal", FATAL, true},
00235     {"panic", PANIC, true},
00236     {NULL, 0, false}
00237 };
00238 
00239 static const struct config_enum_entry server_message_level_options[] = {
00240     {"debug", DEBUG2, true},
00241     {"debug5", DEBUG5, false},
00242     {"debug4", DEBUG4, false},
00243     {"debug3", DEBUG3, false},
00244     {"debug2", DEBUG2, false},
00245     {"debug1", DEBUG1, false},
00246     {"info", INFO, false},
00247     {"notice", NOTICE, false},
00248     {"warning", WARNING, false},
00249     {"error", ERROR, false},
00250     {"log", LOG, false},
00251     {"fatal", FATAL, false},
00252     {"panic", PANIC, false},
00253     {NULL, 0, false}
00254 };
00255 
00256 static const struct config_enum_entry intervalstyle_options[] = {
00257     {"postgres", INTSTYLE_POSTGRES, false},
00258     {"postgres_verbose", INTSTYLE_POSTGRES_VERBOSE, false},
00259     {"sql_standard", INTSTYLE_SQL_STANDARD, false},
00260     {"iso_8601", INTSTYLE_ISO_8601, false},
00261     {NULL, 0, false}
00262 };
00263 
00264 static const struct config_enum_entry log_error_verbosity_options[] = {
00265     {"terse", PGERROR_TERSE, false},
00266     {"default", PGERROR_DEFAULT, false},
00267     {"verbose", PGERROR_VERBOSE, false},
00268     {NULL, 0, false}
00269 };
00270 
00271 static const struct config_enum_entry log_statement_options[] = {
00272     {"none", LOGSTMT_NONE, false},
00273     {"ddl", LOGSTMT_DDL, false},
00274     {"mod", LOGSTMT_MOD, false},
00275     {"all", LOGSTMT_ALL, false},
00276     {NULL, 0, false}
00277 };
00278 
00279 static const struct config_enum_entry isolation_level_options[] = {
00280     {"serializable", XACT_SERIALIZABLE, false},
00281     {"repeatable read", XACT_REPEATABLE_READ, false},
00282     {"read committed", XACT_READ_COMMITTED, false},
00283     {"read uncommitted", XACT_READ_UNCOMMITTED, false},
00284     {NULL, 0}
00285 };
00286 
00287 static const struct config_enum_entry session_replication_role_options[] = {
00288     {"origin", SESSION_REPLICATION_ROLE_ORIGIN, false},
00289     {"replica", SESSION_REPLICATION_ROLE_REPLICA, false},
00290     {"local", SESSION_REPLICATION_ROLE_LOCAL, false},
00291     {NULL, 0, false}
00292 };
00293 
00294 static const struct config_enum_entry syslog_facility_options[] = {
00295 #ifdef HAVE_SYSLOG
00296     {"local0", LOG_LOCAL0, false},
00297     {"local1", LOG_LOCAL1, false},
00298     {"local2", LOG_LOCAL2, false},
00299     {"local3", LOG_LOCAL3, false},
00300     {"local4", LOG_LOCAL4, false},
00301     {"local5", LOG_LOCAL5, false},
00302     {"local6", LOG_LOCAL6, false},
00303     {"local7", LOG_LOCAL7, false},
00304 #else
00305     {"none", 0, false},
00306 #endif
00307     {NULL, 0}
00308 };
00309 
00310 static const struct config_enum_entry track_function_options[] = {
00311     {"none", TRACK_FUNC_OFF, false},
00312     {"pl", TRACK_FUNC_PL, false},
00313     {"all", TRACK_FUNC_ALL, false},
00314     {NULL, 0, false}
00315 };
00316 
00317 static const struct config_enum_entry xmlbinary_options[] = {
00318     {"base64", XMLBINARY_BASE64, false},
00319     {"hex", XMLBINARY_HEX, false},
00320     {NULL, 0, false}
00321 };
00322 
00323 static const struct config_enum_entry xmloption_options[] = {
00324     {"content", XMLOPTION_CONTENT, false},
00325     {"document", XMLOPTION_DOCUMENT, false},
00326     {NULL, 0, false}
00327 };
00328 
00329 /*
00330  * Although only "on", "off", and "safe_encoding" are documented, we
00331  * accept all the likely variants of "on" and "off".
00332  */
00333 static const struct config_enum_entry backslash_quote_options[] = {
00334     {"safe_encoding", BACKSLASH_QUOTE_SAFE_ENCODING, false},
00335     {"on", BACKSLASH_QUOTE_ON, false},
00336     {"off", BACKSLASH_QUOTE_OFF, false},
00337     {"true", BACKSLASH_QUOTE_ON, true},
00338     {"false", BACKSLASH_QUOTE_OFF, true},
00339     {"yes", BACKSLASH_QUOTE_ON, true},
00340     {"no", BACKSLASH_QUOTE_OFF, true},
00341     {"1", BACKSLASH_QUOTE_ON, true},
00342     {"0", BACKSLASH_QUOTE_OFF, true},
00343     {NULL, 0, false}
00344 };
00345 
00346 /*
00347  * Although only "on", "off", and "partition" are documented, we
00348  * accept all the likely variants of "on" and "off".
00349  */
00350 static const struct config_enum_entry constraint_exclusion_options[] = {
00351     {"partition", CONSTRAINT_EXCLUSION_PARTITION, false},
00352     {"on", CONSTRAINT_EXCLUSION_ON, false},
00353     {"off", CONSTRAINT_EXCLUSION_OFF, false},
00354     {"true", CONSTRAINT_EXCLUSION_ON, true},
00355     {"false", CONSTRAINT_EXCLUSION_OFF, true},
00356     {"yes", CONSTRAINT_EXCLUSION_ON, true},
00357     {"no", CONSTRAINT_EXCLUSION_OFF, true},
00358     {"1", CONSTRAINT_EXCLUSION_ON, true},
00359     {"0", CONSTRAINT_EXCLUSION_OFF, true},
00360     {NULL, 0, false}
00361 };
00362 
00363 /*
00364  * Although only "on", "off", "remote_write", and "local" are documented, we
00365  * accept all the likely variants of "on" and "off".
00366  */
00367 static const struct config_enum_entry synchronous_commit_options[] = {
00368     {"local", SYNCHRONOUS_COMMIT_LOCAL_FLUSH, false},
00369     {"remote_write", SYNCHRONOUS_COMMIT_REMOTE_WRITE, false},
00370     {"on", SYNCHRONOUS_COMMIT_ON, false},
00371     {"off", SYNCHRONOUS_COMMIT_OFF, false},
00372     {"true", SYNCHRONOUS_COMMIT_ON, true},
00373     {"false", SYNCHRONOUS_COMMIT_OFF, true},
00374     {"yes", SYNCHRONOUS_COMMIT_ON, true},
00375     {"no", SYNCHRONOUS_COMMIT_OFF, true},
00376     {"1", SYNCHRONOUS_COMMIT_ON, true},
00377     {"0", SYNCHRONOUS_COMMIT_OFF, true},
00378     {NULL, 0, false}
00379 };
00380 
00381 /*
00382  * Options for enum values stored in other modules
00383  */
00384 extern const struct config_enum_entry wal_level_options[];
00385 extern const struct config_enum_entry sync_method_options[];
00386 
00387 /*
00388  * GUC option variables that are exported from this module
00389  */
00390 #ifdef USE_ASSERT_CHECKING
00391 bool        assert_enabled = true;
00392 #else
00393 bool        assert_enabled = false;
00394 #endif
00395 bool        log_duration = false;
00396 bool        Debug_print_plan = false;
00397 bool        Debug_print_parse = false;
00398 bool        Debug_print_rewritten = false;
00399 bool        Debug_pretty_print = true;
00400 
00401 bool        log_parser_stats = false;
00402 bool        log_planner_stats = false;
00403 bool        log_executor_stats = false;
00404 bool        log_statement_stats = false;        /* this is sort of all three
00405                                                  * above together */
00406 bool        log_btree_build_stats = false;
00407 char       *event_source;
00408 
00409 bool        check_function_bodies = true;
00410 bool        default_with_oids = false;
00411 bool        SQL_inheritance = true;
00412 
00413 bool        Password_encryption = true;
00414 
00415 int         log_min_error_statement = ERROR;
00416 int         log_min_messages = WARNING;
00417 int         client_min_messages = NOTICE;
00418 int         log_min_duration_statement = -1;
00419 int         log_temp_files = -1;
00420 int         trace_recovery_messages = LOG;
00421 
00422 int         temp_file_limit = -1;
00423 
00424 int         num_temp_buffers = 1024;
00425 
00426 char       *data_directory;
00427 char       *ConfigFileName;
00428 char       *HbaFileName;
00429 char       *IdentFileName;
00430 char       *external_pid_file;
00431 
00432 char       *pgstat_temp_directory;
00433 
00434 char       *application_name;
00435 
00436 int         tcp_keepalives_idle;
00437 int         tcp_keepalives_interval;
00438 int         tcp_keepalives_count;
00439 
00440 /*
00441  * These variables are all dummies that don't do anything, except in some
00442  * cases provide the value for SHOW to display.  The real state is elsewhere
00443  * and is kept in sync by assign_hooks.
00444  */
00445 static char *log_destination_string;
00446 
00447 static char *syslog_ident_str;
00448 static bool phony_autocommit;
00449 static bool session_auth_is_superuser;
00450 static double phony_random_seed;
00451 static char *client_encoding_string;
00452 static char *datestyle_string;
00453 static char *locale_collate;
00454 static char *locale_ctype;
00455 static char *server_encoding_string;
00456 static char *server_version_string;
00457 static int  server_version_num;
00458 static char *timezone_string;
00459 static char *log_timezone_string;
00460 static char *timezone_abbreviations_string;
00461 static char *XactIsoLevel_string;
00462 static char *session_authorization_string;
00463 static int  max_function_args;
00464 static int  max_index_keys;
00465 static int  max_identifier_length;
00466 static int  block_size;
00467 static int  segment_size;
00468 static int  wal_block_size;
00469 static int  wal_segment_size;
00470 static bool integer_datetimes;
00471 static int  effective_io_concurrency;
00472 
00473 /* should be static, but commands/variable.c needs to get at this */
00474 char       *role_string;
00475 
00476 
00477 /*
00478  * Displayable names for context types (enum GucContext)
00479  *
00480  * Note: these strings are deliberately not localized.
00481  */
00482 const char *const GucContext_Names[] =
00483 {
00484      /* PGC_INTERNAL */ "internal",
00485      /* PGC_POSTMASTER */ "postmaster",
00486      /* PGC_SIGHUP */ "sighup",
00487      /* PGC_BACKEND */ "backend",
00488      /* PGC_SUSET */ "superuser",
00489      /* PGC_USERSET */ "user"
00490 };
00491 
00492 /*
00493  * Displayable names for source types (enum GucSource)
00494  *
00495  * Note: these strings are deliberately not localized.
00496  */
00497 const char *const GucSource_Names[] =
00498 {
00499      /* PGC_S_DEFAULT */ "default",
00500      /* PGC_S_DYNAMIC_DEFAULT */ "default",
00501      /* PGC_S_ENV_VAR */ "environment variable",
00502      /* PGC_S_FILE */ "configuration file",
00503      /* PGC_S_ARGV */ "command line",
00504      /* PGC_S_GLOBAL */ "global",
00505      /* PGC_S_DATABASE */ "database",
00506      /* PGC_S_USER */ "user",
00507      /* PGC_S_DATABASE_USER */ "database user",
00508      /* PGC_S_CLIENT */ "client",
00509      /* PGC_S_OVERRIDE */ "override",
00510      /* PGC_S_INTERACTIVE */ "interactive",
00511      /* PGC_S_TEST */ "test",
00512      /* PGC_S_SESSION */ "session"
00513 };
00514 
00515 /*
00516  * Displayable names for the groupings defined in enum config_group
00517  */
00518 const char *const config_group_names[] =
00519 {
00520     /* UNGROUPED */
00521     gettext_noop("Ungrouped"),
00522     /* FILE_LOCATIONS */
00523     gettext_noop("File Locations"),
00524     /* CONN_AUTH */
00525     gettext_noop("Connections and Authentication"),
00526     /* CONN_AUTH_SETTINGS */
00527     gettext_noop("Connections and Authentication / Connection Settings"),
00528     /* CONN_AUTH_SECURITY */
00529     gettext_noop("Connections and Authentication / Security and Authentication"),
00530     /* RESOURCES */
00531     gettext_noop("Resource Usage"),
00532     /* RESOURCES_MEM */
00533     gettext_noop("Resource Usage / Memory"),
00534     /* RESOURCES_DISK */
00535     gettext_noop("Resource Usage / Disk"),
00536     /* RESOURCES_KERNEL */
00537     gettext_noop("Resource Usage / Kernel Resources"),
00538     /* RESOURCES_VACUUM_DELAY */
00539     gettext_noop("Resource Usage / Cost-Based Vacuum Delay"),
00540     /* RESOURCES_BGWRITER */
00541     gettext_noop("Resource Usage / Background Writer"),
00542     /* RESOURCES_ASYNCHRONOUS */
00543     gettext_noop("Resource Usage / Asynchronous Behavior"),
00544     /* WAL */
00545     gettext_noop("Write-Ahead Log"),
00546     /* WAL_SETTINGS */
00547     gettext_noop("Write-Ahead Log / Settings"),
00548     /* WAL_CHECKPOINTS */
00549     gettext_noop("Write-Ahead Log / Checkpoints"),
00550     /* WAL_ARCHIVING */
00551     gettext_noop("Write-Ahead Log / Archiving"),
00552     /* REPLICATION */
00553     gettext_noop("Replication"),
00554     /* REPLICATION_SENDING */
00555     gettext_noop("Replication / Sending Servers"),
00556     /* REPLICATION_MASTER */
00557     gettext_noop("Replication / Master Server"),
00558     /* REPLICATION_STANDBY */
00559     gettext_noop("Replication / Standby Servers"),
00560     /* QUERY_TUNING */
00561     gettext_noop("Query Tuning"),
00562     /* QUERY_TUNING_METHOD */
00563     gettext_noop("Query Tuning / Planner Method Configuration"),
00564     /* QUERY_TUNING_COST */
00565     gettext_noop("Query Tuning / Planner Cost Constants"),
00566     /* QUERY_TUNING_GEQO */
00567     gettext_noop("Query Tuning / Genetic Query Optimizer"),
00568     /* QUERY_TUNING_OTHER */
00569     gettext_noop("Query Tuning / Other Planner Options"),
00570     /* LOGGING */
00571     gettext_noop("Reporting and Logging"),
00572     /* LOGGING_WHERE */
00573     gettext_noop("Reporting and Logging / Where to Log"),
00574     /* LOGGING_WHEN */
00575     gettext_noop("Reporting and Logging / When to Log"),
00576     /* LOGGING_WHAT */
00577     gettext_noop("Reporting and Logging / What to Log"),
00578     /* STATS */
00579     gettext_noop("Statistics"),
00580     /* STATS_MONITORING */
00581     gettext_noop("Statistics / Monitoring"),
00582     /* STATS_COLLECTOR */
00583     gettext_noop("Statistics / Query and Index Statistics Collector"),
00584     /* AUTOVACUUM */
00585     gettext_noop("Autovacuum"),
00586     /* CLIENT_CONN */
00587     gettext_noop("Client Connection Defaults"),
00588     /* CLIENT_CONN_STATEMENT */
00589     gettext_noop("Client Connection Defaults / Statement Behavior"),
00590     /* CLIENT_CONN_LOCALE */
00591     gettext_noop("Client Connection Defaults / Locale and Formatting"),
00592     /* CLIENT_CONN_OTHER */
00593     gettext_noop("Client Connection Defaults / Other Defaults"),
00594     /* LOCK_MANAGEMENT */
00595     gettext_noop("Lock Management"),
00596     /* COMPAT_OPTIONS */
00597     gettext_noop("Version and Platform Compatibility"),
00598     /* COMPAT_OPTIONS_PREVIOUS */
00599     gettext_noop("Version and Platform Compatibility / Previous PostgreSQL Versions"),
00600     /* COMPAT_OPTIONS_CLIENT */
00601     gettext_noop("Version and Platform Compatibility / Other Platforms and Clients"),
00602     /* ERROR_HANDLING */
00603     gettext_noop("Error Handling"),
00604     /* PRESET_OPTIONS */
00605     gettext_noop("Preset Options"),
00606     /* CUSTOM_OPTIONS */
00607     gettext_noop("Customized Options"),
00608     /* DEVELOPER_OPTIONS */
00609     gettext_noop("Developer Options"),
00610     /* help_config wants this array to be null-terminated */
00611     NULL
00612 };
00613 
00614 /*
00615  * Displayable names for GUC variable types (enum config_type)
00616  *
00617  * Note: these strings are deliberately not localized.
00618  */
00619 const char *const config_type_names[] =
00620 {
00621      /* PGC_BOOL */ "bool",
00622      /* PGC_INT */ "integer",
00623      /* PGC_REAL */ "real",
00624      /* PGC_STRING */ "string",
00625      /* PGC_ENUM */ "enum"
00626 };
00627 
00628 
00629 /*
00630  * Contents of GUC tables
00631  *
00632  * See src/backend/utils/misc/README for design notes.
00633  *
00634  * TO ADD AN OPTION:
00635  *
00636  * 1. Declare a global variable of type bool, int, double, or char*
00637  *    and make use of it.
00638  *
00639  * 2. Decide at what times it's safe to set the option. See guc.h for
00640  *    details.
00641  *
00642  * 3. Decide on a name, a default value, upper and lower bounds (if
00643  *    applicable), etc.
00644  *
00645  * 4. Add a record below.
00646  *
00647  * 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
00648  *    appropriate.
00649  *
00650  * 6. Don't forget to document the option (at least in config.sgml).
00651  *
00652  * 7. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure
00653  *    it is not single quoted at dump time.
00654  */
00655 
00656 
00657 /******** option records follow ********/
00658 
00659 static struct config_bool ConfigureNamesBool[] =
00660 {
00661     {
00662         {"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
00663             gettext_noop("Enables the planner's use of sequential-scan plans."),
00664             NULL
00665         },
00666         &enable_seqscan,
00667         true,
00668         NULL, NULL, NULL
00669     },
00670     {
00671         {"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
00672             gettext_noop("Enables the planner's use of index-scan plans."),
00673             NULL
00674         },
00675         &enable_indexscan,
00676         true,
00677         NULL, NULL, NULL
00678     },
00679     {
00680         {"enable_indexonlyscan", PGC_USERSET, QUERY_TUNING_METHOD,
00681             gettext_noop("Enables the planner's use of index-only-scan plans."),
00682             NULL
00683         },
00684         &enable_indexonlyscan,
00685         true,
00686         NULL, NULL, NULL
00687     },
00688     {
00689         {"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
00690             gettext_noop("Enables the planner's use of bitmap-scan plans."),
00691             NULL
00692         },
00693         &enable_bitmapscan,
00694         true,
00695         NULL, NULL, NULL
00696     },
00697     {
00698         {"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
00699             gettext_noop("Enables the planner's use of TID scan plans."),
00700             NULL
00701         },
00702         &enable_tidscan,
00703         true,
00704         NULL, NULL, NULL
00705     },
00706     {
00707         {"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
00708             gettext_noop("Enables the planner's use of explicit sort steps."),
00709             NULL
00710         },
00711         &enable_sort,
00712         true,
00713         NULL, NULL, NULL
00714     },
00715     {
00716         {"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
00717             gettext_noop("Enables the planner's use of hashed aggregation plans."),
00718             NULL
00719         },
00720         &enable_hashagg,
00721         true,
00722         NULL, NULL, NULL
00723     },
00724     {
00725         {"enable_material", PGC_USERSET, QUERY_TUNING_METHOD,
00726             gettext_noop("Enables the planner's use of materialization."),
00727             NULL
00728         },
00729         &enable_material,
00730         true,
00731         NULL, NULL, NULL
00732     },
00733     {
00734         {"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
00735             gettext_noop("Enables the planner's use of nested-loop join plans."),
00736             NULL
00737         },
00738         &enable_nestloop,
00739         true,
00740         NULL, NULL, NULL
00741     },
00742     {
00743         {"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
00744             gettext_noop("Enables the planner's use of merge join plans."),
00745             NULL
00746         },
00747         &enable_mergejoin,
00748         true,
00749         NULL, NULL, NULL
00750     },
00751     {
00752         {"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
00753             gettext_noop("Enables the planner's use of hash join plans."),
00754             NULL
00755         },
00756         &enable_hashjoin,
00757         true,
00758         NULL, NULL, NULL
00759     },
00760     {
00761         {"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
00762             gettext_noop("Enables genetic query optimization."),
00763             gettext_noop("This algorithm attempts to do planning without "
00764                          "exhaustive searching.")
00765         },
00766         &enable_geqo,
00767         true,
00768         NULL, NULL, NULL
00769     },
00770     {
00771         /* Not for general use --- used by SET SESSION AUTHORIZATION */
00772         {"is_superuser", PGC_INTERNAL, UNGROUPED,
00773             gettext_noop("Shows whether the current user is a superuser."),
00774             NULL,
00775             GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
00776         },
00777         &session_auth_is_superuser,
00778         false,
00779         NULL, NULL, NULL
00780     },
00781     {
00782         {"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
00783             gettext_noop("Enables advertising the server via Bonjour."),
00784             NULL
00785         },
00786         &enable_bonjour,
00787         false,
00788         check_bonjour, NULL, NULL
00789     },
00790     {
00791         {"ssl", PGC_POSTMASTER, CONN_AUTH_SECURITY,
00792             gettext_noop("Enables SSL connections."),
00793             NULL
00794         },
00795         &EnableSSL,
00796         false,
00797         check_ssl, NULL, NULL
00798     },
00799     {
00800         {"fsync", PGC_SIGHUP, WAL_SETTINGS,
00801             gettext_noop("Forces synchronization of updates to disk."),
00802             gettext_noop("The server will use the fsync() system call in several places to make "
00803             "sure that updates are physically written to disk. This insures "
00804                          "that a database cluster will recover to a consistent state after "
00805                          "an operating system or hardware crash.")
00806         },
00807         &enableFsync,
00808         true,
00809         NULL, NULL, NULL
00810     },
00811     {
00812         {"ignore_checksum_failure", PGC_SUSET, DEVELOPER_OPTIONS,
00813             gettext_noop("Continues processing after a checksum failure."),
00814             gettext_noop("Detection of a checksum failure normally causes PostgreSQL to "
00815                 "report an error, aborting the current transaction. Setting "
00816                          "ignore_checksum_failure to true causes the system to ignore the failure "
00817                          "(but still report a warning), and continue processing. This "
00818                          "behavior could cause crashes or other serious problems. Only "
00819                          "has an effect if checksums are enabled."),
00820             GUC_NOT_IN_SAMPLE
00821         },
00822         &ignore_checksum_failure,
00823         false,
00824         NULL, NULL, NULL
00825     },
00826     {
00827         {"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
00828             gettext_noop("Continues processing past damaged page headers."),
00829             gettext_noop("Detection of a damaged page header normally causes PostgreSQL to "
00830                 "report an error, aborting the current transaction. Setting "
00831                          "zero_damaged_pages to true causes the system to instead report a "
00832                          "warning, zero out the damaged page, and continue processing. This "
00833                          "behavior will destroy data, namely all the rows on the damaged page."),
00834             GUC_NOT_IN_SAMPLE
00835         },
00836         &zero_damaged_pages,
00837         false,
00838         NULL, NULL, NULL
00839     },
00840     {
00841         {"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
00842             gettext_noop("Writes full pages to WAL when first modified after a checkpoint."),
00843             gettext_noop("A page write in process during an operating system crash might be "
00844                          "only partially written to disk.  During recovery, the row changes "
00845               "stored in WAL are not enough to recover.  This option writes "
00846                          "pages when first modified after a checkpoint to WAL so full recovery "
00847                          "is possible.")
00848         },
00849         &fullPageWrites,
00850         true,
00851         NULL, NULL, NULL
00852     },
00853     {
00854         {"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
00855             gettext_noop("Logs each checkpoint."),
00856             NULL
00857         },
00858         &log_checkpoints,
00859         false,
00860         NULL, NULL, NULL
00861     },
00862     {
00863         {"log_connections", PGC_BACKEND, LOGGING_WHAT,
00864             gettext_noop("Logs each successful connection."),
00865             NULL
00866         },
00867         &Log_connections,
00868         false,
00869         NULL, NULL, NULL
00870     },
00871     {
00872         {"log_disconnections", PGC_BACKEND, LOGGING_WHAT,
00873             gettext_noop("Logs end of a session, including duration."),
00874             NULL
00875         },
00876         &Log_disconnections,
00877         false,
00878         NULL, NULL, NULL
00879     },
00880     {
00881         {"debug_assertions", PGC_USERSET, DEVELOPER_OPTIONS,
00882             gettext_noop("Turns on various assertion checks."),
00883             gettext_noop("This is a debugging aid."),
00884             GUC_NOT_IN_SAMPLE
00885         },
00886         &assert_enabled,
00887 #ifdef USE_ASSERT_CHECKING
00888         true,
00889 #else
00890         false,
00891 #endif
00892         check_debug_assertions, NULL, NULL
00893     },
00894 
00895     {
00896         {"exit_on_error", PGC_USERSET, ERROR_HANDLING_OPTIONS,
00897             gettext_noop("Terminate session on any error."),
00898             NULL
00899         },
00900         &ExitOnAnyError,
00901         false,
00902         NULL, NULL, NULL
00903     },
00904     {
00905         {"restart_after_crash", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
00906             gettext_noop("Reinitialize server after backend crash."),
00907             NULL
00908         },
00909         &restart_after_crash,
00910         true,
00911         NULL, NULL, NULL
00912     },
00913 
00914     {
00915         {"log_duration", PGC_SUSET, LOGGING_WHAT,
00916             gettext_noop("Logs the duration of each completed SQL statement."),
00917             NULL
00918         },
00919         &log_duration,
00920         false,
00921         NULL, NULL, NULL
00922     },
00923     {
00924         {"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
00925             gettext_noop("Logs each query's parse tree."),
00926             NULL
00927         },
00928         &Debug_print_parse,
00929         false,
00930         NULL, NULL, NULL
00931     },
00932     {
00933         {"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
00934             gettext_noop("Logs each query's rewritten parse tree."),
00935             NULL
00936         },
00937         &Debug_print_rewritten,
00938         false,
00939         NULL, NULL, NULL
00940     },
00941     {
00942         {"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
00943             gettext_noop("Logs each query's execution plan."),
00944             NULL
00945         },
00946         &Debug_print_plan,
00947         false,
00948         NULL, NULL, NULL
00949     },
00950     {
00951         {"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
00952             gettext_noop("Indents parse and plan tree displays."),
00953             NULL
00954         },
00955         &Debug_pretty_print,
00956         true,
00957         NULL, NULL, NULL
00958     },
00959     {
00960         {"log_parser_stats", PGC_SUSET, STATS_MONITORING,
00961             gettext_noop("Writes parser performance statistics to the server log."),
00962             NULL
00963         },
00964         &log_parser_stats,
00965         false,
00966         check_stage_log_stats, NULL, NULL
00967     },
00968     {
00969         {"log_planner_stats", PGC_SUSET, STATS_MONITORING,
00970             gettext_noop("Writes planner performance statistics to the server log."),
00971             NULL
00972         },
00973         &log_planner_stats,
00974         false,
00975         check_stage_log_stats, NULL, NULL
00976     },
00977     {
00978         {"log_executor_stats", PGC_SUSET, STATS_MONITORING,
00979             gettext_noop("Writes executor performance statistics to the server log."),
00980             NULL
00981         },
00982         &log_executor_stats,
00983         false,
00984         check_stage_log_stats, NULL, NULL
00985     },
00986     {
00987         {"log_statement_stats", PGC_SUSET, STATS_MONITORING,
00988             gettext_noop("Writes cumulative performance statistics to the server log."),
00989             NULL
00990         },
00991         &log_statement_stats,
00992         false,
00993         check_log_stats, NULL, NULL
00994     },
00995 #ifdef BTREE_BUILD_STATS
00996     {
00997         {"log_btree_build_stats", PGC_SUSET, DEVELOPER_OPTIONS,
00998             gettext_noop("No description available."),
00999             NULL,
01000             GUC_NOT_IN_SAMPLE
01001         },
01002         &log_btree_build_stats,
01003         false,
01004         NULL, NULL, NULL
01005     },
01006 #endif
01007 
01008     {
01009         {"track_activities", PGC_SUSET, STATS_COLLECTOR,
01010             gettext_noop("Collects information about executing commands."),
01011             gettext_noop("Enables the collection of information on the currently "
01012                          "executing command of each session, along with "
01013                          "the time at which that command began execution.")
01014         },
01015         &pgstat_track_activities,
01016         true,
01017         NULL, NULL, NULL
01018     },
01019     {
01020         {"track_counts", PGC_SUSET, STATS_COLLECTOR,
01021             gettext_noop("Collects statistics on database activity."),
01022             NULL
01023         },
01024         &pgstat_track_counts,
01025         true,
01026         NULL, NULL, NULL
01027     },
01028     {
01029         {"track_io_timing", PGC_SUSET, STATS_COLLECTOR,
01030             gettext_noop("Collects timing statistics for database I/O activity."),
01031             NULL
01032         },
01033         &track_io_timing,
01034         false,
01035         NULL, NULL, NULL
01036     },
01037 
01038     {
01039         {"update_process_title", PGC_SUSET, STATS_COLLECTOR,
01040             gettext_noop("Updates the process title to show the active SQL command."),
01041             gettext_noop("Enables updating of the process title every time a new SQL command is received by the server.")
01042         },
01043         &update_process_title,
01044         true,
01045         NULL, NULL, NULL
01046     },
01047 
01048     {
01049         {"autovacuum", PGC_SIGHUP, AUTOVACUUM,
01050             gettext_noop("Starts the autovacuum subprocess."),
01051             NULL
01052         },
01053         &autovacuum_start_daemon,
01054         true,
01055         NULL, NULL, NULL
01056     },
01057 
01058     {
01059         {"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
01060             gettext_noop("Generates debugging output for LISTEN and NOTIFY."),
01061             NULL,
01062             GUC_NOT_IN_SAMPLE
01063         },
01064         &Trace_notify,
01065         false,
01066         NULL, NULL, NULL
01067     },
01068 
01069 #ifdef LOCK_DEBUG
01070     {
01071         {"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
01072             gettext_noop("No description available."),
01073             NULL,
01074             GUC_NOT_IN_SAMPLE
01075         },
01076         &Trace_locks,
01077         false,
01078         NULL, NULL, NULL
01079     },
01080     {
01081         {"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
01082             gettext_noop("No description available."),
01083             NULL,
01084             GUC_NOT_IN_SAMPLE
01085         },
01086         &Trace_userlocks,
01087         false,
01088         NULL, NULL, NULL
01089     },
01090     {
01091         {"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
01092             gettext_noop("No description available."),
01093             NULL,
01094             GUC_NOT_IN_SAMPLE
01095         },
01096         &Trace_lwlocks,
01097         false,
01098         NULL, NULL, NULL
01099     },
01100     {
01101         {"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
01102             gettext_noop("No description available."),
01103             NULL,
01104             GUC_NOT_IN_SAMPLE
01105         },
01106         &Debug_deadlocks,
01107         false,
01108         NULL, NULL, NULL
01109     },
01110 #endif
01111 
01112     {
01113         {"log_lock_waits", PGC_SUSET, LOGGING_WHAT,
01114             gettext_noop("Logs long lock waits."),
01115             NULL
01116         },
01117         &log_lock_waits,
01118         false,
01119         NULL, NULL, NULL
01120     },
01121 
01122     {
01123         {"log_hostname", PGC_SIGHUP, LOGGING_WHAT,
01124             gettext_noop("Logs the host name in the connection logs."),
01125             gettext_noop("By default, connection logs only show the IP address "
01126                          "of the connecting host. If you want them to show the host name you "
01127               "can turn this on, but depending on your host name resolution "
01128                "setup it might impose a non-negligible performance penalty.")
01129         },
01130         &log_hostname,
01131         false,
01132         NULL, NULL, NULL
01133     },
01134     {
01135         {"sql_inheritance", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
01136             gettext_noop("Causes subtables to be included by default in various commands."),
01137             NULL
01138         },
01139         &SQL_inheritance,
01140         true,
01141         NULL, NULL, NULL
01142     },
01143     {
01144         {"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
01145             gettext_noop("Encrypt passwords."),
01146             gettext_noop("When a password is specified in CREATE USER or "
01147                "ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
01148                          "this parameter determines whether the password is to be encrypted.")
01149         },
01150         &Password_encryption,
01151         true,
01152         NULL, NULL, NULL
01153     },
01154     {
01155         {"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
01156             gettext_noop("Treats \"expr=NULL\" as \"expr IS NULL\"."),
01157             gettext_noop("When turned on, expressions of the form expr = NULL "
01158                "(or NULL = expr) are treated as expr IS NULL, that is, they "
01159                 "return true if expr evaluates to the null value, and false "
01160                "otherwise. The correct behavior of expr = NULL is to always "
01161                          "return null (unknown).")
01162         },
01163         &Transform_null_equals,
01164         false,
01165         NULL, NULL, NULL
01166     },
01167     {
01168         {"db_user_namespace", PGC_SIGHUP, CONN_AUTH_SECURITY,
01169             gettext_noop("Enables per-database user names."),
01170             NULL
01171         },
01172         &Db_user_namespace,
01173         false,
01174         NULL, NULL, NULL
01175     },
01176     {
01177         /* only here for backwards compatibility */
01178         {"autocommit", PGC_USERSET, CLIENT_CONN_STATEMENT,
01179             gettext_noop("This parameter doesn't do anything."),
01180             gettext_noop("It's just here so that we won't choke on SET AUTOCOMMIT TO ON from 7.3-vintage clients."),
01181             GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
01182         },
01183         &phony_autocommit,
01184         true,
01185         check_phony_autocommit, NULL, NULL
01186     },
01187     {
01188         {"default_transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
01189             gettext_noop("Sets the default read-only status of new transactions."),
01190             NULL
01191         },
01192         &DefaultXactReadOnly,
01193         false,
01194         NULL, NULL, NULL
01195     },
01196     {
01197         {"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
01198             gettext_noop("Sets the current transaction's read-only status."),
01199             NULL,
01200             GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
01201         },
01202         &XactReadOnly,
01203         false,
01204         check_transaction_read_only, NULL, NULL
01205     },
01206     {
01207         {"default_transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
01208             gettext_noop("Sets the default deferrable status of new transactions."),
01209             NULL
01210         },
01211         &DefaultXactDeferrable,
01212         false,
01213         NULL, NULL, NULL
01214     },
01215     {
01216         {"transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
01217             gettext_noop("Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures."),
01218             NULL,
01219             GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
01220         },
01221         &XactDeferrable,
01222         false,
01223         check_transaction_deferrable, NULL, NULL
01224     },
01225     {
01226         {"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
01227             gettext_noop("Check function bodies during CREATE FUNCTION."),
01228             NULL
01229         },
01230         &check_function_bodies,
01231         true,
01232         NULL, NULL, NULL
01233     },
01234     {
01235         {"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
01236             gettext_noop("Enable input of NULL elements in arrays."),
01237             gettext_noop("When turned on, unquoted NULL in an array input "
01238                          "value means a null value; "
01239                          "otherwise it is taken literally.")
01240         },
01241         &Array_nulls,
01242         true,
01243         NULL, NULL, NULL
01244     },
01245     {
01246         {"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
01247             gettext_noop("Create new tables with OIDs by default."),
01248             NULL
01249         },
01250         &default_with_oids,
01251         false,
01252         NULL, NULL, NULL
01253     },
01254     {
01255         {"logging_collector", PGC_POSTMASTER, LOGGING_WHERE,
01256             gettext_noop("Start a subprocess to capture stderr output and/or csvlogs into log files."),
01257             NULL
01258         },
01259         &Logging_collector,
01260         false,
01261         NULL, NULL, NULL
01262     },
01263     {
01264         {"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
01265             gettext_noop("Truncate existing log files of same name during log rotation."),
01266             NULL
01267         },
01268         &Log_truncate_on_rotation,
01269         false,
01270         NULL, NULL, NULL
01271     },
01272 
01273 #ifdef TRACE_SORT
01274     {
01275         {"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
01276             gettext_noop("Emit information about resource usage in sorting."),
01277             NULL,
01278             GUC_NOT_IN_SAMPLE
01279         },
01280         &trace_sort,
01281         false,
01282         NULL, NULL, NULL
01283     },
01284 #endif
01285 
01286 #ifdef TRACE_SYNCSCAN
01287     /* this is undocumented because not exposed in a standard build */
01288     {
01289         {"trace_syncscan", PGC_USERSET, DEVELOPER_OPTIONS,
01290             gettext_noop("Generate debugging output for synchronized scanning."),
01291             NULL,
01292             GUC_NOT_IN_SAMPLE
01293         },
01294         &trace_syncscan,
01295         false,
01296         NULL, NULL, NULL
01297     },
01298 #endif
01299 
01300 #ifdef DEBUG_BOUNDED_SORT
01301     /* this is undocumented because not exposed in a standard build */
01302     {
01303         {
01304             "optimize_bounded_sort", PGC_USERSET, QUERY_TUNING_METHOD,
01305             gettext_noop("Enable bounded sorting using heap sort."),
01306             NULL,
01307             GUC_NOT_IN_SAMPLE
01308         },
01309         &optimize_bounded_sort,
01310         true,
01311         NULL, NULL, NULL
01312     },
01313 #endif
01314 
01315 #ifdef WAL_DEBUG
01316     {
01317         {"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
01318             gettext_noop("Emit WAL-related debugging output."),
01319             NULL,
01320             GUC_NOT_IN_SAMPLE
01321         },
01322         &XLOG_DEBUG,
01323         false,
01324         NULL, NULL, NULL
01325     },
01326 #endif
01327 
01328     {
01329         {"integer_datetimes", PGC_INTERNAL, PRESET_OPTIONS,
01330             gettext_noop("Datetimes are integer based."),
01331             NULL,
01332             GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
01333         },
01334         &integer_datetimes,
01335 #ifdef HAVE_INT64_TIMESTAMP
01336         true,
01337 #else
01338         false,
01339 #endif
01340         NULL, NULL, NULL
01341     },
01342 
01343     {
01344         {"krb_caseins_users", PGC_SIGHUP, CONN_AUTH_SECURITY,
01345             gettext_noop("Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."),
01346             NULL
01347         },
01348         &pg_krb_caseins_users,
01349         false,
01350         NULL, NULL, NULL
01351     },
01352 
01353     {
01354         {"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
01355             gettext_noop("Warn about backslash escapes in ordinary string literals."),
01356             NULL
01357         },
01358         &escape_string_warning,
01359         true,
01360         NULL, NULL, NULL
01361     },
01362 
01363     {
01364         {"standard_conforming_strings", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
01365             gettext_noop("Causes '...' strings to treat backslashes literally."),
01366             NULL,
01367             GUC_REPORT
01368         },
01369         &standard_conforming_strings,
01370         true,
01371         NULL, NULL, NULL
01372     },
01373 
01374     {
01375         {"synchronize_seqscans", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
01376             gettext_noop("Enable synchronized sequential scans."),
01377             NULL
01378         },
01379         &synchronize_seqscans,
01380         true,
01381         NULL, NULL, NULL
01382     },
01383 
01384     {
01385         {"archive_mode", PGC_POSTMASTER, WAL_ARCHIVING,
01386             gettext_noop("Allows archiving of WAL files using archive_command."),
01387             NULL
01388         },
01389         &XLogArchiveMode,
01390         false,
01391         NULL, NULL, NULL
01392     },
01393 
01394     {
01395         {"hot_standby", PGC_POSTMASTER, REPLICATION_STANDBY,
01396             gettext_noop("Allows connections and queries during recovery."),
01397             NULL
01398         },
01399         &EnableHotStandby,
01400         false,
01401         NULL, NULL, NULL
01402     },
01403 
01404     {
01405         {"hot_standby_feedback", PGC_SIGHUP, REPLICATION_STANDBY,
01406             gettext_noop("Allows feedback from a hot standby to the primary that will avoid query conflicts."),
01407             NULL
01408         },
01409         &hot_standby_feedback,
01410         false,
01411         NULL, NULL, NULL
01412     },
01413 
01414     {
01415         {"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS,
01416             gettext_noop("Allows modifications of the structure of system tables."),
01417             NULL,
01418             GUC_NOT_IN_SAMPLE
01419         },
01420         &allowSystemTableMods,
01421         false,
01422         NULL, NULL, NULL
01423     },
01424 
01425     {
01426         {"ignore_system_indexes", PGC_BACKEND, DEVELOPER_OPTIONS,
01427             gettext_noop("Disables reading from system indexes."),
01428             gettext_noop("It does not prevent updating the indexes, so it is safe "
01429                          "to use.  The worst consequence is slowness."),
01430             GUC_NOT_IN_SAMPLE
01431         },
01432         &IgnoreSystemIndexes,
01433         false,
01434         NULL, NULL, NULL
01435     },
01436 
01437     {
01438         {"lo_compat_privileges", PGC_SUSET, COMPAT_OPTIONS_PREVIOUS,
01439             gettext_noop("Enables backward compatibility mode for privilege checks on large objects."),
01440             gettext_noop("Skips privilege checks when reading or modifying large objects, "
01441                   "for compatibility with PostgreSQL releases prior to 9.0.")
01442         },
01443         &lo_compat_privileges,
01444         false,
01445         NULL, NULL, NULL
01446     },
01447 
01448     {
01449         {"quote_all_identifiers", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
01450             gettext_noop("When generating SQL fragments, quote all identifiers."),
01451             NULL,
01452         },
01453         &quote_all_identifiers,
01454         false,
01455         NULL, NULL, NULL
01456     },
01457 
01458     /* End-of-list marker */
01459     {
01460         {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
01461     }
01462 };
01463 
01464 
01465 static struct config_int ConfigureNamesInt[] =
01466 {
01467     {
01468         {"archive_timeout", PGC_SIGHUP, WAL_ARCHIVING,
01469             gettext_noop("Forces a switch to the next xlog file if a "
01470                          "new file has not been started within N seconds."),
01471             NULL,
01472             GUC_UNIT_S
01473         },
01474         &XLogArchiveTimeout,
01475         0, 0, INT_MAX / 2,
01476         NULL, NULL, NULL
01477     },
01478     {
01479         {"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
01480             gettext_noop("Waits N seconds on connection startup after authentication."),
01481             gettext_noop("This allows attaching a debugger to the process."),
01482             GUC_NOT_IN_SAMPLE | GUC_UNIT_S
01483         },
01484         &PostAuthDelay,
01485         0, 0, INT_MAX / 1000000,
01486         NULL, NULL, NULL
01487     },
01488     {
01489         {"default_statistics_target", PGC_USERSET, QUERY_TUNING_OTHER,
01490             gettext_noop("Sets the default statistics target."),
01491             gettext_noop("This applies to table columns that have not had a "
01492                 "column-specific target set via ALTER TABLE SET STATISTICS.")
01493         },
01494         &default_statistics_target,
01495         100, 1, 10000,
01496         NULL, NULL, NULL
01497     },
01498     {
01499         {"from_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
01500             gettext_noop("Sets the FROM-list size beyond which subqueries "
01501                          "are not collapsed."),
01502             gettext_noop("The planner will merge subqueries into upper "
01503                 "queries if the resulting FROM list would have no more than "
01504                          "this many items.")
01505         },
01506         &from_collapse_limit,
01507         8, 1, INT_MAX,
01508         NULL, NULL, NULL
01509     },
01510     {
01511         {"join_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
01512             gettext_noop("Sets the FROM-list size beyond which JOIN "
01513                          "constructs are not flattened."),
01514             gettext_noop("The planner will flatten explicit JOIN "
01515                          "constructs into lists of FROM items whenever a "
01516                          "list of no more than this many items would result.")
01517         },
01518         &join_collapse_limit,
01519         8, 1, INT_MAX,
01520         NULL, NULL, NULL
01521     },
01522     {
01523         {"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
01524             gettext_noop("Sets the threshold of FROM items beyond which GEQO is used."),
01525             NULL
01526         },
01527         &geqo_threshold,
01528         12, 2, INT_MAX,
01529         NULL, NULL, NULL
01530     },
01531     {
01532         {"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
01533             gettext_noop("GEQO: effort is used to set the default for other GEQO parameters."),
01534             NULL
01535         },
01536         &Geqo_effort,
01537         DEFAULT_GEQO_EFFORT, MIN_GEQO_EFFORT, MAX_GEQO_EFFORT,
01538         NULL, NULL, NULL
01539     },
01540     {
01541         {"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
01542             gettext_noop("GEQO: number of individuals in the population."),
01543             gettext_noop("Zero selects a suitable default value.")
01544         },
01545         &Geqo_pool_size,
01546         0, 0, INT_MAX,
01547         NULL, NULL, NULL
01548     },
01549     {
01550         {"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
01551             gettext_noop("GEQO: number of iterations of the algorithm."),
01552             gettext_noop("Zero selects a suitable default value.")
01553         },
01554         &Geqo_generations,
01555         0, 0, INT_MAX,
01556         NULL, NULL, NULL
01557     },
01558 
01559     {
01560         /* This is PGC_SUSET to prevent hiding from log_lock_waits. */
01561         {"deadlock_timeout", PGC_SUSET, LOCK_MANAGEMENT,
01562             gettext_noop("Sets the time to wait on a lock before checking for deadlock."),
01563             NULL,
01564             GUC_UNIT_MS
01565         },
01566         &DeadlockTimeout,
01567         1000, 1, INT_MAX,
01568         NULL, NULL, NULL
01569     },
01570 
01571     {
01572         {"max_standby_archive_delay", PGC_SIGHUP, REPLICATION_STANDBY,
01573             gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data."),
01574             NULL,
01575             GUC_UNIT_MS
01576         },
01577         &max_standby_archive_delay,
01578         30 * 1000, -1, INT_MAX,
01579         NULL, NULL, NULL
01580     },
01581 
01582     {
01583         {"max_standby_streaming_delay", PGC_SIGHUP, REPLICATION_STANDBY,
01584             gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data."),
01585             NULL,
01586             GUC_UNIT_MS
01587         },
01588         &max_standby_streaming_delay,
01589         30 * 1000, -1, INT_MAX,
01590         NULL, NULL, NULL
01591     },
01592 
01593     {
01594         {"wal_receiver_status_interval", PGC_SIGHUP, REPLICATION_STANDBY,
01595             gettext_noop("Sets the maximum interval between WAL receiver status reports to the primary."),
01596             NULL,
01597             GUC_UNIT_S
01598         },
01599         &wal_receiver_status_interval,
01600         10, 0, INT_MAX / 1000,
01601         NULL, NULL, NULL
01602     },
01603 
01604     {
01605         {"wal_receiver_timeout", PGC_SIGHUP, REPLICATION_STANDBY,
01606             gettext_noop("Sets the maximum wait time to receive data from master."),
01607             NULL,
01608             GUC_UNIT_MS
01609         },
01610         &wal_receiver_timeout,
01611         60 * 1000, 0, INT_MAX,
01612         NULL, NULL, NULL
01613     },
01614 
01615     {
01616         {"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
01617             gettext_noop("Sets the maximum number of concurrent connections."),
01618             NULL
01619         },
01620         &MaxConnections,
01621         100, 1, MAX_BACKENDS,
01622         check_maxconnections, NULL, NULL
01623     },
01624 
01625     {
01626         {"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
01627             gettext_noop("Sets the number of connection slots reserved for superusers."),
01628             NULL
01629         },
01630         &ReservedBackends,
01631         3, 0, MAX_BACKENDS,
01632         NULL, NULL, NULL
01633     },
01634 
01635     /*
01636      * We sometimes multiply the number of shared buffers by two without
01637      * checking for overflow, so we mustn't allow more than INT_MAX / 2.
01638      */
01639     {
01640         {"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
01641             gettext_noop("Sets the number of shared memory buffers used by the server."),
01642             NULL,
01643             GUC_UNIT_BLOCKS
01644         },
01645         &NBuffers,
01646         1024, 16, INT_MAX / 2,
01647         NULL, NULL, NULL
01648     },
01649 
01650     {
01651         {"temp_buffers", PGC_USERSET, RESOURCES_MEM,
01652             gettext_noop("Sets the maximum number of temporary buffers used by each session."),
01653             NULL,
01654             GUC_UNIT_BLOCKS
01655         },
01656         &num_temp_buffers,
01657         1024, 100, INT_MAX / 2,
01658         check_temp_buffers, NULL, NULL
01659     },
01660 
01661     {
01662         {"port", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
01663             gettext_noop("Sets the TCP port the server listens on."),
01664             NULL
01665         },
01666         &PostPortNumber,
01667         DEF_PGPORT, 1, 65535,
01668         NULL, NULL, NULL
01669     },
01670 
01671     {
01672         {"unix_socket_permissions", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
01673             gettext_noop("Sets the access permissions of the Unix-domain socket."),
01674             gettext_noop("Unix-domain sockets use the usual Unix file system "
01675                          "permission set. The parameter value is expected "
01676                          "to be a numeric mode specification in the form "
01677                          "accepted by the chmod and umask system calls. "
01678                          "(To use the customary octal format the number must "
01679                          "start with a 0 (zero).)")
01680         },
01681         &Unix_socket_permissions,
01682         0777, 0000, 0777,
01683         NULL, NULL, show_unix_socket_permissions
01684     },
01685 
01686     {
01687         {"log_file_mode", PGC_SIGHUP, LOGGING_WHERE,
01688             gettext_noop("Sets the file permissions for log files."),
01689             gettext_noop("The parameter value is expected "
01690                          "to be a numeric mode specification in the form "
01691                          "accepted by the chmod and umask system calls. "
01692                          "(To use the customary octal format the number must "
01693                          "start with a 0 (zero).)")
01694         },
01695         &Log_file_mode,
01696         0600, 0000, 0777,
01697         NULL, NULL, show_log_file_mode
01698     },
01699 
01700     {
01701         {"work_mem", PGC_USERSET, RESOURCES_MEM,
01702             gettext_noop("Sets the maximum memory to be used for query workspaces."),
01703             gettext_noop("This much memory can be used by each internal "
01704                          "sort operation and hash table before switching to "
01705                          "temporary disk files."),
01706             GUC_UNIT_KB
01707         },
01708         &work_mem,
01709         1024, 64, MAX_KILOBYTES,
01710         NULL, NULL, NULL
01711     },
01712 
01713     {
01714         {"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
01715             gettext_noop("Sets the maximum memory to be used for maintenance operations."),
01716             gettext_noop("This includes operations such as VACUUM and CREATE INDEX."),
01717             GUC_UNIT_KB
01718         },
01719         &maintenance_work_mem,
01720         16384, 1024, MAX_KILOBYTES,
01721         NULL, NULL, NULL
01722     },
01723 
01724     /*
01725      * We use the hopefully-safely-small value of 100kB as the compiled-in
01726      * default for max_stack_depth.  InitializeGUCOptions will increase it if
01727      * possible, depending on the actual platform-specific stack limit.
01728      */
01729     {
01730         {"max_stack_depth", PGC_SUSET, RESOURCES_MEM,
01731             gettext_noop("Sets the maximum stack depth, in kilobytes."),
01732             NULL,
01733             GUC_UNIT_KB
01734         },
01735         &max_stack_depth,
01736         100, 100, MAX_KILOBYTES,
01737         check_max_stack_depth, assign_max_stack_depth, NULL
01738     },
01739 
01740     {
01741         {"temp_file_limit", PGC_SUSET, RESOURCES_DISK,
01742             gettext_noop("Limits the total size of all temporary files used by each session."),
01743             gettext_noop("-1 means no limit."),
01744             GUC_UNIT_KB
01745         },
01746         &temp_file_limit,
01747         -1, -1, INT_MAX,
01748         NULL, NULL, NULL
01749     },
01750 
01751     {
01752         {"vacuum_cost_page_hit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
01753             gettext_noop("Vacuum cost for a page found in the buffer cache."),
01754             NULL
01755         },
01756         &VacuumCostPageHit,
01757         1, 0, 10000,
01758         NULL, NULL, NULL
01759     },
01760 
01761     {
01762         {"vacuum_cost_page_miss", PGC_USERSET, RESOURCES_VACUUM_DELAY,
01763             gettext_noop("Vacuum cost for a page not found in the buffer cache."),
01764             NULL
01765         },
01766         &VacuumCostPageMiss,
01767         10, 0, 10000,
01768         NULL, NULL, NULL
01769     },
01770 
01771     {
01772         {"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES_VACUUM_DELAY,
01773             gettext_noop("Vacuum cost for a page dirtied by vacuum."),
01774             NULL
01775         },
01776         &VacuumCostPageDirty,
01777         20, 0, 10000,
01778         NULL, NULL, NULL
01779     },
01780 
01781     {
01782         {"vacuum_cost_limit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
01783             gettext_noop("Vacuum cost amount available before napping."),
01784             NULL
01785         },
01786         &VacuumCostLimit,
01787         200, 1, 10000,
01788         NULL, NULL, NULL
01789     },
01790 
01791     {
01792         {"vacuum_cost_delay", PGC_USERSET, RESOURCES_VACUUM_DELAY,
01793             gettext_noop("Vacuum cost delay in milliseconds."),
01794             NULL,
01795             GUC_UNIT_MS
01796         },
01797         &VacuumCostDelay,
01798         0, 0, 100,
01799         NULL, NULL, NULL
01800     },
01801 
01802     {
01803         {"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
01804             gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
01805             NULL,
01806             GUC_UNIT_MS
01807         },
01808         &autovacuum_vac_cost_delay,
01809         20, -1, 100,
01810         NULL, NULL, NULL
01811     },
01812 
01813     {
01814         {"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
01815             gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
01816             NULL
01817         },
01818         &autovacuum_vac_cost_limit,
01819         -1, -1, 10000,
01820         NULL, NULL, NULL
01821     },
01822 
01823     {
01824         {"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
01825             gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
01826             NULL
01827         },
01828         &max_files_per_process,
01829         1000, 25, INT_MAX,
01830         NULL, NULL, NULL
01831     },
01832 
01833     /*
01834      * See also CheckRequiredParameterValues() if this parameter changes
01835      */
01836     {
01837         {"max_prepared_transactions", PGC_POSTMASTER, RESOURCES_MEM,
01838             gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
01839             NULL
01840         },
01841         &max_prepared_xacts,
01842         0, 0, MAX_BACKENDS,
01843         NULL, NULL, NULL
01844     },
01845 
01846 #ifdef LOCK_DEBUG
01847     {
01848         {"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
01849             gettext_noop("No description available."),
01850             NULL,
01851             GUC_NOT_IN_SAMPLE
01852         },
01853         &Trace_lock_oidmin,
01854         FirstNormalObjectId, 0, INT_MAX,
01855         NULL, NULL, NULL
01856     },
01857     {
01858         {"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
01859             gettext_noop("No description available."),
01860             NULL,
01861             GUC_NOT_IN_SAMPLE
01862         },
01863         &Trace_lock_table,
01864         0, 0, INT_MAX,
01865         NULL, NULL, NULL
01866     },
01867 #endif
01868 
01869     {
01870         {"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
01871             gettext_noop("Sets the maximum allowed duration of any statement."),
01872             gettext_noop("A value of 0 turns off the timeout."),
01873             GUC_UNIT_MS
01874         },
01875         &StatementTimeout,
01876         0, 0, INT_MAX,
01877         NULL, NULL, NULL
01878     },
01879 
01880     {
01881         {"lock_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
01882             gettext_noop("Sets the maximum allowed duration of any wait for a lock."),
01883             gettext_noop("A value of 0 turns off the timeout."),
01884             GUC_UNIT_MS
01885         },
01886         &LockTimeout,
01887         0, 0, INT_MAX,
01888         NULL, NULL, NULL
01889     },
01890 
01891     {
01892         {"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
01893             gettext_noop("Minimum age at which VACUUM should freeze a table row."),
01894             NULL
01895         },
01896         &vacuum_freeze_min_age,
01897         50000000, 0, 1000000000,
01898         NULL, NULL, NULL
01899     },
01900 
01901     {
01902         {"vacuum_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
01903             gettext_noop("Age at which VACUUM should scan whole table to freeze tuples."),
01904             NULL
01905         },
01906         &vacuum_freeze_table_age,
01907         150000000, 0, 2000000000,
01908         NULL, NULL, NULL
01909     },
01910 
01911     {
01912         {"vacuum_defer_cleanup_age", PGC_SIGHUP, REPLICATION_MASTER,
01913             gettext_noop("Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."),
01914             NULL
01915         },
01916         &vacuum_defer_cleanup_age,
01917         0, 0, 1000000,
01918         NULL, NULL, NULL
01919     },
01920 
01921     /*
01922      * See also CheckRequiredParameterValues() if this parameter changes
01923      */
01924     {
01925         {"max_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
01926             gettext_noop("Sets the maximum number of locks per transaction."),
01927             gettext_noop("The shared lock table is sized on the assumption that "
01928               "at most max_locks_per_transaction * max_connections distinct "
01929                          "objects will need to be locked at any one time.")
01930         },
01931         &max_locks_per_xact,
01932         64, 10, INT_MAX,
01933         NULL, NULL, NULL
01934     },
01935 
01936     {
01937         {"max_pred_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
01938             gettext_noop("Sets the maximum number of predicate locks per transaction."),
01939             gettext_noop("The shared predicate lock table is sized on the assumption that "
01940                          "at most max_pred_locks_per_transaction * max_connections distinct "
01941                          "objects will need to be locked at any one time.")
01942         },
01943         &max_predicate_locks_per_xact,
01944         64, 10, INT_MAX,
01945         NULL, NULL, NULL
01946     },
01947 
01948     {
01949         {"authentication_timeout", PGC_SIGHUP, CONN_AUTH_SECURITY,
01950             gettext_noop("Sets the maximum allowed time to complete client authentication."),
01951             NULL,
01952             GUC_UNIT_S
01953         },
01954         &AuthenticationTimeout,
01955         60, 1, 600,
01956         NULL, NULL, NULL
01957     },
01958 
01959     {
01960         /* Not for general use */
01961         {"pre_auth_delay", PGC_SIGHUP, DEVELOPER_OPTIONS,
01962             gettext_noop("Waits N seconds on connection startup before authentication."),
01963             gettext_noop("This allows attaching a debugger to the process."),
01964             GUC_NOT_IN_SAMPLE | GUC_UNIT_S
01965         },
01966         &PreAuthDelay,
01967         0, 0, 60,
01968         NULL, NULL, NULL
01969     },
01970 
01971     {
01972         {"wal_keep_segments", PGC_SIGHUP, REPLICATION_SENDING,
01973             gettext_noop("Sets the number of WAL files held for standby servers."),
01974             NULL
01975         },
01976         &wal_keep_segments,
01977         0, 0, INT_MAX,
01978         NULL, NULL, NULL
01979     },
01980 
01981     {
01982         {"checkpoint_segments", PGC_SIGHUP, WAL_CHECKPOINTS,
01983             gettext_noop("Sets the maximum distance in log segments between automatic WAL checkpoints."),
01984             NULL
01985         },
01986         &CheckPointSegments,
01987         3, 1, INT_MAX,
01988         NULL, NULL, NULL
01989     },
01990 
01991     {
01992         {"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS,
01993             gettext_noop("Sets the maximum time between automatic WAL checkpoints."),
01994             NULL,
01995             GUC_UNIT_S
01996         },
01997         &CheckPointTimeout,
01998         300, 30, 3600,
01999         NULL, NULL, NULL
02000     },
02001 
02002     {
02003         {"checkpoint_warning", PGC_SIGHUP, WAL_CHECKPOINTS,
02004             gettext_noop("Enables warnings if checkpoint segments are filled more "
02005                          "frequently than this."),
02006             gettext_noop("Write a message to the server log if checkpoints "
02007             "caused by the filling of checkpoint segment files happens more "
02008                          "frequently than this number of seconds. Zero turns off the warning."),
02009             GUC_UNIT_S
02010         },
02011         &CheckPointWarning,
02012         30, 0, INT_MAX,
02013         NULL, NULL, NULL
02014     },
02015 
02016     {
02017         {"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
02018             gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
02019             NULL,
02020             GUC_UNIT_XBLOCKS
02021         },
02022         &XLOGbuffers,
02023         -1, -1, INT_MAX,
02024         check_wal_buffers, NULL, NULL
02025     },
02026 
02027     {
02028         {"wal_writer_delay", PGC_SIGHUP, WAL_SETTINGS,
02029             gettext_noop("WAL writer sleep time between WAL flushes."),
02030             NULL,
02031             GUC_UNIT_MS
02032         },
02033         &WalWriterDelay,
02034         200, 1, 10000,
02035         NULL, NULL, NULL
02036     },
02037 
02038     {
02039         /* see max_connections */
02040         {"max_wal_senders", PGC_POSTMASTER, REPLICATION_SENDING,
02041             gettext_noop("Sets the maximum number of simultaneously running WAL sender processes."),
02042             NULL
02043         },
02044         &max_wal_senders,
02045         0, 0, MAX_BACKENDS,
02046         NULL, NULL, NULL
02047     },
02048 
02049     {
02050         {"wal_sender_timeout", PGC_SIGHUP, REPLICATION_SENDING,
02051             gettext_noop("Sets the maximum time to wait for WAL replication."),
02052             NULL,
02053             GUC_UNIT_MS
02054         },
02055         &wal_sender_timeout,
02056         60 * 1000, 0, INT_MAX,
02057         NULL, NULL, NULL
02058     },
02059 
02060     {
02061         {"commit_delay", PGC_SUSET, WAL_SETTINGS,
02062             gettext_noop("Sets the delay in microseconds between transaction commit and "
02063                          "flushing WAL to disk."),
02064             NULL
02065             /* we have no microseconds designation, so can't supply units here */
02066         },
02067         &CommitDelay,
02068         0, 0, 100000,
02069         NULL, NULL, NULL
02070     },
02071 
02072     {
02073         {"commit_siblings", PGC_USERSET, WAL_SETTINGS,
02074             gettext_noop("Sets the minimum concurrent open transactions before performing "
02075                          "commit_delay."),
02076             NULL
02077         },
02078         &CommitSiblings,
02079         5, 0, 1000,
02080         NULL, NULL, NULL
02081     },
02082 
02083     {
02084         {"extra_float_digits", PGC_USERSET, CLIENT_CONN_LOCALE,
02085             gettext_noop("Sets the number of digits displayed for floating-point values."),
02086             gettext_noop("This affects real, double precision, and geometric data types. "
02087              "The parameter value is added to the standard number of digits "
02088                          "(FLT_DIG or DBL_DIG as appropriate).")
02089         },
02090         &extra_float_digits,
02091         0, -15, 3,
02092         NULL, NULL, NULL
02093     },
02094 
02095     {
02096         {"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN,
02097             gettext_noop("Sets the minimum execution time above which "
02098                          "statements will be logged."),
02099             gettext_noop("Zero prints all queries. -1 turns this feature off."),
02100             GUC_UNIT_MS
02101         },
02102         &log_min_duration_statement,
02103         -1, -1, INT_MAX,
02104         NULL, NULL, NULL
02105     },
02106 
02107     {
02108         {"log_autovacuum_min_duration", PGC_SIGHUP, LOGGING_WHAT,
02109             gettext_noop("Sets the minimum execution time above which "
02110                          "autovacuum actions will be logged."),
02111             gettext_noop("Zero prints all actions. -1 turns autovacuum logging off."),
02112             GUC_UNIT_MS
02113         },
02114         &Log_autovacuum_min_duration,
02115         -1, -1, INT_MAX,
02116         NULL, NULL, NULL
02117     },
02118 
02119     {
02120         {"bgwriter_delay", PGC_SIGHUP, RESOURCES_BGWRITER,
02121             gettext_noop("Background writer sleep time between rounds."),
02122             NULL,
02123             GUC_UNIT_MS
02124         },
02125         &BgWriterDelay,
02126         200, 10, 10000,
02127         NULL, NULL, NULL
02128     },
02129 
02130     {
02131         {"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES_BGWRITER,
02132             gettext_noop("Background writer maximum number of LRU pages to flush per round."),
02133             NULL
02134         },
02135         &bgwriter_lru_maxpages,
02136         100, 0, 1000,
02137         NULL, NULL, NULL
02138     },
02139 
02140     {
02141         {"effective_io_concurrency",
02142 #ifdef USE_PREFETCH
02143             PGC_USERSET,
02144 #else
02145             PGC_INTERNAL,
02146 #endif
02147             RESOURCES_ASYNCHRONOUS,
02148             gettext_noop("Number of simultaneous requests that can be handled efficiently by the disk subsystem."),
02149             gettext_noop("For RAID arrays, this should be approximately the number of drive spindles in the array.")
02150         },
02151         &effective_io_concurrency,
02152 #ifdef USE_PREFETCH
02153         1, 0, 1000,
02154 #else
02155         0, 0, 0,
02156 #endif
02157         check_effective_io_concurrency, assign_effective_io_concurrency, NULL
02158     },
02159 
02160     {
02161         {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
02162             gettext_noop("Automatic log file rotation will occur after N minutes."),
02163             NULL,
02164             GUC_UNIT_MIN
02165         },
02166         &Log_RotationAge,
02167         HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / SECS_PER_MINUTE,
02168         NULL, NULL, NULL
02169     },
02170 
02171     {
02172         {"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
02173             gettext_noop("Automatic log file rotation will occur after N kilobytes."),
02174             NULL,
02175             GUC_UNIT_KB
02176         },
02177         &Log_RotationSize,
02178         10 * 1024, 0, INT_MAX / 1024,
02179         NULL, NULL, NULL
02180     },
02181 
02182     {
02183         {"max_function_args", PGC_INTERNAL, PRESET_OPTIONS,
02184             gettext_noop("Shows the maximum number of function arguments."),
02185             NULL,
02186             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02187         },
02188         &max_function_args,
02189         FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS,
02190         NULL, NULL, NULL
02191     },
02192 
02193     {
02194         {"max_index_keys", PGC_INTERNAL, PRESET_OPTIONS,
02195             gettext_noop("Shows the maximum number of index keys."),
02196             NULL,
02197             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02198         },
02199         &max_index_keys,
02200         INDEX_MAX_KEYS, INDEX_MAX_KEYS, INDEX_MAX_KEYS,
02201         NULL, NULL, NULL
02202     },
02203 
02204     {
02205         {"max_identifier_length", PGC_INTERNAL, PRESET_OPTIONS,
02206             gettext_noop("Shows the maximum identifier length."),
02207             NULL,
02208             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02209         },
02210         &max_identifier_length,
02211         NAMEDATALEN - 1, NAMEDATALEN - 1, NAMEDATALEN - 1,
02212         NULL, NULL, NULL
02213     },
02214 
02215     {
02216         {"block_size", PGC_INTERNAL, PRESET_OPTIONS,
02217             gettext_noop("Shows the size of a disk block."),
02218             NULL,
02219             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02220         },
02221         &block_size,
02222         BLCKSZ, BLCKSZ, BLCKSZ,
02223         NULL, NULL, NULL
02224     },
02225 
02226     {
02227         {"segment_size", PGC_INTERNAL, PRESET_OPTIONS,
02228             gettext_noop("Shows the number of pages per disk file."),
02229             NULL,
02230             GUC_UNIT_BLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02231         },
02232         &segment_size,
02233         RELSEG_SIZE, RELSEG_SIZE, RELSEG_SIZE,
02234         NULL, NULL, NULL
02235     },
02236 
02237     {
02238         {"wal_block_size", PGC_INTERNAL, PRESET_OPTIONS,
02239             gettext_noop("Shows the block size in the write ahead log."),
02240             NULL,
02241             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02242         },
02243         &wal_block_size,
02244         XLOG_BLCKSZ, XLOG_BLCKSZ, XLOG_BLCKSZ,
02245         NULL, NULL, NULL
02246     },
02247 
02248     {
02249         {"wal_segment_size", PGC_INTERNAL, PRESET_OPTIONS,
02250             gettext_noop("Shows the number of pages per write ahead log segment."),
02251             NULL,
02252             GUC_UNIT_XBLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02253         },
02254         &wal_segment_size,
02255         (XLOG_SEG_SIZE / XLOG_BLCKSZ),
02256         (XLOG_SEG_SIZE / XLOG_BLCKSZ),
02257         (XLOG_SEG_SIZE / XLOG_BLCKSZ),
02258         NULL, NULL, NULL
02259     },
02260 
02261     {
02262         {"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
02263             gettext_noop("Time to sleep between autovacuum runs."),
02264             NULL,
02265             GUC_UNIT_S
02266         },
02267         &autovacuum_naptime,
02268         60, 1, INT_MAX / 1000,
02269         NULL, NULL, NULL
02270     },
02271     {
02272         {"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
02273             gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
02274             NULL
02275         },
02276         &autovacuum_vac_thresh,
02277         50, 0, INT_MAX,
02278         NULL, NULL, NULL
02279     },
02280     {
02281         {"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
02282             gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."),
02283             NULL
02284         },
02285         &autovacuum_anl_thresh,
02286         50, 0, INT_MAX,
02287         NULL, NULL, NULL
02288     },
02289     {
02290         /* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
02291         {"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
02292             gettext_noop("Age at which to autovacuum a table to prevent transaction ID wraparound."),
02293             NULL
02294         },
02295         &autovacuum_freeze_max_age,
02296         /* see pg_resetxlog if you change the upper-limit value */
02297         200000000, 100000000, 2000000000,
02298         NULL, NULL, NULL
02299     },
02300     {
02301         /* see max_connections */
02302         {"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
02303             gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
02304             NULL
02305         },
02306         &autovacuum_max_workers,
02307         3, 1, MAX_BACKENDS,
02308         check_autovacuum_max_workers, NULL, NULL
02309     },
02310 
02311     {
02312         {"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER,
02313             gettext_noop("Time between issuing TCP keepalives."),
02314             gettext_noop("A value of 0 uses the system default."),
02315             GUC_UNIT_S
02316         },
02317         &tcp_keepalives_idle,
02318         0, 0, INT_MAX,
02319         NULL, assign_tcp_keepalives_idle, show_tcp_keepalives_idle
02320     },
02321 
02322     {
02323         {"tcp_keepalives_interval", PGC_USERSET, CLIENT_CONN_OTHER,
02324             gettext_noop("Time between TCP keepalive retransmits."),
02325             gettext_noop("A value of 0 uses the system default."),
02326             GUC_UNIT_S
02327         },
02328         &tcp_keepalives_interval,
02329         0, 0, INT_MAX,
02330         NULL, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
02331     },
02332 
02333     {
02334         {"ssl_renegotiation_limit", PGC_USERSET, CONN_AUTH_SECURITY,
02335             gettext_noop("Set the amount of traffic to send and receive before renegotiating the encryption keys."),
02336             NULL,
02337             GUC_UNIT_KB,
02338         },
02339         &ssl_renegotiation_limit,
02340         512 * 1024, 0, MAX_KILOBYTES,
02341         NULL, NULL, NULL
02342     },
02343 
02344     {
02345         {"tcp_keepalives_count", PGC_USERSET, CLIENT_CONN_OTHER,
02346             gettext_noop("Maximum number of TCP keepalive retransmits."),
02347             gettext_noop("This controls the number of consecutive keepalive retransmits that can be "
02348                          "lost before a connection is considered dead. A value of 0 uses the "
02349                          "system default."),
02350         },
02351         &tcp_keepalives_count,
02352         0, 0, INT_MAX,
02353         NULL, assign_tcp_keepalives_count, show_tcp_keepalives_count
02354     },
02355 
02356     {
02357         {"gin_fuzzy_search_limit", PGC_USERSET, CLIENT_CONN_OTHER,
02358             gettext_noop("Sets the maximum allowed result for exact search by GIN."),
02359             NULL,
02360             0
02361         },
02362         &GinFuzzySearchLimit,
02363         0, 0, INT_MAX,
02364         NULL, NULL, NULL
02365     },
02366 
02367     {
02368         {"effective_cache_size", PGC_USERSET, QUERY_TUNING_COST,
02369             gettext_noop("Sets the planner's assumption about the size of the disk cache."),
02370             gettext_noop("That is, the portion of the kernel's disk cache that "
02371                          "will be used for PostgreSQL data files. This is measured in disk "
02372                          "pages, which are normally 8 kB each."),
02373             GUC_UNIT_BLOCKS,
02374         },
02375         &effective_cache_size,
02376         DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX,
02377         NULL, NULL, NULL
02378     },
02379 
02380     {
02381         /* Can't be set in postgresql.conf */
02382         {"server_version_num", PGC_INTERNAL, PRESET_OPTIONS,
02383             gettext_noop("Shows the server version as an integer."),
02384             NULL,
02385             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02386         },
02387         &server_version_num,
02388         PG_VERSION_NUM, PG_VERSION_NUM, PG_VERSION_NUM,
02389         NULL, NULL, NULL
02390     },
02391 
02392     {
02393         {"log_temp_files", PGC_SUSET, LOGGING_WHAT,
02394             gettext_noop("Log the use of temporary files larger than this number of kilobytes."),
02395             gettext_noop("Zero logs all files. The default is -1 (turning this feature off)."),
02396             GUC_UNIT_KB
02397         },
02398         &log_temp_files,
02399         -1, -1, INT_MAX,
02400         NULL, NULL, NULL
02401     },
02402 
02403     {
02404         {"track_activity_query_size", PGC_POSTMASTER, RESOURCES_MEM,
02405             gettext_noop("Sets the size reserved for pg_stat_activity.query, in bytes."),
02406             NULL,
02407         },
02408         &pgstat_track_activity_query_size,
02409         1024, 100, 102400,
02410         NULL, NULL, NULL
02411     },
02412 
02413     /* End-of-list marker */
02414     {
02415         {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
02416     }
02417 };
02418 
02419 
02420 static struct config_real ConfigureNamesReal[] =
02421 {
02422     {
02423         {"seq_page_cost", PGC_USERSET, QUERY_TUNING_COST,
02424             gettext_noop("Sets the planner's estimate of the cost of a "
02425                          "sequentially fetched disk page."),
02426             NULL
02427         },
02428         &seq_page_cost,
02429         DEFAULT_SEQ_PAGE_COST, 0, DBL_MAX,
02430         NULL, NULL, NULL
02431     },
02432     {
02433         {"random_page_cost", PGC_USERSET, QUERY_TUNING_COST,
02434             gettext_noop("Sets the planner's estimate of the cost of a "
02435                          "nonsequentially fetched disk page."),
02436             NULL
02437         },
02438         &random_page_cost,
02439         DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX,
02440         NULL, NULL, NULL
02441     },
02442     {
02443         {"cpu_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
02444             gettext_noop("Sets the planner's estimate of the cost of "
02445                          "processing each tuple (row)."),
02446             NULL
02447         },
02448         &cpu_tuple_cost,
02449         DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX,
02450         NULL, NULL, NULL
02451     },
02452     {
02453         {"cpu_index_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
02454             gettext_noop("Sets the planner's estimate of the cost of "
02455                          "processing each index entry during an index scan."),
02456             NULL
02457         },
02458         &cpu_index_tuple_cost,
02459         DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX,
02460         NULL, NULL, NULL
02461     },
02462     {
02463         {"cpu_operator_cost", PGC_USERSET, QUERY_TUNING_COST,
02464             gettext_noop("Sets the planner's estimate of the cost of "
02465                          "processing each operator or function call."),
02466             NULL
02467         },
02468         &cpu_operator_cost,
02469         DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX,
02470         NULL, NULL, NULL
02471     },
02472 
02473     {
02474         {"cursor_tuple_fraction", PGC_USERSET, QUERY_TUNING_OTHER,
02475             gettext_noop("Sets the planner's estimate of the fraction of "
02476                          "a cursor's rows that will be retrieved."),
02477             NULL
02478         },
02479         &cursor_tuple_fraction,
02480         DEFAULT_CURSOR_TUPLE_FRACTION, 0.0, 1.0,
02481         NULL, NULL, NULL
02482     },
02483 
02484     {
02485         {"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO,
02486             gettext_noop("GEQO: selective pressure within the population."),
02487             NULL
02488         },
02489         &Geqo_selection_bias,
02490         DEFAULT_GEQO_SELECTION_BIAS,
02491         MIN_GEQO_SELECTION_BIAS, MAX_GEQO_SELECTION_BIAS,
02492         NULL, NULL, NULL
02493     },
02494     {
02495         {"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
02496             gettext_noop("GEQO: seed for random path selection."),
02497             NULL
02498         },
02499         &Geqo_seed,
02500         0.0, 0.0, 1.0,
02501         NULL, NULL, NULL
02502     },
02503 
02504     {
02505         {"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES_BGWRITER,
02506             gettext_noop("Multiple of the average buffer usage to free per round."),
02507             NULL
02508         },
02509         &bgwriter_lru_multiplier,
02510         2.0, 0.0, 10.0,
02511         NULL, NULL, NULL
02512     },
02513 
02514     {
02515         {"seed", PGC_USERSET, UNGROUPED,
02516             gettext_noop("Sets the seed for random-number generation."),
02517             NULL,
02518             GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02519         },
02520         &phony_random_seed,
02521         0.0, -1.0, 1.0,
02522         check_random_seed, assign_random_seed, show_random_seed
02523     },
02524 
02525     {
02526         {"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
02527             gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
02528             NULL
02529         },
02530         &autovacuum_vac_scale,
02531         0.2, 0.0, 100.0,
02532         NULL, NULL, NULL
02533     },
02534     {
02535         {"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
02536             gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."),
02537             NULL
02538         },
02539         &autovacuum_anl_scale,
02540         0.1, 0.0, 100.0,
02541         NULL, NULL, NULL
02542     },
02543 
02544     {
02545         {"checkpoint_completion_target", PGC_SIGHUP, WAL_CHECKPOINTS,
02546             gettext_noop("Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."),
02547             NULL
02548         },
02549         &CheckPointCompletionTarget,
02550         0.5, 0.0, 1.0,
02551         NULL, NULL, NULL
02552     },
02553 
02554     /* End-of-list marker */
02555     {
02556         {NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL, NULL
02557     }
02558 };
02559 
02560 
02561 static struct config_string ConfigureNamesString[] =
02562 {
02563     {
02564         {"archive_command", PGC_SIGHUP, WAL_ARCHIVING,
02565             gettext_noop("Sets the shell command that will be called to archive a WAL file."),
02566             NULL
02567         },
02568         &XLogArchiveCommand,
02569         "",
02570         NULL, NULL, show_archive_command
02571     },
02572 
02573     {
02574         {"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
02575             gettext_noop("Sets the client's character set encoding."),
02576             NULL,
02577             GUC_IS_NAME | GUC_REPORT
02578         },
02579         &client_encoding_string,
02580         "SQL_ASCII",
02581         check_client_encoding, assign_client_encoding, NULL
02582     },
02583 
02584     {
02585         {"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
02586             gettext_noop("Controls information prefixed to each log line."),
02587             gettext_noop("If blank, no prefix is used.")
02588         },
02589         &Log_line_prefix,
02590         "",
02591         NULL, NULL, NULL
02592     },
02593 
02594     {
02595         {"log_timezone", PGC_SIGHUP, LOGGING_WHAT,
02596             gettext_noop("Sets the time zone to use in log messages."),
02597             NULL
02598         },
02599         &log_timezone_string,
02600         "GMT",
02601         check_log_timezone, assign_log_timezone, show_log_timezone
02602     },
02603 
02604     {
02605         {"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
02606             gettext_noop("Sets the display format for date and time values."),
02607             gettext_noop("Also controls interpretation of ambiguous "
02608                          "date inputs."),
02609             GUC_LIST_INPUT | GUC_REPORT
02610         },
02611         &datestyle_string,
02612         "ISO, MDY",
02613         check_datestyle, assign_datestyle, NULL
02614     },
02615 
02616     {
02617         {"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT,
02618             gettext_noop("Sets the default tablespace to create tables and indexes in."),
02619             gettext_noop("An empty string selects the database's default tablespace."),
02620             GUC_IS_NAME
02621         },
02622         &default_tablespace,
02623         "",
02624         check_default_tablespace, NULL, NULL
02625     },
02626 
02627     {
02628         {"temp_tablespaces", PGC_USERSET, CLIENT_CONN_STATEMENT,
02629             gettext_noop("Sets the tablespace(s) to use for temporary tables and sort files."),
02630             NULL,
02631             GUC_LIST_INPUT | GUC_LIST_QUOTE
02632         },
02633         &temp_tablespaces,
02634         "",
02635         check_temp_tablespaces, assign_temp_tablespaces, NULL
02636     },
02637 
02638     {
02639         {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
02640             gettext_noop("Sets the path for dynamically loadable modules."),
02641             gettext_noop("If a dynamically loadable module needs to be opened and "
02642                          "the specified name does not have a directory component (i.e., the "
02643                          "name does not contain a slash), the system will search this path for "
02644                          "the specified file."),
02645             GUC_SUPERUSER_ONLY
02646         },
02647         &Dynamic_library_path,
02648         "$libdir",
02649         NULL, NULL, NULL
02650     },
02651 
02652     {
02653         {"krb_server_keyfile", PGC_SIGHUP, CONN_AUTH_SECURITY,
02654             gettext_noop("Sets the location of the Kerberos server key file."),
02655             NULL,
02656             GUC_SUPERUSER_ONLY
02657         },
02658         &pg_krb_server_keyfile,
02659         PG_KRB_SRVTAB,
02660         NULL, NULL, NULL
02661     },
02662 
02663     {
02664         {"krb_srvname", PGC_SIGHUP, CONN_AUTH_SECURITY,
02665             gettext_noop("Sets the name of the Kerberos service."),
02666             NULL
02667         },
02668         &pg_krb_srvnam,
02669         PG_KRB_SRVNAM,
02670         NULL, NULL, NULL
02671     },
02672 
02673     {
02674         {"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
02675             gettext_noop("Sets the Bonjour service name."),
02676             NULL
02677         },
02678         &bonjour_name,
02679         "",
02680         NULL, NULL, NULL
02681     },
02682 
02683     /* See main.c about why defaults for LC_foo are not all alike */
02684 
02685     {
02686         {"lc_collate", PGC_INTERNAL, CLIENT_CONN_LOCALE,
02687             gettext_noop("Shows the collation order locale."),
02688             NULL,
02689             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02690         },
02691         &locale_collate,
02692         "C",
02693         NULL, NULL, NULL
02694     },
02695 
02696     {
02697         {"lc_ctype", PGC_INTERNAL, CLIENT_CONN_LOCALE,
02698             gettext_noop("Shows the character classification and case conversion locale."),
02699             NULL,
02700             GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02701         },
02702         &locale_ctype,
02703         "C",
02704         NULL, NULL, NULL
02705     },
02706 
02707     {
02708         {"lc_messages", PGC_SUSET, CLIENT_CONN_LOCALE,
02709             gettext_noop("Sets the language in which messages are displayed."),
02710             NULL
02711         },
02712         &locale_messages,
02713         "",
02714         check_locale_messages, assign_locale_messages, NULL
02715     },
02716 
02717     {
02718         {"lc_monetary", PGC_USERSET, CLIENT_CONN_LOCALE,
02719             gettext_noop("Sets the locale for formatting monetary amounts."),
02720             NULL
02721         },
02722         &locale_monetary,
02723         "C",
02724         check_locale_monetary, assign_locale_monetary, NULL
02725     },
02726 
02727     {
02728         {"lc_numeric", PGC_USERSET, CLIENT_CONN_LOCALE,
02729             gettext_noop("Sets the locale for formatting numbers."),
02730             NULL
02731         },
02732         &locale_numeric,
02733         "C",
02734         check_locale_numeric, assign_locale_numeric, NULL
02735     },
02736 
02737     {
02738         {"lc_time", PGC_USERSET, CLIENT_CONN_LOCALE,
02739             gettext_noop("Sets the locale for formatting date and time values."),
02740             NULL
02741         },
02742         &locale_time,
02743         "C",
02744         check_locale_time, assign_locale_time, NULL
02745     },
02746 
02747     {
02748         {"shared_preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
02749             gettext_noop("Lists shared libraries to preload into server."),
02750             NULL,
02751             GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
02752         },
02753         &shared_preload_libraries_string,
02754         "",
02755         NULL, NULL, NULL
02756     },
02757 
02758     {
02759         {"local_preload_libraries", PGC_BACKEND, CLIENT_CONN_OTHER,
02760             gettext_noop("Lists shared libraries to preload into each backend."),
02761             NULL,
02762             GUC_LIST_INPUT | GUC_LIST_QUOTE
02763         },
02764         &local_preload_libraries_string,
02765         "",
02766         NULL, NULL, NULL
02767     },
02768 
02769     {
02770         {"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT,
02771             gettext_noop("Sets the schema search order for names that are not schema-qualified."),
02772             NULL,
02773             GUC_LIST_INPUT | GUC_LIST_QUOTE
02774         },
02775         &namespace_search_path,
02776         "\"$user\",public",
02777         check_search_path, assign_search_path, NULL
02778     },
02779 
02780     {
02781         /* Can't be set in postgresql.conf */
02782         {"server_encoding", PGC_INTERNAL, CLIENT_CONN_LOCALE,
02783             gettext_noop("Sets the server (database) character set encoding."),
02784             NULL,
02785             GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02786         },
02787         &server_encoding_string,
02788         "SQL_ASCII",
02789         NULL, NULL, NULL
02790     },
02791 
02792     {
02793         /* Can't be set in postgresql.conf */
02794         {"server_version", PGC_INTERNAL, PRESET_OPTIONS,
02795             gettext_noop("Shows the server version."),
02796             NULL,
02797             GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02798         },
02799         &server_version_string,
02800         PG_VERSION,
02801         NULL, NULL, NULL
02802     },
02803 
02804     {
02805         /* Not for general use --- used by SET ROLE */
02806         {"role", PGC_USERSET, UNGROUPED,
02807             gettext_noop("Sets the current role."),
02808             NULL,
02809             GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
02810         },
02811         &role_string,
02812         "none",
02813         check_role, assign_role, show_role
02814     },
02815 
02816     {
02817         /* Not for general use --- used by SET SESSION AUTHORIZATION */
02818         {"session_authorization", PGC_USERSET, UNGROUPED,
02819             gettext_noop("Sets the session user name."),
02820             NULL,
02821             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
02822         },
02823         &session_authorization_string,
02824         NULL,
02825         check_session_authorization, assign_session_authorization, NULL
02826     },
02827 
02828     {
02829         {"log_destination", PGC_SIGHUP, LOGGING_WHERE,
02830             gettext_noop("Sets the destination for server log output."),
02831             gettext_noop("Valid values are combinations of \"stderr\", "
02832                          "\"syslog\", \"csvlog\", and \"eventlog\", "
02833                          "depending on the platform."),
02834             GUC_LIST_INPUT
02835         },
02836         &log_destination_string,
02837         "stderr",
02838         check_log_destination, assign_log_destination, NULL
02839     },
02840     {
02841         {"log_directory", PGC_SIGHUP, LOGGING_WHERE,
02842             gettext_noop("Sets the destination directory for log files."),
02843             gettext_noop("Can be specified as relative to the data directory "
02844                          "or as absolute path."),
02845             GUC_SUPERUSER_ONLY
02846         },
02847         &Log_directory,
02848         "pg_log",
02849         check_canonical_path, NULL, NULL
02850     },
02851     {
02852         {"log_filename", PGC_SIGHUP, LOGGING_WHERE,
02853             gettext_noop("Sets the file name pattern for log files."),
02854             NULL,
02855             GUC_SUPERUSER_ONLY
02856         },
02857         &Log_filename,
02858         "postgresql-%Y-%m-%d_%H%M%S.log",
02859         NULL, NULL, NULL
02860     },
02861 
02862     {
02863         {"syslog_ident", PGC_SIGHUP, LOGGING_WHERE,
02864             gettext_noop("Sets the program name used to identify PostgreSQL "
02865                          "messages in syslog."),
02866             NULL
02867         },
02868         &syslog_ident_str,
02869         "postgres",
02870         NULL, assign_syslog_ident, NULL
02871     },
02872 
02873     {
02874         {"event_source", PGC_POSTMASTER, LOGGING_WHERE,
02875             gettext_noop("Sets the application name used to identify "
02876                          "PostgreSQL messages in the event log."),
02877             NULL
02878         },
02879         &event_source,
02880         "PostgreSQL",
02881         NULL, NULL, NULL
02882     },
02883 
02884     {
02885         {"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
02886             gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
02887             NULL,
02888             GUC_REPORT
02889         },
02890         &timezone_string,
02891         "GMT",
02892         check_timezone, assign_timezone, show_timezone
02893     },
02894     {
02895         {"timezone_abbreviations", PGC_USERSET, CLIENT_CONN_LOCALE,
02896             gettext_noop("Selects a file of time zone abbreviations."),
02897             NULL
02898         },
02899         &timezone_abbreviations_string,
02900         NULL,
02901         check_timezone_abbreviations, assign_timezone_abbreviations, NULL
02902     },
02903 
02904     {
02905         {"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
02906             gettext_noop("Sets the current transaction's isolation level."),
02907             NULL,
02908             GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
02909         },
02910         &XactIsoLevel_string,
02911         "default",
02912         check_XactIsoLevel, assign_XactIsoLevel, show_XactIsoLevel
02913     },
02914 
02915     {
02916         {"unix_socket_group", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
02917             gettext_noop("Sets the owning group of the Unix-domain socket."),
02918             gettext_noop("The owning user of the socket is always the user "
02919                          "that starts the server.")
02920         },
02921         &Unix_socket_group,
02922         "",
02923         NULL, NULL, NULL
02924     },
02925 
02926     {
02927         {"unix_socket_directories", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
02928             gettext_noop("Sets the directories where Unix-domain sockets will be created."),
02929             NULL,
02930             GUC_SUPERUSER_ONLY
02931         },
02932         &Unix_socket_directories,
02933 #ifdef HAVE_UNIX_SOCKETS
02934         DEFAULT_PGSOCKET_DIR,
02935 #else
02936         "",
02937 #endif
02938         NULL, NULL, NULL
02939     },
02940 
02941     {
02942         {"listen_addresses", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
02943             gettext_noop("Sets the host name or IP address(es) to listen to."),
02944             NULL,
02945             GUC_LIST_INPUT
02946         },
02947         &ListenAddresses,
02948         "localhost",
02949         NULL, NULL, NULL
02950     },
02951 
02952     {
02953         {"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
02954             gettext_noop("Sets the server's data directory."),
02955             NULL,
02956             GUC_SUPERUSER_ONLY
02957         },
02958         &data_directory,
02959         NULL,
02960         NULL, NULL, NULL
02961     },
02962 
02963     {
02964         {"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
02965             gettext_noop("Sets the server's main configuration file."),
02966             NULL,
02967             GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
02968         },
02969         &ConfigFileName,
02970         NULL,
02971         NULL, NULL, NULL
02972     },
02973 
02974     {
02975         {"hba_file", PGC_POSTMASTER, FILE_LOCATIONS,
02976             gettext_noop("Sets the server's \"hba\" configuration file."),
02977             NULL,
02978             GUC_SUPERUSER_ONLY
02979         },
02980         &HbaFileName,
02981         NULL,
02982         NULL, NULL, NULL
02983     },
02984 
02985     {
02986         {"ident_file", PGC_POSTMASTER, FILE_LOCATIONS,
02987             gettext_noop("Sets the server's \"ident\" configuration file."),
02988             NULL,
02989             GUC_SUPERUSER_ONLY
02990         },
02991         &IdentFileName,
02992         NULL,
02993         NULL, NULL, NULL
02994     },
02995 
02996     {
02997         {"external_pid_file", PGC_POSTMASTER, FILE_LOCATIONS,
02998             gettext_noop("Writes the postmaster PID to the specified file."),
02999             NULL,
03000             GUC_SUPERUSER_ONLY
03001         },
03002         &external_pid_file,
03003         NULL,
03004         check_canonical_path, NULL, NULL
03005     },
03006 
03007     {
03008         {"ssl_cert_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
03009             gettext_noop("Location of the SSL server certificate file."),
03010             NULL
03011         },
03012         &ssl_cert_file,
03013         "server.crt",
03014         NULL, NULL, NULL
03015     },
03016 
03017     {
03018         {"ssl_key_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
03019             gettext_noop("Location of the SSL server private key file."),
03020             NULL
03021         },
03022         &ssl_key_file,
03023         "server.key",
03024         NULL, NULL, NULL
03025     },
03026 
03027     {
03028         {"ssl_ca_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
03029             gettext_noop("Location of the SSL certificate authority file."),
03030             NULL
03031         },
03032         &ssl_ca_file,
03033         "",
03034         NULL, NULL, NULL
03035     },
03036 
03037     {
03038         {"ssl_crl_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
03039             gettext_noop("Location of the SSL certificate revocation list file."),
03040             NULL
03041         },
03042         &ssl_crl_file,
03043         "",
03044         NULL, NULL, NULL
03045     },
03046 
03047     {
03048         {"stats_temp_directory", PGC_SIGHUP, STATS_COLLECTOR,
03049             gettext_noop("Writes temporary statistics files to the specified directory."),
03050             NULL,
03051             GUC_SUPERUSER_ONLY
03052         },
03053         &pgstat_temp_directory,
03054         "pg_stat_tmp",
03055         check_canonical_path, assign_pgstat_temp_directory, NULL
03056     },
03057 
03058     {
03059         {"synchronous_standby_names", PGC_SIGHUP, REPLICATION_MASTER,
03060             gettext_noop("List of names of potential synchronous standbys."),
03061             NULL,
03062             GUC_LIST_INPUT
03063         },
03064         &SyncRepStandbyNames,
03065         "",
03066         check_synchronous_standby_names, NULL, NULL
03067     },
03068 
03069     {
03070         {"default_text_search_config", PGC_USERSET, CLIENT_CONN_LOCALE,
03071             gettext_noop("Sets default text search configuration."),
03072             NULL
03073         },
03074         &TSCurrentConfig,
03075         "pg_catalog.simple",
03076         check_TSCurrentConfig, assign_TSCurrentConfig, NULL
03077     },
03078 
03079     {
03080         {"ssl_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY,
03081             gettext_noop("Sets the list of allowed SSL ciphers."),
03082             NULL,
03083             GUC_SUPERUSER_ONLY
03084         },
03085         &SSLCipherSuites,
03086 #ifdef USE_SSL
03087         "DEFAULT:!LOW:!EXP:!MD5:@STRENGTH",
03088 #else
03089         "none",
03090 #endif
03091         NULL, NULL, NULL
03092     },
03093 
03094     {
03095         {"application_name", PGC_USERSET, LOGGING_WHAT,
03096             gettext_noop("Sets the application name to be reported in statistics and logs."),
03097             NULL,
03098             GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE
03099         },
03100         &application_name,
03101         "",
03102         check_application_name, assign_application_name, NULL
03103     },
03104 
03105     /* End-of-list marker */
03106     {
03107         {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
03108     }
03109 };
03110 
03111 
03112 static struct config_enum ConfigureNamesEnum[] =
03113 {
03114     {
03115         {"backslash_quote", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
03116             gettext_noop("Sets whether \"\\'\" is allowed in string literals."),
03117             NULL
03118         },
03119         &backslash_quote,
03120         BACKSLASH_QUOTE_SAFE_ENCODING, backslash_quote_options,
03121         NULL, NULL, NULL
03122     },
03123 
03124     {
03125         {"bytea_output", PGC_USERSET, CLIENT_CONN_STATEMENT,
03126             gettext_noop("Sets the output format for bytea."),
03127             NULL
03128         },
03129         &bytea_output,
03130         BYTEA_OUTPUT_HEX, bytea_output_options,
03131         NULL, NULL, NULL
03132     },
03133 
03134     {
03135         {"client_min_messages", PGC_USERSET, LOGGING_WHEN,
03136             gettext_noop("Sets the message levels that are sent to the client."),
03137             gettext_noop("Each level includes all the levels that follow it. The later"
03138                          " the level, the fewer messages are sent.")
03139         },
03140         &client_min_messages,
03141         NOTICE, client_message_level_options,
03142         NULL, NULL, NULL
03143     },
03144 
03145     {
03146         {"constraint_exclusion", PGC_USERSET, QUERY_TUNING_OTHER,
03147             gettext_noop("Enables the planner to use constraints to optimize queries."),
03148             gettext_noop("Table scans will be skipped if their constraints"
03149                          " guarantee that no rows match the query.")
03150         },
03151         &constraint_exclusion,
03152         CONSTRAINT_EXCLUSION_PARTITION, constraint_exclusion_options,
03153         NULL, NULL, NULL
03154     },
03155 
03156     {
03157         {"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
03158             gettext_noop("Sets the transaction isolation level of each new transaction."),
03159             NULL
03160         },
03161         &DefaultXactIsoLevel,
03162         XACT_READ_COMMITTED, isolation_level_options,
03163         NULL, NULL, NULL
03164     },
03165 
03166     {
03167         {"IntervalStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
03168             gettext_noop("Sets the display format for interval values."),
03169             NULL,
03170             GUC_REPORT
03171         },
03172         &IntervalStyle,
03173         INTSTYLE_POSTGRES, intervalstyle_options,
03174         NULL, NULL, NULL
03175     },
03176 
03177     {
03178         {"log_error_verbosity", PGC_SUSET, LOGGING_WHAT,
03179             gettext_noop("Sets the verbosity of logged messages."),
03180             NULL
03181         },
03182         &Log_error_verbosity,
03183         PGERROR_DEFAULT, log_error_verbosity_options,
03184         NULL, NULL, NULL
03185     },
03186 
03187     {
03188         {"log_min_messages", PGC_SUSET, LOGGING_WHEN,
03189             gettext_noop("Sets the message levels that are logged."),
03190             gettext_noop("Each level includes all the levels that follow it. The later"
03191                          " the level, the fewer messages are sent.")
03192         },
03193         &log_min_messages,
03194         WARNING, server_message_level_options,
03195         NULL, NULL, NULL
03196     },
03197 
03198     {
03199         {"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
03200             gettext_noop("Causes all statements generating error at or above this level to be logged."),
03201             gettext_noop("Each level includes all the levels that follow it. The later"
03202                          " the level, the fewer messages are sent.")
03203         },
03204         &log_min_error_statement,
03205         ERROR, server_message_level_options,
03206         NULL, NULL, NULL
03207     },
03208 
03209     {
03210         {"log_statement", PGC_SUSET, LOGGING_WHAT,
03211             gettext_noop("Sets the type of statements logged."),
03212             NULL
03213         },
03214         &log_statement,
03215         LOGSTMT_NONE, log_statement_options,
03216         NULL, NULL, NULL
03217     },
03218 
03219     {
03220         {"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
03221             gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
03222             NULL
03223         },
03224         &syslog_facility,
03225 #ifdef HAVE_SYSLOG
03226         LOG_LOCAL0,
03227 #else
03228         0,
03229 #endif
03230         syslog_facility_options,
03231         NULL, assign_syslog_facility, NULL
03232     },
03233 
03234     {
03235         {"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
03236             gettext_noop("Sets the session's behavior for triggers and rewrite rules."),
03237             NULL
03238         },
03239         &SessionReplicationRole,
03240         SESSION_REPLICATION_ROLE_ORIGIN, session_replication_role_options,
03241         NULL, assign_session_replication_role, NULL
03242     },
03243 
03244     {
03245         {"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
03246             gettext_noop("Sets the current transaction's synchronization level."),
03247             NULL
03248         },
03249         &synchronous_commit,
03250         SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
03251         NULL, assign_synchronous_commit, NULL
03252     },
03253 
03254     {
03255         {"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS,
03256             gettext_noop("Enables logging of recovery-related debugging information."),
03257             gettext_noop("Each level includes all the levels that follow it. The later"
03258                          " the level, the fewer messages are sent.")
03259         },
03260         &trace_recovery_messages,
03261 
03262         /*
03263          * client_message_level_options allows too many values, really, but
03264          * it's not worth having a separate options array for this.
03265          */
03266         LOG, client_message_level_options,
03267         NULL, NULL, NULL
03268     },
03269 
03270     {
03271         {"track_functions", PGC_SUSET, STATS_COLLECTOR,
03272             gettext_noop("Collects function-level statistics on database activity."),
03273             NULL
03274         },
03275         &pgstat_track_functions,
03276         TRACK_FUNC_OFF, track_function_options,
03277         NULL, NULL, NULL
03278     },
03279 
03280     {
03281         {"wal_level", PGC_POSTMASTER, WAL_SETTINGS,
03282             gettext_noop("Set the level of information written to the WAL."),
03283             NULL
03284         },
03285         &wal_level,
03286         WAL_LEVEL_MINIMAL, wal_level_options,
03287         NULL, NULL, NULL
03288     },
03289 
03290     {
03291         {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
03292             gettext_noop("Selects the method used for forcing WAL updates to disk."),
03293             NULL
03294         },
03295         &sync_method,
03296         DEFAULT_SYNC_METHOD, sync_method_options,
03297         NULL, assign_xlog_sync_method, NULL
03298     },
03299 
03300     {
03301         {"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
03302             gettext_noop("Sets how binary values are to be encoded in XML."),
03303             NULL
03304         },
03305         &xmlbinary,
03306         XMLBINARY_BASE64, xmlbinary_options,
03307         NULL, NULL, NULL
03308     },
03309 
03310     {
03311         {"xmloption", PGC_USERSET, CLIENT_CONN_STATEMENT,
03312             gettext_noop("Sets whether XML data in implicit parsing and serialization "
03313                          "operations is to be considered as documents or content fragments."),
03314             NULL
03315         },
03316         &xmloption,
03317         XMLOPTION_CONTENT, xmloption_options,
03318         NULL, NULL, NULL
03319     },
03320 
03321 
03322     /* End-of-list marker */
03323     {
03324         {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
03325     }
03326 };
03327 
03328 /******** end of options list ********/
03329 
03330 
03331 /*
03332  * To allow continued support of obsolete names for GUC variables, we apply
03333  * the following mappings to any unrecognized name.  Note that an old name
03334  * should be mapped to a new one only if the new variable has very similar
03335  * semantics to the old.
03336  */
03337 static const char *const map_old_guc_names[] = {
03338     "sort_mem", "work_mem",
03339     "vacuum_mem", "maintenance_work_mem",
03340     NULL
03341 };
03342 
03343 
03344 /*
03345  * Actual lookup of variables is done through this single, sorted array.
03346  */
03347 static struct config_generic **guc_variables;
03348 
03349 /* Current number of variables contained in the vector */
03350 static int  num_guc_variables;
03351 
03352 /* Vector capacity */
03353 static int  size_guc_variables;
03354 
03355 
03356 static bool guc_dirty;          /* TRUE if need to do commit/abort work */
03357 
03358 static bool reporting_enabled;  /* TRUE to enable GUC_REPORT */
03359 
03360 static int  GUCNestLevel = 0;   /* 1 when in main transaction */
03361 
03362 
03363 static int  guc_var_compare(const void *a, const void *b);
03364 static int  guc_name_compare(const char *namea, const char *nameb);
03365 static void InitializeGUCOptionsFromEnvironment(void);
03366 static void InitializeOneGUCOption(struct config_generic * gconf);
03367 static void push_old_value(struct config_generic * gconf, GucAction action);
03368 static void ReportGUCOption(struct config_generic * record);
03369 static void reapply_stacked_values(struct config_generic * variable,
03370                        struct config_string * pHolder,
03371                        GucStack *stack,
03372                        const char *curvalue,
03373                        GucContext curscontext, GucSource cursource);
03374 static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
03375 static void ShowAllGUCConfig(DestReceiver *dest);
03376 static char *_ShowOption(struct config_generic * record, bool use_units);
03377 static bool validate_option_array_item(const char *name, const char *value,
03378                            bool skipIfNoPermissions);
03379 
03380 
03381 /*
03382  * Some infrastructure for checking malloc/strdup/realloc calls
03383  */
03384 static void *
03385 guc_malloc(int elevel, size_t size)
03386 {
03387     void       *data;
03388 
03389     /* Avoid unportable behavior of malloc(0) */
03390     if (size == 0)
03391         size = 1;
03392     data = malloc(size);
03393     if (data == NULL)
03394         ereport(elevel,
03395                 (errcode(ERRCODE_OUT_OF_MEMORY),
03396                  errmsg("out of memory")));
03397     return data;
03398 }
03399 
03400 static void *
03401 guc_realloc(int elevel, void *old, size_t size)
03402 {
03403     void       *data;
03404 
03405     /* Avoid unportable behavior of realloc(NULL, 0) */
03406     if (old == NULL && size == 0)
03407         size = 1;
03408     data = realloc(old, size);
03409     if (data == NULL)
03410         ereport(elevel,
03411                 (errcode(ERRCODE_OUT_OF_MEMORY),
03412                  errmsg("out of memory")));
03413     return data;
03414 }
03415 
03416 static char *
03417 guc_strdup(int elevel, const char *src)
03418 {
03419     char       *data;
03420 
03421     data = strdup(src);
03422     if (data == NULL)
03423         ereport(elevel,
03424                 (errcode(ERRCODE_OUT_OF_MEMORY),
03425                  errmsg("out of memory")));
03426     return data;
03427 }
03428 
03429 
03430 /*
03431  * Detect whether strval is referenced anywhere in a GUC string item
03432  */
03433 static bool
03434 string_field_used(struct config_string * conf, char *strval)
03435 {
03436     GucStack   *stack;
03437 
03438     if (strval == *(conf->variable) ||
03439         strval == conf->reset_val ||
03440         strval == conf->boot_val)
03441         return true;
03442     for (stack = conf->gen.stack; stack; stack = stack->prev)
03443     {
03444         if (strval == stack->prior.val.stringval ||
03445             strval == stack->masked.val.stringval)
03446             return true;
03447     }
03448     return false;
03449 }
03450 
03451 /*
03452  * Support for assigning to a field of a string GUC item.  Free the prior
03453  * value if it's not referenced anywhere else in the item (including stacked
03454  * states).
03455  */
03456 static void
03457 set_string_field(struct config_string * conf, char **field, char *newval)
03458 {
03459     char       *oldval = *field;
03460 
03461     /* Do the assignment */
03462     *field = newval;
03463 
03464     /* Free old value if it's not NULL and isn't referenced anymore */
03465     if (oldval && !string_field_used(conf, oldval))
03466         free(oldval);
03467 }
03468 
03469 /*
03470  * Detect whether an "extra" struct is referenced anywhere in a GUC item
03471  */
03472 static bool
03473 extra_field_used(struct config_generic * gconf, void *extra)
03474 {
03475     GucStack   *stack;
03476 
03477     if (extra == gconf->extra)
03478         return true;
03479     switch (gconf->vartype)
03480     {
03481         case PGC_BOOL:
03482             if (extra == ((struct config_bool *) gconf)->reset_extra)
03483                 return true;
03484             break;
03485         case PGC_INT:
03486             if (extra == ((struct config_int *) gconf)->reset_extra)
03487                 return true;
03488             break;
03489         case PGC_REAL:
03490             if (extra == ((struct config_real *) gconf)->reset_extra)
03491                 return true;
03492             break;
03493         case PGC_STRING:
03494             if (extra == ((struct config_string *) gconf)->reset_extra)
03495                 return true;
03496             break;
03497         case PGC_ENUM:
03498             if (extra == ((struct config_enum *) gconf)->reset_extra)
03499                 return true;
03500             break;
03501     }
03502     for (stack = gconf->stack; stack; stack = stack->prev)
03503     {
03504         if (extra == stack->prior.extra ||
03505             extra == stack->masked.extra)
03506             return true;
03507     }
03508 
03509     return false;
03510 }
03511 
03512 /*
03513  * Support for assigning to an "extra" field of a GUC item.  Free the prior
03514  * value if it's not referenced anywhere else in the item (including stacked
03515  * states).
03516  */
03517 static void
03518 set_extra_field(struct config_generic * gconf, void **field, void *newval)
03519 {
03520     void       *oldval = *field;
03521 
03522     /* Do the assignment */
03523     *field = newval;
03524 
03525     /* Free old value if it's not NULL and isn't referenced anymore */
03526     if (oldval && !extra_field_used(gconf, oldval))
03527         free(oldval);
03528 }
03529 
03530 /*
03531  * Support for copying a variable's active value into a stack entry.
03532  * The "extra" field associated with the active value is copied, too.
03533  *
03534  * NB: be sure stringval and extra fields of a new stack entry are
03535  * initialized to NULL before this is used, else we'll try to free() them.
03536  */
03537 static void
03538 set_stack_value(struct config_generic * gconf, config_var_value *val)
03539 {
03540     switch (gconf->vartype)
03541     {
03542         case PGC_BOOL:
03543             val->val.boolval =
03544                 *((struct config_bool *) gconf)->variable;
03545             break;
03546         case PGC_INT:
03547             val->val.intval =
03548                 *((struct config_int *) gconf)->variable;
03549             break;
03550         case PGC_REAL:
03551             val->val.realval =
03552                 *((struct config_real *) gconf)->variable;
03553             break;
03554         case PGC_STRING:
03555             set_string_field((struct config_string *) gconf,
03556                              &(val->val.stringval),
03557                              *((struct config_string *) gconf)->variable);
03558             break;
03559         case PGC_ENUM:
03560             val->val.enumval =
03561                 *((struct config_enum *) gconf)->variable;
03562             break;
03563     }
03564     set_extra_field(gconf, &(val->extra), gconf->extra);
03565 }
03566 
03567 /*
03568  * Support for discarding a no-longer-needed value in a stack entry.
03569  * The "extra" field associated with the stack entry is cleared, too.
03570  */
03571 static void
03572 discard_stack_value(struct config_generic * gconf, config_var_value *val)
03573 {
03574     switch (gconf->vartype)
03575     {
03576         case PGC_BOOL:
03577         case PGC_INT:
03578         case PGC_REAL:
03579         case PGC_ENUM:
03580             /* no need to do anything */
03581             break;
03582         case PGC_STRING:
03583             set_string_field((struct config_string *) gconf,
03584                              &(val->val.stringval),
03585                              NULL);
03586             break;
03587     }
03588     set_extra_field(gconf, &(val->extra), NULL);
03589 }
03590 
03591 
03592 /*
03593  * Fetch the sorted array pointer (exported for help_config.c's use ONLY)
03594  */
03595 struct config_generic **
03596 get_guc_variables(void)
03597 {
03598     return guc_variables;
03599 }
03600 
03601 
03602 /*
03603  * Build the sorted array.  This is split out so that it could be
03604  * re-executed after startup (eg, we could allow loadable modules to
03605  * add vars, and then we'd need to re-sort).
03606  */
03607 void
03608 build_guc_variables(void)
03609 {
03610     int         size_vars;
03611     int         num_vars = 0;
03612     struct config_generic **guc_vars;
03613     int         i;
03614 
03615     for (i = 0; ConfigureNamesBool[i].gen.name; i++)
03616     {
03617         struct config_bool *conf = &ConfigureNamesBool[i];
03618 
03619         /* Rather than requiring vartype to be filled in by hand, do this: */
03620         conf->gen.vartype = PGC_BOOL;
03621         num_vars++;
03622     }
03623 
03624     for (i = 0; ConfigureNamesInt[i].gen.name; i++)
03625     {
03626         struct config_int *conf = &ConfigureNamesInt[i];
03627 
03628         conf->gen.vartype = PGC_INT;
03629         num_vars++;
03630     }
03631 
03632     for (i = 0; ConfigureNamesReal[i].gen.name; i++)
03633     {
03634         struct config_real *conf = &ConfigureNamesReal[i];
03635 
03636         conf->gen.vartype = PGC_REAL;
03637         num_vars++;
03638     }
03639 
03640     for (i = 0; ConfigureNamesString[i].gen.name; i++)
03641     {
03642         struct config_string *conf = &ConfigureNamesString[i];
03643 
03644         conf->gen.vartype = PGC_STRING;
03645         num_vars++;
03646     }
03647 
03648     for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
03649     {
03650         struct config_enum *conf = &ConfigureNamesEnum[i];
03651 
03652         conf->gen.vartype = PGC_ENUM;
03653         num_vars++;
03654     }
03655 
03656     /*
03657      * Create table with 20% slack
03658      */
03659     size_vars = num_vars + num_vars / 4;
03660 
03661     guc_vars = (struct config_generic **)
03662         guc_malloc(FATAL, size_vars * sizeof(struct config_generic *));
03663 
03664     num_vars = 0;
03665 
03666     for (i = 0; ConfigureNamesBool[i].gen.name; i++)
03667         guc_vars[num_vars++] = &ConfigureNamesBool[i].gen;
03668 
03669     for (i = 0; ConfigureNamesInt[i].gen.name; i++)
03670         guc_vars[num_vars++] = &ConfigureNamesInt[i].gen;
03671 
03672     for (i = 0; ConfigureNamesReal[i].gen.name; i++)
03673         guc_vars[num_vars++] = &ConfigureNamesReal[i].gen;
03674 
03675     for (i = 0; ConfigureNamesString[i].gen.name; i++)
03676         guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
03677 
03678     for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
03679         guc_vars[num_vars++] = &ConfigureNamesEnum[i].gen;
03680 
03681     if (guc_variables)
03682         free(guc_variables);
03683     guc_variables = guc_vars;
03684     num_guc_variables = num_vars;
03685     size_guc_variables = size_vars;
03686     qsort((void *) guc_variables, num_guc_variables,
03687           sizeof(struct config_generic *), guc_var_compare);
03688 }
03689 
03690 /*
03691  * Add a new GUC variable to the list of known variables. The
03692  * list is expanded if needed.
03693  */
03694 static bool
03695 add_guc_variable(struct config_generic * var, int elevel)
03696 {
03697     if (num_guc_variables + 1 >= size_guc_variables)
03698     {
03699         /*
03700          * Increase the vector by 25%
03701          */
03702         int         size_vars = size_guc_variables + size_guc_variables / 4;
03703         struct config_generic **guc_vars;
03704 
03705         if (size_vars == 0)
03706         {
03707             size_vars = 100;
03708             guc_vars = (struct config_generic **)
03709                 guc_malloc(elevel, size_vars * sizeof(struct config_generic *));
03710         }
03711         else
03712         {
03713             guc_vars = (struct config_generic **)
03714                 guc_realloc(elevel, guc_variables, size_vars * sizeof(struct config_generic *));
03715         }
03716 
03717         if (guc_vars == NULL)
03718             return false;       /* out of memory */
03719 
03720         guc_variables = guc_vars;
03721         size_guc_variables = size_vars;
03722     }
03723     guc_variables[num_guc_variables++] = var;
03724     qsort((void *) guc_variables, num_guc_variables,
03725           sizeof(struct config_generic *), guc_var_compare);
03726     return true;
03727 }
03728 
03729 /*
03730  * Create and add a placeholder variable for a custom variable name.
03731  */
03732 static struct config_generic *
03733 add_placeholder_variable(const char *name, int elevel)
03734 {
03735     size_t      sz = sizeof(struct config_string) + sizeof(char *);
03736     struct config_string *var;
03737     struct config_generic *gen;
03738 
03739     var = (struct config_string *) guc_malloc(elevel, sz);
03740     if (var == NULL)
03741         return NULL;
03742     memset(var, 0, sz);
03743     gen = &var->gen;
03744 
03745     gen->name = guc_strdup(elevel, name);
03746     if (gen->name == NULL)
03747     {
03748         free(var);
03749         return NULL;
03750     }
03751 
03752     gen->context = PGC_USERSET;
03753     gen->group = CUSTOM_OPTIONS;
03754     gen->short_desc = "GUC placeholder variable";
03755     gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER;
03756     gen->vartype = PGC_STRING;
03757 
03758     /*
03759      * The char* is allocated at the end of the struct since we have no
03760      * 'static' place to point to.  Note that the current value, as well as
03761      * the boot and reset values, start out NULL.
03762      */
03763     var->variable = (char **) (var + 1);
03764 
03765     if (!add_guc_variable((struct config_generic *) var, elevel))
03766     {
03767         free((void *) gen->name);
03768         free(var);
03769         return NULL;
03770     }
03771 
03772     return gen;
03773 }
03774 
03775 /*
03776  * Look up option NAME.  If it exists, return a pointer to its record,
03777  * else return NULL.  If create_placeholders is TRUE, we'll create a
03778  * placeholder record for a valid-looking custom variable name.
03779  */
03780 static struct config_generic *
03781 find_option(const char *name, bool create_placeholders, int elevel)
03782 {
03783     const char **key = &name;
03784     struct config_generic **res;
03785     int         i;
03786 
03787     Assert(name);
03788 
03789     /*
03790      * By equating const char ** with struct config_generic *, we are assuming
03791      * the name field is first in config_generic.
03792      */
03793     res = (struct config_generic **) bsearch((void *) &key,
03794                                              (void *) guc_variables,
03795                                              num_guc_variables,
03796                                              sizeof(struct config_generic *),
03797                                              guc_var_compare);
03798     if (res)
03799         return *res;
03800 
03801     /*
03802      * See if the name is an obsolete name for a variable.  We assume that the
03803      * set of supported old names is short enough that a brute-force search is
03804      * the best way.
03805      */
03806     for (i = 0; map_old_guc_names[i] != NULL; i += 2)
03807     {
03808         if (guc_name_compare(name, map_old_guc_names[i]) == 0)
03809             return find_option(map_old_guc_names[i + 1], false, elevel);
03810     }
03811 
03812     if (create_placeholders)
03813     {
03814         /*
03815          * Check if the name is qualified, and if so, add a placeholder.
03816          */
03817         if (strchr(name, GUC_QUALIFIER_SEPARATOR) != NULL)
03818             return add_placeholder_variable(name, elevel);
03819     }
03820 
03821     /* Unknown name */
03822     return NULL;
03823 }
03824 
03825 
03826 /*
03827  * comparator for qsorting and bsearching guc_variables array
03828  */
03829 static int
03830 guc_var_compare(const void *a, const void *b)
03831 {
03832     const struct config_generic *confa = *(struct config_generic * const *) a;
03833     const struct config_generic *confb = *(struct config_generic * const *) b;
03834 
03835     return guc_name_compare(confa->name, confb->name);
03836 }
03837 
03838 /*
03839  * the bare comparison function for GUC names
03840  */
03841 static int
03842 guc_name_compare(const char *namea, const char *nameb)
03843 {
03844     /*
03845      * The temptation to use strcasecmp() here must be resisted, because the
03846      * array ordering has to remain stable across setlocale() calls. So, build
03847      * our own with a simple ASCII-only downcasing.
03848      */
03849     while (*namea && *nameb)
03850     {
03851         char        cha = *namea++;
03852         char        chb = *nameb++;
03853 
03854         if (cha >= 'A' && cha <= 'Z')
03855             cha += 'a' - 'A';
03856         if (chb >= 'A' && chb <= 'Z')
03857             chb += 'a' - 'A';
03858         if (cha != chb)
03859             return cha - chb;
03860     }
03861     if (*namea)
03862         return 1;               /* a is longer */
03863     if (*nameb)
03864         return -1;              /* b is longer */
03865     return 0;
03866 }
03867 
03868 
03869 /*
03870  * Initialize GUC options during program startup.
03871  *
03872  * Note that we cannot read the config file yet, since we have not yet
03873  * processed command-line switches.
03874  */
03875 void
03876 InitializeGUCOptions(void)
03877 {
03878     int         i;
03879 
03880     /*
03881      * Before log_line_prefix could possibly receive a nonempty setting, make
03882      * sure that timezone processing is minimally alive (see elog.c).
03883      */
03884     pg_timezone_initialize();
03885 
03886     /*
03887      * Build sorted array of all GUC variables.
03888      */
03889     build_guc_variables();
03890 
03891     /*
03892      * Load all variables with their compiled-in defaults, and initialize
03893      * status fields as needed.
03894      */
03895     for (i = 0; i < num_guc_variables; i++)
03896     {
03897         InitializeOneGUCOption(guc_variables[i]);
03898     }
03899 
03900     guc_dirty = false;
03901 
03902     reporting_enabled = false;
03903 
03904     /*
03905      * Prevent any attempt to override the transaction modes from
03906      * non-interactive sources.
03907      */
03908     SetConfigOption("transaction_isolation", "default",
03909                     PGC_POSTMASTER, PGC_S_OVERRIDE);
03910     SetConfigOption("transaction_read_only", "no",
03911                     PGC_POSTMASTER, PGC_S_OVERRIDE);
03912     SetConfigOption("transaction_deferrable", "no",
03913                     PGC_POSTMASTER, PGC_S_OVERRIDE);
03914 
03915     /*
03916      * For historical reasons, some GUC parameters can receive defaults from
03917      * environment variables.  Process those settings.
03918      */
03919     InitializeGUCOptionsFromEnvironment();
03920 }
03921 
03922 /*
03923  * Assign any GUC values that can come from the server's environment.
03924  *
03925  * This is called from InitializeGUCOptions, and also from ProcessConfigFile
03926  * to deal with the possibility that a setting has been removed from
03927  * postgresql.conf and should now get a value from the environment.
03928  * (The latter is a kludge that should probably go away someday; if so,
03929  * fold this back into InitializeGUCOptions.)
03930  */
03931 static void
03932 InitializeGUCOptionsFromEnvironment(void)
03933 {
03934     char       *env;
03935     long        stack_rlimit;
03936 
03937     env = getenv("PGPORT");
03938     if (env != NULL)
03939         SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
03940 
03941     env = getenv("PGDATESTYLE");
03942     if (env != NULL)
03943         SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
03944 
03945     env = getenv("PGCLIENTENCODING");
03946     if (env != NULL)
03947         SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
03948 
03949     /*
03950      * rlimit isn't exactly an "environment variable", but it behaves about
03951      * the same.  If we can identify the platform stack depth rlimit, increase
03952      * default stack depth setting up to whatever is safe (but at most 2MB).
03953      */
03954     stack_rlimit = get_stack_depth_rlimit();
03955     if (stack_rlimit > 0)
03956     {
03957         long        new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;
03958 
03959         if (new_limit > 100)
03960         {
03961             char        limbuf[16];
03962 
03963             new_limit = Min(new_limit, 2048);
03964             sprintf(limbuf, "%ld", new_limit);
03965             SetConfigOption("max_stack_depth", limbuf,
03966                             PGC_POSTMASTER, PGC_S_ENV_VAR);
03967         }
03968     }
03969 }
03970 
03971 /*
03972  * Initialize one GUC option variable to its compiled-in default.
03973  *
03974  * Note: the reason for calling check_hooks is not that we think the boot_val
03975  * might fail, but that the hooks might wish to compute an "extra" struct.
03976  */
03977 static void
03978 InitializeOneGUCOption(struct config_generic * gconf)
03979 {
03980     gconf->status = 0;
03981     gconf->source = PGC_S_DEFAULT;
03982     gconf->reset_source = PGC_S_DEFAULT;
03983     gconf->scontext = PGC_INTERNAL;
03984     gconf->reset_scontext = PGC_INTERNAL;
03985     gconf->stack = NULL;
03986     gconf->extra = NULL;
03987     gconf->sourcefile = NULL;
03988     gconf->sourceline = 0;
03989 
03990     switch (gconf->vartype)
03991     {
03992         case PGC_BOOL:
03993             {
03994                 struct config_bool *conf = (struct config_bool *) gconf;
03995                 bool        newval = conf->boot_val;
03996                 void       *extra = NULL;
03997 
03998                 if (!call_bool_check_hook(conf, &newval, &extra,
03999                                           PGC_S_DEFAULT, LOG))
04000                     elog(FATAL, "failed to initialize %s to %d",
04001                          conf->gen.name, (int) newval);
04002                 if (conf->assign_hook)
04003                     (*conf->assign_hook) (newval, extra);
04004                 *conf->variable = conf->reset_val = newval;
04005                 conf->gen.extra = conf->reset_extra = extra;
04006                 break;
04007             }
04008         case PGC_INT:
04009             {
04010                 struct config_int *conf = (struct config_int *) gconf;
04011                 int         newval = conf->boot_val;
04012                 void       *extra = NULL;
04013 
04014                 Assert(newval >= conf->min);
04015                 Assert(newval <= conf->max);
04016                 if (!call_int_check_hook(conf, &newval, &extra,
04017                                          PGC_S_DEFAULT, LOG))
04018                     elog(FATAL, "failed to initialize %s to %d",
04019                          conf->gen.name, newval);
04020                 if (conf->assign_hook)
04021                     (*conf->assign_hook) (newval, extra);
04022                 *conf->variable = conf->reset_val = newval;
04023                 conf->gen.extra = conf->reset_extra = extra;
04024                 break;
04025             }
04026         case PGC_REAL:
04027             {
04028                 struct config_real *conf = (struct config_real *) gconf;
04029                 double      newval = conf->boot_val;
04030                 void       *extra = NULL;
04031 
04032                 Assert(newval >= conf->min);
04033                 Assert(newval <= conf->max);
04034                 if (!call_real_check_hook(conf, &newval, &extra,
04035                                           PGC_S_DEFAULT, LOG))
04036                     elog(FATAL, "failed to initialize %s to %g",
04037                          conf->gen.name, newval);
04038                 if (conf->assign_hook)
04039                     (*conf->assign_hook) (newval, extra);
04040                 *conf->variable = conf->reset_val = newval;
04041                 conf->gen.extra = conf->reset_extra = extra;
04042                 break;
04043             }
04044         case PGC_STRING:
04045             {
04046                 struct config_string *conf = (struct config_string *) gconf;
04047                 char       *newval;
04048                 void       *extra = NULL;
04049 
04050                 /* non-NULL boot_val must always get strdup'd */
04051                 if (conf->boot_val != NULL)
04052                     newval = guc_strdup(FATAL, conf->boot_val);
04053                 else
04054                     newval = NULL;
04055 
04056                 if (!call_string_check_hook(conf, &newval, &extra,
04057                                             PGC_S_DEFAULT, LOG))
04058                     elog(FATAL, "failed to initialize %s to \"%s\"",
04059                          conf->gen.name, newval ? newval : "");
04060                 if (conf->assign_hook)
04061                     (*conf->assign_hook) (newval, extra);
04062                 *conf->variable = conf->reset_val = newval;
04063                 conf->gen.extra = conf->reset_extra = extra;
04064                 break;
04065             }
04066         case PGC_ENUM:
04067             {
04068                 struct config_enum *conf = (struct config_enum *) gconf;
04069                 int         newval = conf->boot_val;
04070                 void       *extra = NULL;
04071 
04072                 if (!call_enum_check_hook(conf, &newval, &extra,
04073                                           PGC_S_DEFAULT, LOG))
04074                     elog(FATAL, "failed to initialize %s to %d",
04075                          conf->gen.name, newval);
04076                 if (conf->assign_hook)
04077                     (*conf->assign_hook) (newval, extra);
04078                 *conf->variable = conf->reset_val = newval;
04079                 conf->gen.extra = conf->reset_extra = extra;
04080                 break;
04081             }
04082     }
04083 }
04084 
04085 
04086 /*
04087  * Select the configuration files and data directory to be used, and
04088  * do the initial read of postgresql.conf.
04089  *
04090  * This is called after processing command-line switches.
04091  *      userDoption is the -D switch value if any (NULL if unspecified).
04092  *      progname is just for use in error messages.
04093  *
04094  * Returns true on success; on failure, prints a suitable error message
04095  * to stderr and returns false.
04096  */
04097 bool
04098 SelectConfigFiles(const char *userDoption, const char *progname)
04099 {
04100     char       *configdir;
04101     char       *fname;
04102     struct stat stat_buf;
04103 
04104     /* configdir is -D option, or $PGDATA if no -D */
04105     if (userDoption)
04106         configdir = make_absolute_path(userDoption);
04107     else
04108         configdir = make_absolute_path(getenv("PGDATA"));
04109 
04110     /*
04111      * Find the configuration file: if config_file was specified on the
04112      * command line, use it, else use configdir/postgresql.conf.  In any case
04113      * ensure the result is an absolute path, so that it will be interpreted
04114      * the same way by future backends.
04115      */
04116     if (ConfigFileName)
04117         fname = make_absolute_path(ConfigFileName);
04118     else if (configdir)
04119     {
04120         fname = guc_malloc(FATAL,
04121                            strlen(configdir) + strlen(CONFIG_FILENAME) + 2);
04122         sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);
04123     }
04124     else
04125     {
04126         write_stderr("%s does not know where to find the server configuration file.\n"
04127                      "You must specify the --config-file or -D invocation "
04128                      "option or set the PGDATA environment variable.\n",
04129                      progname);
04130         return false;
04131     }
04132 
04133     /*
04134      * Set the ConfigFileName GUC variable to its final value, ensuring that
04135      * it can't be overridden later.
04136      */
04137     SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
04138     free(fname);
04139 
04140     /*
04141      * Now read the config file for the first time.
04142      */
04143     if (stat(ConfigFileName, &stat_buf) != 0)
04144     {
04145         write_stderr("%s cannot access the server configuration file \"%s\": %s\n",
04146                      progname, ConfigFileName, strerror(errno));
04147         free(configdir);
04148         return false;
04149     }
04150 
04151     ProcessConfigFile(PGC_POSTMASTER);
04152 
04153     /*
04154      * If the data_directory GUC variable has been set, use that as DataDir;
04155      * otherwise use configdir if set; else punt.
04156      *
04157      * Note: SetDataDir will copy and absolute-ize its argument, so we don't
04158      * have to.
04159      */
04160     if (data_directory)
04161         SetDataDir(data_directory);
04162     else if (configdir)
04163         SetDataDir(configdir);
04164     else
04165     {
04166         write_stderr("%s does not know where to find the database system data.\n"
04167                      "This can be specified as \"data_directory\" in \"%s\", "
04168                      "or by the -D invocation option, or by the "
04169                      "PGDATA environment variable.\n",
04170                      progname, ConfigFileName);
04171         return false;
04172     }
04173 
04174     /*
04175      * Reflect the final DataDir value back into the data_directory GUC var.
04176      * (If you are wondering why we don't just make them a single variable,
04177      * it's because the EXEC_BACKEND case needs DataDir to be transmitted to
04178      * child backends specially.  XXX is that still true?  Given that we now
04179      * chdir to DataDir, EXEC_BACKEND can read the config file without knowing
04180      * DataDir in advance.)
04181      */
04182     SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
04183 
04184     /*
04185      * If timezone_abbreviations wasn't set in the configuration file, install
04186      * the default value.  We do it this way because we can't safely install a
04187      * "real" value until my_exec_path is set, which may not have happened
04188      * when InitializeGUCOptions runs, so the bootstrap default value cannot
04189      * be the real desired default.
04190      */
04191     pg_timezone_abbrev_initialize();
04192 
04193     /*
04194      * Figure out where pg_hba.conf is, and make sure the path is absolute.
04195      */
04196     if (HbaFileName)
04197         fname = make_absolute_path(HbaFileName);
04198     else if (configdir)
04199     {
04200         fname = guc_malloc(FATAL,
04201                            strlen(configdir) + strlen(HBA_FILENAME) + 2);
04202         sprintf(fname, "%s/%s", configdir, HBA_FILENAME);
04203     }
04204     else
04205     {
04206         write_stderr("%s does not know where to find the \"hba\" configuration file.\n"
04207                      "This can be specified as \"hba_file\" in \"%s\", "
04208                      "or by the -D invocation option, or by the "
04209                      "PGDATA environment variable.\n",
04210                      progname, ConfigFileName);
04211         return false;
04212     }
04213     SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
04214     free(fname);
04215 
04216     /*
04217      * Likewise for pg_ident.conf.
04218      */
04219     if (IdentFileName)
04220         fname = make_absolute_path(IdentFileName);
04221     else if (configdir)
04222     {
04223         fname = guc_malloc(FATAL,
04224                            strlen(configdir) + strlen(IDENT_FILENAME) + 2);
04225         sprintf(fname, "%s/%s", configdir, IDENT_FILENAME);
04226     }
04227     else
04228     {
04229         write_stderr("%s does not know where to find the \"ident\" configuration file.\n"
04230                      "This can be specified as \"ident_file\" in \"%s\", "
04231                      "or by the -D invocation option, or by the "
04232                      "PGDATA environment variable.\n",
04233                      progname, ConfigFileName);
04234         return false;
04235     }
04236     SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
04237     free(fname);
04238 
04239     free(configdir);
04240 
04241     return true;
04242 }
04243 
04244 
04245 /*
04246  * Reset all options to their saved default values (implements RESET ALL)
04247  */
04248 void
04249 ResetAllOptions(void)
04250 {
04251     int         i;
04252 
04253     for (i = 0; i < num_guc_variables; i++)
04254     {
04255         struct config_generic *gconf = guc_variables[i];
04256 
04257         /* Don't reset non-SET-able values */
04258         if (gconf->context != PGC_SUSET &&
04259             gconf->context != PGC_USERSET)
04260             continue;
04261         /* Don't reset if special exclusion from RESET ALL */
04262         if (gconf->flags & GUC_NO_RESET_ALL)
04263             continue;
04264         /* No need to reset if wasn't SET */
04265         if (gconf->source <= PGC_S_OVERRIDE)
04266             continue;
04267 
04268         /* Save old value to support transaction abort */
04269         push_old_value(gconf, GUC_ACTION_SET);
04270 
04271         switch (gconf->vartype)
04272         {
04273             case PGC_BOOL:
04274                 {
04275                     struct config_bool *conf = (struct config_bool *) gconf;
04276 
04277                     if (conf->assign_hook)
04278                         (*conf->assign_hook) (conf->reset_val,
04279                                               conf->reset_extra);
04280                     *conf->variable = conf->reset_val;
04281                     set_extra_field(&conf->gen, &conf->gen.extra,
04282                                     conf->reset_extra);
04283                     break;
04284                 }
04285             case PGC_INT:
04286                 {
04287                     struct config_int *conf = (struct config_int *) gconf;
04288 
04289                     if (conf->assign_hook)
04290                         (*conf->assign_hook) (conf->reset_val,
04291                                               conf->reset_extra);
04292                     *conf->variable = conf->reset_val;
04293                     set_extra_field(&conf->gen, &conf->gen.extra,
04294                                     conf->reset_extra);
04295                     break;
04296                 }
04297             case PGC_REAL:
04298                 {
04299                     struct config_real *conf = (struct config_real *) gconf;
04300 
04301                     if (conf->assign_hook)
04302                         (*conf->assign_hook) (conf->reset_val,
04303                                               conf->reset_extra);
04304                     *conf->variable = conf->reset_val;
04305                     set_extra_field(&conf->gen, &conf->gen.extra,
04306                                     conf->reset_extra);
04307                     break;
04308                 }
04309             case PGC_STRING:
04310                 {
04311                     struct config_string *conf = (struct config_string *) gconf;
04312 
04313                     if (conf->assign_hook)
04314                         (*conf->assign_hook) (conf->reset_val,
04315                                               conf->reset_extra);
04316                     set_string_field(conf, conf->variable, conf->reset_val);
04317                     set_extra_field(&conf->gen, &conf->gen.extra,
04318                                     conf->reset_extra);
04319                     break;
04320                 }
04321             case PGC_ENUM:
04322                 {
04323                     struct config_enum *conf = (struct config_enum *) gconf;
04324 
04325                     if (conf->assign_hook)
04326                         (*conf->assign_hook) (conf->reset_val,
04327                                               conf->reset_extra);
04328                     *conf->variable = conf->reset_val;
04329                     set_extra_field(&conf->gen, &conf->gen.extra,
04330                                     conf->reset_extra);
04331                     break;
04332                 }
04333         }
04334 
04335         gconf->source = gconf->reset_source;
04336         gconf->scontext = gconf->reset_scontext;
04337 
04338         if (gconf->flags & GUC_REPORT)
04339             ReportGUCOption(gconf);
04340     }
04341 }
04342 
04343 
04344 /*
04345  * push_old_value
04346  *      Push previous state during transactional assignment to a GUC variable.
04347  */
04348 static void
04349 push_old_value(struct config_generic * gconf, GucAction action)
04350 {
04351     GucStack   *stack;
04352 
04353     /* If we're not inside a nest level, do nothing */
04354     if (GUCNestLevel == 0)
04355         return;
04356 
04357     /* Do we already have a stack entry of the current nest level? */
04358     stack = gconf->stack;
04359     if (stack && stack->nest_level >= GUCNestLevel)
04360     {
04361         /* Yes, so adjust its state if necessary */
04362         Assert(stack->nest_level == GUCNestLevel);
04363         switch (action)
04364         {
04365             case GUC_ACTION_SET:
04366                 /* SET overrides any prior action at same nest level */
04367                 if (stack->state == GUC_SET_LOCAL)
04368                 {
04369                     /* must discard old masked value */
04370                     discard_stack_value(gconf, &stack->masked);
04371                 }
04372                 stack->state = GUC_SET;
04373                 break;
04374             case GUC_ACTION_LOCAL:
04375                 if (stack->state == GUC_SET)
04376                 {
04377                     /* SET followed by SET LOCAL, remember SET's value */
04378                     stack->masked_scontext = gconf->scontext;
04379                     set_stack_value(gconf, &stack->masked);
04380                     stack->state = GUC_SET_LOCAL;
04381                 }
04382                 /* in all other cases, no change to stack entry */
04383                 break;
04384             case GUC_ACTION_SAVE:
04385                 /* Could only have a prior SAVE of same variable */
04386                 Assert(stack->state == GUC_SAVE);
04387                 break;
04388         }
04389         Assert(guc_dirty);      /* must be set already */
04390         return;
04391     }
04392 
04393     /*
04394      * Push a new stack entry
04395      *
04396      * We keep all the stack entries in TopTransactionContext for simplicity.
04397      */
04398     stack = (GucStack *) MemoryContextAllocZero(TopTransactionContext,
04399                                                 sizeof(GucStack));
04400 
04401     stack->prev = gconf->stack;
04402     stack->nest_level = GUCNestLevel;
04403     switch (action)
04404     {
04405         case GUC_ACTION_SET:
04406             stack->state = GUC_SET;
04407             break;
04408         case GUC_ACTION_LOCAL:
04409             stack->state = GUC_LOCAL;
04410             break;
04411         case GUC_ACTION_SAVE:
04412             stack->state = GUC_SAVE;
04413             break;
04414     }
04415     stack->source = gconf->source;
04416     stack->scontext = gconf->scontext;
04417     set_stack_value(gconf, &stack->prior);
04418 
04419     gconf->stack = stack;
04420 
04421     /* Ensure we remember to pop at end of xact */
04422     guc_dirty = true;
04423 }
04424 
04425 
04426 /*
04427  * Do GUC processing at main transaction start.
04428  */
04429 void
04430 AtStart_GUC(void)
04431 {
04432     /*
04433      * The nest level should be 0 between transactions; if it isn't, somebody
04434      * didn't call AtEOXact_GUC, or called it with the wrong nestLevel.  We
04435      * throw a warning but make no other effort to clean up.
04436      */
04437     if (GUCNestLevel != 0)
04438         elog(WARNING, "GUC nest level = %d at transaction start",
04439              GUCNestLevel);
04440     GUCNestLevel = 1;
04441 }
04442 
04443 /*
04444  * Enter a new nesting level for GUC values.  This is called at subtransaction
04445  * start, and when entering a function that has proconfig settings, and in
04446  * some other places where we want to set GUC variables transiently.
04447  * NOTE we must not risk error here, else subtransaction start will be unhappy.
04448  */
04449 int
04450 NewGUCNestLevel(void)
04451 {
04452     return ++GUCNestLevel;
04453 }
04454 
04455 /*
04456  * Do GUC processing at transaction or subtransaction commit or abort, or
04457  * when exiting a function that has proconfig settings, or when undoing a
04458  * transient assignment to some GUC variables.  (The name is thus a bit of
04459  * a misnomer; perhaps it should be ExitGUCNestLevel or some such.)
04460  * During abort, we discard all GUC settings that were applied at nesting
04461  * levels >= nestLevel.  nestLevel == 1 corresponds to the main transaction.
04462  */
04463 void
04464 AtEOXact_GUC(bool isCommit, int nestLevel)
04465 {
04466     bool        still_dirty;
04467     int         i;
04468 
04469     /*
04470      * Note: it's possible to get here with GUCNestLevel == nestLevel-1 during
04471      * abort, if there is a failure during transaction start before
04472      * AtStart_GUC is called.
04473      */
04474     Assert(nestLevel > 0 &&
04475            (nestLevel <= GUCNestLevel ||
04476             (nestLevel == GUCNestLevel + 1 && !isCommit)));
04477 
04478     /* Quick exit if nothing's changed in this transaction */
04479     if (!guc_dirty)
04480     {
04481         GUCNestLevel = nestLevel - 1;
04482         return;
04483     }
04484 
04485     still_dirty = false;
04486     for (i = 0; i < num_guc_variables; i++)
04487     {
04488         struct config_generic *gconf = guc_variables[i];
04489         GucStack   *stack;
04490 
04491         /*
04492          * Process and pop each stack entry within the nest level. To simplify
04493          * fmgr_security_definer() and other places that use GUC_ACTION_SAVE,
04494          * we allow failure exit from code that uses a local nest level to be
04495          * recovered at the surrounding transaction or subtransaction abort;
04496          * so there could be more than one stack entry to pop.
04497          */
04498         while ((stack = gconf->stack) != NULL &&
04499                stack->nest_level >= nestLevel)
04500         {
04501             GucStack   *prev = stack->prev;
04502             bool        restorePrior = false;
04503             bool        restoreMasked = false;
04504             bool        changed;
04505 
04506             /*
04507              * In this next bit, if we don't set either restorePrior or
04508              * restoreMasked, we must "discard" any unwanted fields of the
04509              * stack entries to avoid leaking memory.  If we do set one of
04510              * those flags, unused fields will be cleaned up after restoring.
04511              */
04512             if (!isCommit)      /* if abort, always restore prior value */
04513                 restorePrior = true;
04514             else if (stack->state == GUC_SAVE)
04515                 restorePrior = true;
04516             else if (stack->nest_level == 1)
04517             {
04518                 /* transaction commit */
04519                 if (stack->state == GUC_SET_LOCAL)
04520                     restoreMasked = true;
04521                 else if (stack->state == GUC_SET)
04522                 {
04523                     /* we keep the current active value */
04524                     discard_stack_value(gconf, &stack->prior);
04525                 }
04526                 else    /* must be GUC_LOCAL */
04527                     restorePrior = true;
04528             }
04529             else if (prev == NULL ||
04530                      prev->nest_level < stack->nest_level - 1)
04531             {
04532                 /* decrement entry's level and do not pop it */
04533                 stack->nest_level--;
04534                 continue;
04535             }
04536             else
04537             {
04538                 /*
04539                  * We have to merge this stack entry into prev. See README for
04540                  * discussion of this bit.
04541                  */
04542                 switch (stack->state)
04543                 {
04544                     case GUC_SAVE:
04545                         Assert(false);  /* can't get here */
04546 
04547                     case GUC_SET:
04548                         /* next level always becomes SET */
04549                         discard_stack_value(gconf, &stack->prior);
04550                         if (prev->state == GUC_SET_LOCAL)
04551                             discard_stack_value(gconf, &prev->masked);
04552                         prev->state = GUC_SET;
04553                         break;
04554 
04555                     case GUC_LOCAL:
04556                         if (prev->state == GUC_SET)
04557                         {
04558                             /* LOCAL migrates down */
04559                             prev->masked_scontext = stack->scontext;
04560                             prev->masked = stack->prior;
04561                             prev->state = GUC_SET_LOCAL;
04562                         }
04563                         else
04564                         {
04565                             /* else just forget this stack level */
04566                             discard_stack_value(gconf, &stack->prior);
04567                         }
04568                         break;
04569 
04570                     case GUC_SET_LOCAL:
04571                         /* prior state at this level no longer wanted */
04572                         discard_stack_value(gconf, &stack->prior);
04573                         /* copy down the masked state */
04574                         prev->masked_scontext = stack->masked_scontext;
04575                         if (prev->state == GUC_SET_LOCAL)
04576                             discard_stack_value(gconf, &prev->masked);
04577                         prev->masked = stack->masked;
04578                         prev->state = GUC_SET_LOCAL;
04579                         break;
04580                 }
04581             }
04582 
04583             changed = false;
04584 
04585             if (restorePrior || restoreMasked)
04586             {
04587                 /* Perform appropriate restoration of the stacked value */
04588                 config_var_value newvalue;
04589                 GucSource   newsource;
04590                 GucContext  newscontext;
04591 
04592                 if (restoreMasked)
04593                 {
04594                     newvalue = stack->masked;
04595                     newsource = PGC_S_SESSION;
04596                     newscontext = stack->masked_scontext;
04597                 }
04598                 else
04599                 {
04600                     newvalue = stack->prior;
04601                     newsource = stack->source;
04602                     newscontext = stack->scontext;
04603                 }
04604 
04605                 switch (gconf->vartype)
04606                 {
04607                     case PGC_BOOL:
04608                         {
04609                             struct config_bool *conf = (struct config_bool *) gconf;
04610                             bool        newval = newvalue.val.boolval;
04611                             void       *newextra = newvalue.extra;
04612 
04613                             if (*conf->variable != newval ||
04614                                 conf->gen.extra != newextra)
04615                             {
04616                                 if (conf->assign_hook)
04617                                     (*conf->assign_hook) (newval, newextra);
04618                                 *conf->variable = newval;
04619                                 set_extra_field(&conf->gen, &conf->gen.extra,
04620                                                 newextra);
04621                                 changed = true;
04622                             }
04623                             break;
04624                         }
04625                     case PGC_INT:
04626                         {
04627                             struct config_int *conf = (struct config_int *) gconf;
04628                             int         newval = newvalue.val.intval;
04629                             void       *newextra = newvalue.extra;
04630 
04631                             if (*conf->variable != newval ||
04632                                 conf->gen.extra != newextra)
04633                             {
04634                                 if (conf->assign_hook)
04635                                     (*conf->assign_hook) (newval, newextra);
04636                                 *conf->variable = newval;
04637                                 set_extra_field(&conf->gen, &conf->gen.extra,
04638                                                 newextra);
04639                                 changed = true;
04640                             }
04641                             break;
04642                         }
04643                     case PGC_REAL:
04644                         {
04645                             struct config_real *conf = (struct config_real *) gconf;
04646                             double      newval = newvalue.val.realval;
04647                             void       *newextra = newvalue.extra;
04648 
04649                             if (*conf->variable != newval ||
04650                                 conf->gen.extra != newextra)
04651                             {
04652                                 if (conf->assign_hook)
04653                                     (*conf->assign_hook) (newval, newextra);
04654                                 *conf->variable = newval;
04655                                 set_extra_field(&conf->gen, &conf->gen.extra,
04656                                                 newextra);
04657                                 changed = true;
04658                             }
04659                             break;
04660                         }
04661                     case PGC_STRING:
04662                         {
04663                             struct config_string *conf = (struct config_string *) gconf;
04664                             char       *newval = newvalue.val.stringval;
04665                             void       *newextra = newvalue.extra;
04666 
04667                             if (*conf->variable != newval ||
04668                                 conf->gen.extra != newextra)
04669                             {
04670                                 if (conf->assign_hook)
04671                                     (*conf->assign_hook) (newval, newextra);
04672                                 set_string_field(conf, conf->variable, newval);
04673                                 set_extra_field(&conf->gen, &conf->gen.extra,
04674                                                 newextra);
04675                                 changed = true;
04676                             }
04677 
04678                             /*
04679                              * Release stacked values if not used anymore. We
04680                              * could use discard_stack_value() here, but since
04681                              * we have type-specific code anyway, might as
04682                              * well inline it.
04683                              */
04684                             set_string_field(conf, &stack->prior.val.stringval, NULL);
04685                             set_string_field(conf, &stack->masked.val.stringval, NULL);
04686                             break;
04687                         }
04688                     case PGC_ENUM:
04689                         {
04690                             struct config_enum *conf = (struct config_enum *) gconf;
04691                             int         newval = newvalue.val.enumval;
04692                             void       *newextra = newvalue.extra;
04693 
04694                             if (*conf->variable != newval ||
04695                                 conf->gen.extra != newextra)
04696                             {
04697                                 if (conf->assign_hook)
04698                                     (*conf->assign_hook) (newval, newextra);
04699                                 *conf->variable = newval;
04700                                 set_extra_field(&conf->gen, &conf->gen.extra,
04701                                                 newextra);
04702                                 changed = true;
04703                             }
04704                             break;
04705                         }
04706                 }
04707 
04708                 /*
04709                  * Release stacked extra values if not used anymore.
04710                  */
04711                 set_extra_field(gconf, &(stack->prior.extra), NULL);
04712                 set_extra_field(gconf, &(stack->masked.extra), NULL);
04713 
04714                 /* And restore source information */
04715                 gconf->source = newsource;
04716                 gconf->scontext = newscontext;
04717             }
04718 
04719             /* Finish popping the state stack */
04720             gconf->stack = prev;
04721             pfree(stack);
04722 
04723             /* Report new value if we changed it */
04724             if (changed && (gconf->flags & GUC_REPORT))
04725                 ReportGUCOption(gconf);
04726         }                       /* end of stack-popping loop */
04727 
04728         if (stack != NULL)
04729             still_dirty = true;
04730     }
04731 
04732     /* If there are no remaining stack entries, we can reset guc_dirty */
04733     guc_dirty = still_dirty;
04734 
04735     /* Update nesting level */
04736     GUCNestLevel = nestLevel - 1;
04737 }
04738 
04739 
04740 /*
04741  * Start up automatic reporting of changes to variables marked GUC_REPORT.
04742  * This is executed at completion of backend startup.
04743  */
04744 void
04745 BeginReportingGUCOptions(void)
04746 {
04747     int         i;
04748 
04749     /*
04750      * Don't do anything unless talking to an interactive frontend of protocol
04751      * 3.0 or later.
04752      */
04753     if (whereToSendOutput != DestRemote ||
04754         PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
04755         return;
04756 
04757     reporting_enabled = true;
04758 
04759     /* Transmit initial values of interesting variables */
04760     for (i = 0; i < num_guc_variables; i++)
04761     {
04762         struct config_generic *conf = guc_variables[i];
04763 
04764         if (conf->flags & GUC_REPORT)
04765             ReportGUCOption(conf);
04766     }
04767 }
04768 
04769 /*
04770  * ReportGUCOption: if appropriate, transmit option value to frontend
04771  */
04772 static void
04773 ReportGUCOption(struct config_generic * record)
04774 {
04775     if (reporting_enabled && (record->flags & GUC_REPORT))
04776     {
04777         char       *val = _ShowOption(record, false);
04778         StringInfoData msgbuf;
04779 
04780         pq_beginmessage(&msgbuf, 'S');
04781         pq_sendstring(&msgbuf, record->name);
04782         pq_sendstring(&msgbuf, val);
04783         pq_endmessage(&msgbuf);
04784 
04785         pfree(val);
04786     }
04787 }
04788 
04789 /*
04790  * Try to parse value as an integer.  The accepted formats are the
04791  * usual decimal, octal, or hexadecimal formats, optionally followed by
04792  * a unit name if "flags" indicates a unit is allowed.
04793  *
04794  * If the string parses okay, return true, else false.
04795  * If okay and result is not NULL, return the value in *result.
04796  * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
04797  *  HINT message, or NULL if no hint provided.
04798  */
04799 bool
04800 parse_int(const char *value, int *result, int flags, const char **hintmsg)
04801 {
04802     int64       val;
04803     char       *endptr;
04804 
04805     /* To suppress compiler warnings, always set output params */
04806     if (result)
04807         *result = 0;
04808     if (hintmsg)
04809         *hintmsg = NULL;
04810 
04811     /* We assume here that int64 is at least as wide as long */
04812     errno = 0;
04813     val = strtol(value, &endptr, 0);
04814 
04815     if (endptr == value)
04816         return false;           /* no HINT for integer syntax error */
04817 
04818     if (errno == ERANGE || val != (int64) ((int32) val))
04819     {
04820         if (hintmsg)
04821             *hintmsg = gettext_noop("Value exceeds integer range.");
04822         return false;
04823     }
04824 
04825     /* allow whitespace between integer and unit */
04826     while (isspace((unsigned char) *endptr))
04827         endptr++;
04828 
04829     /* Handle possible unit */
04830     if (*endptr != '\0')
04831     {
04832         /*
04833          * Note: the multiple-switch coding technique here is a bit tedious,
04834          * but seems necessary to avoid intermediate-value overflows.
04835          */
04836         if (flags & GUC_UNIT_MEMORY)
04837         {
04838             /* Set hint for use if no match or trailing garbage */
04839             if (hintmsg)
04840                 *hintmsg = gettext_noop("Valid units for this parameter are \"kB\", \"MB\", and \"GB\".");
04841 
04842 #if BLCKSZ < 1024 || BLCKSZ > (1024*1024)
04843 #error BLCKSZ must be between 1KB and 1MB
04844 #endif
04845 #if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024*1024)
04846 #error XLOG_BLCKSZ must be between 1KB and 1MB
04847 #endif
04848 
04849             if (strncmp(endptr, "kB", 2) == 0)
04850             {
04851                 endptr += 2;
04852                 switch (flags & GUC_UNIT_MEMORY)
04853                 {
04854                     case GUC_UNIT_BLOCKS:
04855                         val /= (BLCKSZ / 1024);
04856                         break;
04857                     case GUC_UNIT_XBLOCKS:
04858                         val /= (XLOG_BLCKSZ / 1024);
04859                         break;
04860                 }
04861             }
04862             else if (strncmp(endptr, "MB", 2) == 0)
04863             {
04864                 endptr += 2;
04865                 switch (flags & GUC_UNIT_MEMORY)
04866                 {
04867                     case GUC_UNIT_KB:
04868                         val *= KB_PER_MB;
04869                         break;
04870                     case GUC_UNIT_BLOCKS:
04871                         val *= KB_PER_MB / (BLCKSZ / 1024);
04872                         break;
04873                     case GUC_UNIT_XBLOCKS:
04874                         val *= KB_PER_MB / (XLOG_BLCKSZ / 1024);
04875                         break;
04876                 }
04877             }
04878             else if (strncmp(endptr, "GB", 2) == 0)
04879             {
04880                 endptr += 2;
04881                 switch (flags & GUC_UNIT_MEMORY)
04882                 {
04883                     case GUC_UNIT_KB:
04884                         val *= KB_PER_GB;
04885                         break;
04886                     case GUC_UNIT_BLOCKS:
04887                         val *= KB_PER_GB / (BLCKSZ / 1024);
04888                         break;
04889                     case GUC_UNIT_XBLOCKS:
04890                         val *= KB_PER_GB / (XLOG_BLCKSZ / 1024);
04891                         break;
04892                 }
04893             }
04894         }
04895         else if (flags & GUC_UNIT_TIME)
04896         {
04897             /* Set hint for use if no match or trailing garbage */
04898             if (hintmsg)
04899                 *hintmsg = gettext_noop("Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\".");
04900 
04901             if (strncmp(endptr, "ms", 2) == 0)
04902             {
04903                 endptr += 2;
04904                 switch (flags & GUC_UNIT_TIME)
04905                 {
04906                     case GUC_UNIT_S:
04907                         val /= MS_PER_S;
04908                         break;
04909                     case GUC_UNIT_MIN:
04910                         val /= MS_PER_MIN;
04911                         break;
04912                 }
04913             }
04914             else if (strncmp(endptr, "s", 1) == 0)
04915             {
04916                 endptr += 1;
04917                 switch (flags & GUC_UNIT_TIME)
04918                 {
04919                     case GUC_UNIT_MS:
04920                         val *= MS_PER_S;
04921                         break;
04922                     case GUC_UNIT_MIN:
04923                         val /= S_PER_MIN;
04924                         break;
04925                 }
04926             }
04927             else if (strncmp(endptr, "min", 3) == 0)
04928             {
04929                 endptr += 3;
04930                 switch (flags & GUC_UNIT_TIME)
04931                 {
04932                     case GUC_UNIT_MS:
04933                         val *= MS_PER_MIN;
04934                         break;
04935                     case GUC_UNIT_S:
04936                         val *= S_PER_MIN;
04937                         break;
04938                 }
04939             }
04940             else if (strncmp(endptr, "h", 1) == 0)
04941             {
04942                 endptr += 1;
04943                 switch (flags & GUC_UNIT_TIME)
04944                 {
04945                     case GUC_UNIT_MS:
04946                         val *= MS_PER_H;
04947                         break;
04948                     case GUC_UNIT_S:
04949                         val *= S_PER_H;
04950                         break;
04951                     case GUC_UNIT_MIN:
04952                         val *= MIN_PER_H;
04953                         break;
04954                 }
04955             }
04956             else if (strncmp(endptr, "d", 1) == 0)
04957             {
04958                 endptr += 1;
04959                 switch (flags & GUC_UNIT_TIME)
04960                 {
04961                     case GUC_UNIT_MS:
04962                         val *= MS_PER_D;
04963                         break;
04964                     case GUC_UNIT_S:
04965                         val *= S_PER_D;
04966                         break;
04967                     case GUC_UNIT_MIN:
04968                         val *= MIN_PER_D;
04969                         break;
04970                 }
04971             }
04972         }
04973 
04974         /* allow whitespace after unit */
04975         while (isspace((unsigned char) *endptr))
04976             endptr++;
04977 
04978         if (*endptr != '\0')
04979             return false;       /* appropriate hint, if any, already set */
04980 
04981         /* Check for overflow due to units conversion */
04982         if (val != (int64) ((int32) val))
04983         {
04984             if (hintmsg)
04985                 *hintmsg = gettext_noop("Value exceeds integer range.");
04986             return false;
04987         }
04988     }
04989 
04990     if (result)
04991         *result = (int) val;
04992     return true;
04993 }
04994 
04995 
04996 
04997 /*
04998  * Try to parse value as a floating point number in the usual format.
04999  * If the string parses okay, return true, else false.
05000  * If okay and result is not NULL, return the value in *result.
05001  */
05002 bool
05003 parse_real(const char *value, double *result)
05004 {
05005     double      val;
05006     char       *endptr;
05007 
05008     if (result)
05009         *result = 0;            /* suppress compiler warning */
05010 
05011     errno = 0;
05012     val = strtod(value, &endptr);
05013     if (endptr == value || errno == ERANGE)
05014         return false;
05015 
05016     /* allow whitespace after number */
05017     while (isspace((unsigned char) *endptr))
05018         endptr++;
05019     if (*endptr != '\0')
05020         return false;
05021 
05022     if (result)
05023         *result = val;
05024     return true;
05025 }
05026 
05027 
05028 /*
05029  * Lookup the name for an enum option with the selected value.
05030  * Should only ever be called with known-valid values, so throws
05031  * an elog(ERROR) if the enum option is not found.
05032  *
05033  * The returned string is a pointer to static data and not
05034  * allocated for modification.
05035  */
05036 const char *
05037 config_enum_lookup_by_value(struct config_enum * record, int val)
05038 {
05039     const struct config_enum_entry *entry;
05040 
05041     for (entry = record->options; entry && entry->name; entry++)
05042     {
05043         if (entry->val == val)
05044             return entry->name;
05045     }
05046 
05047     elog(ERROR, "could not find enum option %d for %s",
05048          val, record->gen.name);
05049     return NULL;                /* silence compiler */
05050 }
05051 
05052 
05053 /*
05054  * Lookup the value for an enum option with the selected name
05055  * (case-insensitive).
05056  * If the enum option is found, sets the retval value and returns
05057  * true. If it's not found, return FALSE and retval is set to 0.
05058  */
05059 bool
05060 config_enum_lookup_by_name(struct config_enum * record, const char *value,
05061                            int *retval)
05062 {
05063     const struct config_enum_entry *entry;
05064 
05065     for (entry = record->options; entry && entry->name; entry++)
05066     {
05067         if (pg_strcasecmp(value, entry->name) == 0)
05068         {
05069             *retval = entry->val;
05070             return TRUE;
05071         }
05072     }
05073 
05074     *retval = 0;
05075     return FALSE;
05076 }
05077 
05078 
05079 /*
05080  * Return a list of all available options for an enum, excluding
05081  * hidden ones, separated by the given separator.
05082  * If prefix is non-NULL, it is added before the first enum value.
05083  * If suffix is non-NULL, it is added to the end of the string.
05084  */
05085 static char *
05086 config_enum_get_options(struct config_enum * record, const char *prefix,
05087                         const char *suffix, const char *separator)
05088 {
05089     const struct config_enum_entry *entry;
05090     StringInfoData retstr;
05091     int         seplen;
05092 
05093     initStringInfo(&retstr);
05094     appendStringInfoString(&retstr, prefix);
05095 
05096     seplen = strlen(separator);
05097     for (entry = record->options; entry && entry->name; entry++)
05098     {
05099         if (!entry->hidden)
05100         {
05101             appendStringInfoString(&retstr, entry->name);
05102             appendBinaryStringInfo(&retstr, separator, seplen);
05103         }
05104     }
05105 
05106     /*
05107      * All the entries may have been hidden, leaving the string empty if no
05108      * prefix was given. This indicates a broken GUC setup, since there is no
05109      * use for an enum without any values, so we just check to make sure we
05110      * don't write to invalid memory instead of actually trying to do
05111      * something smart with it.
05112      */
05113     if (retstr.len >= seplen)
05114     {
05115         /* Replace final separator */
05116         retstr.data[retstr.len - seplen] = '\0';
05117         retstr.len -= seplen;
05118     }
05119 
05120     appendStringInfoString(&retstr, suffix);
05121 
05122     return retstr.data;
05123 }
05124 
05125 
05126 /*
05127  * Sets option `name' to given value.
05128  *
05129  * The value should be a string, which will be parsed and converted to
05130  * the appropriate data type.  The context and source parameters indicate
05131  * in which context this function is being called, so that it can apply the
05132  * access restrictions properly.
05133  *
05134  * If value is NULL, set the option to its default value (normally the
05135  * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
05136  *
05137  * action indicates whether to set the value globally in the session, locally
05138  * to the current top transaction, or just for the duration of a function call.
05139  *
05140  * If changeVal is false then don't really set the option but do all
05141  * the checks to see if it would work.
05142  *
05143  * elevel should normally be passed as zero, allowing this function to make
05144  * its standard choice of ereport level.  However some callers need to be
05145  * able to override that choice; they should pass the ereport level to use.
05146  *
05147  * Return value:
05148  *  +1: the value is valid and was successfully applied.
05149  *  0:  the name or value is invalid (but see below).
05150  *  -1: the value was not applied because of context, priority, or changeVal.
05151  *
05152  * If there is an error (non-existing option, invalid value) then an
05153  * ereport(ERROR) is thrown *unless* this is called for a source for which
05154  * we don't want an ERROR (currently, those are defaults, the config file,
05155  * and per-database or per-user settings, as well as callers who specify
05156  * a less-than-ERROR elevel).  In those cases we write a suitable error
05157  * message via ereport() and return 0.
05158  *
05159  * See also SetConfigOption for an external interface.
05160  */
05161 int
05162 set_config_option(const char *name, const char *value,
05163                   GucContext context, GucSource source,
05164                   GucAction action, bool changeVal, int elevel)
05165 {
05166     struct config_generic *record;
05167     bool        prohibitValueChange = false;
05168     bool        makeDefault;
05169 
05170     if (elevel == 0)
05171     {
05172         if (source == PGC_S_DEFAULT || source == PGC_S_FILE)
05173         {
05174             /*
05175              * To avoid cluttering the log, only the postmaster bleats loudly
05176              * about problems with the config file.
05177              */
05178             elevel = IsUnderPostmaster ? DEBUG3 : LOG;
05179         }
05180         else if (source == PGC_S_GLOBAL || source == PGC_S_DATABASE || source == PGC_S_USER ||
05181                  source == PGC_S_DATABASE_USER)
05182             elevel = WARNING;
05183         else
05184             elevel = ERROR;
05185     }
05186 
05187     record = find_option(name, true, elevel);
05188     if (record == NULL)
05189     {
05190         ereport(elevel,
05191                 (errcode(ERRCODE_UNDEFINED_OBJECT),
05192                errmsg("unrecognized configuration parameter \"%s\"", name)));
05193         return 0;
05194     }
05195 
05196     /*
05197      * Check if the option can be set at this time. See guc.h for the precise
05198      * rules.
05199      */
05200     switch (record->context)
05201     {
05202         case PGC_INTERNAL:
05203             if (context != PGC_INTERNAL)
05204             {
05205                 ereport(elevel,
05206                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05207                          errmsg("parameter \"%s\" cannot be changed",
05208                                 name)));
05209                 return 0;
05210             }
05211             break;
05212         case PGC_POSTMASTER:
05213             if (context == PGC_SIGHUP)
05214             {
05215                 /*
05216                  * We are re-reading a PGC_POSTMASTER variable from
05217                  * postgresql.conf.  We can't change the setting, so we should
05218                  * give a warning if the DBA tries to change it.  However,
05219                  * because of variant formats, canonicalization by check
05220                  * hooks, etc, we can't just compare the given string directly
05221                  * to what's stored.  Set a flag to check below after we have
05222                  * the final storable value.
05223                  */
05224                 prohibitValueChange = true;
05225             }
05226             else if (context != PGC_POSTMASTER)
05227             {
05228                 ereport(elevel,
05229                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05230                          errmsg("parameter \"%s\" cannot be changed without restarting the server",
05231                                 name)));
05232                 return 0;
05233             }
05234             break;
05235         case PGC_SIGHUP:
05236             if (context != PGC_SIGHUP && context != PGC_POSTMASTER)
05237             {
05238                 ereport(elevel,
05239                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05240                          errmsg("parameter \"%s\" cannot be changed now",
05241                                 name)));
05242                 return 0;
05243             }
05244 
05245             /*
05246              * Hmm, the idea of the SIGHUP context is "ought to be global, but
05247              * can be changed after postmaster start". But there's nothing
05248              * that prevents a crafty administrator from sending SIGHUP
05249              * signals to individual backends only.
05250              */
05251             break;
05252         case PGC_BACKEND:
05253             if (context == PGC_SIGHUP)
05254             {
05255                 /*
05256                  * If a PGC_BACKEND parameter is changed in the config file,
05257                  * we want to accept the new value in the postmaster (whence
05258                  * it will propagate to subsequently-started backends), but
05259                  * ignore it in existing backends.  This is a tad klugy, but
05260                  * necessary because we don't re-read the config file during
05261                  * backend start.
05262                  */
05263                 if (IsUnderPostmaster)
05264                     return -1;
05265             }
05266             else if (context != PGC_POSTMASTER && context != PGC_BACKEND &&
05267                      source != PGC_S_CLIENT)
05268             {
05269                 ereport(elevel,
05270                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05271                          errmsg("parameter \"%s\" cannot be set after connection start",
05272                                 name)));
05273                 return 0;
05274             }
05275             break;
05276         case PGC_SUSET:
05277             if (context == PGC_USERSET || context == PGC_BACKEND)
05278             {
05279                 ereport(elevel,
05280                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
05281                          errmsg("permission denied to set parameter \"%s\"",
05282                                 name)));
05283                 return 0;
05284             }
05285             break;
05286         case PGC_USERSET:
05287             /* always okay */
05288             break;
05289     }
05290 
05291     /*
05292      * Disallow changing GUC_NOT_WHILE_SEC_REST values if we are inside a
05293      * security restriction context.  We can reject this regardless of the GUC
05294      * context or source, mainly because sources that it might be reasonable
05295      * to override for won't be seen while inside a function.
05296      *
05297      * Note: variables marked GUC_NOT_WHILE_SEC_REST should usually be marked
05298      * GUC_NO_RESET_ALL as well, because ResetAllOptions() doesn't check this.
05299      * An exception might be made if the reset value is assumed to be "safe".
05300      *
05301      * Note: this flag is currently used for "session_authorization" and
05302      * "role".  We need to prohibit changing these inside a local userid
05303      * context because when we exit it, GUC won't be notified, leaving things
05304      * out of sync.  (This could be fixed by forcing a new GUC nesting level,
05305      * but that would change behavior in possibly-undesirable ways.)  Also, we
05306      * prohibit changing these in a security-restricted operation because
05307      * otherwise RESET could be used to regain the session user's privileges.
05308      */
05309     if (record->flags & GUC_NOT_WHILE_SEC_REST)
05310     {
05311         if (InLocalUserIdChange())
05312         {
05313             /*
05314              * Phrasing of this error message is historical, but it's the most
05315              * common case.
05316              */
05317             ereport(elevel,
05318                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
05319                      errmsg("cannot set parameter \"%s\" within security-definer function",
05320                             name)));
05321             return 0;
05322         }
05323         if (InSecurityRestrictedOperation())
05324         {
05325             ereport(elevel,
05326                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
05327                      errmsg("cannot set parameter \"%s\" within security-restricted operation",
05328                             name)));
05329             return 0;
05330         }
05331     }
05332 
05333     /*
05334      * Should we set reset/stacked values?  (If so, the behavior is not
05335      * transactional.)  This is done either when we get a default value from
05336      * the database's/user's/client's default settings or when we reset a
05337      * value to its default.
05338      */
05339     makeDefault = changeVal && (source <= PGC_S_OVERRIDE) &&
05340         ((value != NULL) || source == PGC_S_DEFAULT);
05341 
05342     /*
05343      * Ignore attempted set if overridden by previously processed setting.
05344      * However, if changeVal is false then plow ahead anyway since we are
05345      * trying to find out if the value is potentially good, not actually use
05346      * it. Also keep going if makeDefault is true, since we may want to set
05347      * the reset/stacked values even if we can't set the variable itself.
05348      */
05349     if (record->source > source)
05350     {
05351         if (changeVal && !makeDefault)
05352         {
05353             elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
05354                  name);
05355             return -1;
05356         }
05357         changeVal = false;
05358     }
05359 
05360     /*
05361      * Evaluate value and set variable.
05362      */
05363     switch (record->vartype)
05364     {
05365         case PGC_BOOL:
05366             {
05367                 struct config_bool *conf = (struct config_bool *) record;
05368                 bool        newval;
05369                 void       *newextra = NULL;
05370 
05371                 if (value)
05372                 {
05373                     if (!parse_bool(value, &newval))
05374                     {
05375                         ereport(elevel,
05376                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05377                           errmsg("parameter \"%s\" requires a Boolean value",
05378                                  name)));
05379                         return 0;
05380                     }
05381                     if (!call_bool_check_hook(conf, &newval, &newextra,
05382                                               source, elevel))
05383                         return 0;
05384                 }
05385                 else if (source == PGC_S_DEFAULT)
05386                 {
05387                     newval = conf->boot_val;
05388                     if (!call_bool_check_hook(conf, &newval, &newextra,
05389                                               source, elevel))
05390                         return 0;
05391                 }
05392                 else
05393                 {
05394                     newval = conf->reset_val;
05395                     newextra = conf->reset_extra;
05396                     source = conf->gen.reset_source;
05397                     context = conf->gen.reset_scontext;
05398                 }
05399 
05400                 if (prohibitValueChange)
05401                 {
05402                     if (*conf->variable != newval)
05403                     {
05404                         ereport(elevel,
05405                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05406                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
05407                                         name)));
05408                         return 0;
05409                     }
05410                     return -1;
05411                 }
05412 
05413                 if (changeVal)
05414                 {
05415                     /* Save old value to support transaction abort */
05416                     if (!makeDefault)
05417                         push_old_value(&conf->gen, action);
05418 
05419                     if (conf->assign_hook)
05420                         (*conf->assign_hook) (newval, newextra);
05421                     *conf->variable = newval;
05422                     set_extra_field(&conf->gen, &conf->gen.extra,
05423                                     newextra);
05424                     conf->gen.source = source;
05425                     conf->gen.scontext = context;
05426                 }
05427                 if (makeDefault)
05428                 {
05429                     GucStack   *stack;
05430 
05431                     if (conf->gen.reset_source <= source)
05432                     {
05433                         conf->reset_val = newval;
05434                         set_extra_field(&conf->gen, &conf->reset_extra,
05435                                         newextra);
05436                         conf->gen.reset_source = source;
05437                         conf->gen.reset_scontext = context;
05438                     }
05439                     for (stack = conf->gen.stack; stack; stack = stack->prev)
05440                     {
05441                         if (stack->source <= source)
05442                         {
05443                             stack->prior.val.boolval = newval;
05444                             set_extra_field(&conf->gen, &stack->prior.extra,
05445                                             newextra);
05446                             stack->source = source;
05447                             stack->scontext = context;
05448                         }
05449                     }
05450                 }
05451 
05452                 /* Perhaps we didn't install newextra anywhere */
05453                 if (newextra && !extra_field_used(&conf->gen, newextra))
05454                     free(newextra);
05455                 break;
05456             }
05457 
05458         case PGC_INT:
05459             {
05460                 struct config_int *conf = (struct config_int *) record;
05461                 int         newval;
05462                 void       *newextra = NULL;
05463 
05464                 if (value)
05465                 {
05466                     const char *hintmsg;
05467 
05468                     if (!parse_int(value, &newval, conf->gen.flags, &hintmsg))
05469                     {
05470                         ereport(elevel,
05471                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05472                          errmsg("invalid value for parameter \"%s\": \"%s\"",
05473                                 name, value),
05474                                  hintmsg ? errhint("%s", _(hintmsg)) : 0));
05475                         return 0;
05476                     }
05477                     if (newval < conf->min || newval > conf->max)
05478                     {
05479                         ereport(elevel,
05480                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05481                                  errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
05482                                         newval, name, conf->min, conf->max)));
05483                         return 0;
05484                     }
05485                     if (!call_int_check_hook(conf, &newval, &newextra,
05486                                              source, elevel))
05487                         return 0;
05488                 }
05489                 else if (source == PGC_S_DEFAULT)
05490                 {
05491                     newval = conf->boot_val;
05492                     if (!call_int_check_hook(conf, &newval, &newextra,
05493                                              source, elevel))
05494                         return 0;
05495                 }
05496                 else
05497                 {
05498                     newval = conf->reset_val;
05499                     newextra = conf->reset_extra;
05500                     source = conf->gen.reset_source;
05501                     context = conf->gen.reset_scontext;
05502                 }
05503 
05504                 if (prohibitValueChange)
05505                 {
05506                     if (*conf->variable != newval)
05507                     {
05508                         ereport(elevel,
05509                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05510                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
05511                                         name)));
05512                         return 0;
05513                     }
05514                     return -1;
05515                 }
05516 
05517                 if (changeVal)
05518                 {
05519                     /* Save old value to support transaction abort */
05520                     if (!makeDefault)
05521                         push_old_value(&conf->gen, action);
05522 
05523                     if (conf->assign_hook)
05524                         (*conf->assign_hook) (newval, newextra);
05525                     *conf->variable = newval;
05526                     set_extra_field(&conf->gen, &conf->gen.extra,
05527                                     newextra);
05528                     conf->gen.source = source;
05529                     conf->gen.scontext = context;
05530                 }
05531                 if (makeDefault)
05532                 {
05533                     GucStack   *stack;
05534 
05535                     if (conf->gen.reset_source <= source)
05536                     {
05537                         conf->reset_val = newval;
05538                         set_extra_field(&conf->gen, &conf->reset_extra,
05539                                         newextra);
05540                         conf->gen.reset_source = source;
05541                         conf->gen.reset_scontext = context;
05542                     }
05543                     for (stack = conf->gen.stack; stack; stack = stack->prev)
05544                     {
05545                         if (stack->source <= source)
05546                         {
05547                             stack->prior.val.intval = newval;
05548                             set_extra_field(&conf->gen, &stack->prior.extra,
05549                                             newextra);
05550                             stack->source = source;
05551                             stack->scontext = context;
05552                         }
05553                     }
05554                 }
05555 
05556                 /* Perhaps we didn't install newextra anywhere */
05557                 if (newextra && !extra_field_used(&conf->gen, newextra))
05558                     free(newextra);
05559                 break;
05560             }
05561 
05562         case PGC_REAL:
05563             {
05564                 struct config_real *conf = (struct config_real *) record;
05565                 double      newval;
05566                 void       *newextra = NULL;
05567 
05568                 if (value)
05569                 {
05570                     if (!parse_real(value, &newval))
05571                     {
05572                         ereport(elevel,
05573                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05574                           errmsg("parameter \"%s\" requires a numeric value",
05575                                  name)));
05576                         return 0;
05577                     }
05578                     if (newval < conf->min || newval > conf->max)
05579                     {
05580                         ereport(elevel,
05581                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05582                                  errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
05583                                         newval, name, conf->min, conf->max)));
05584                         return 0;
05585                     }
05586                     if (!call_real_check_hook(conf, &newval, &newextra,
05587                                               source, elevel))
05588                         return 0;
05589                 }
05590                 else if (source == PGC_S_DEFAULT)
05591                 {
05592                     newval = conf->boot_val;
05593                     if (!call_real_check_hook(conf, &newval, &newextra,
05594                                               source, elevel))
05595                         return 0;
05596                 }
05597                 else
05598                 {
05599                     newval = conf->reset_val;
05600                     newextra = conf->reset_extra;
05601                     source = conf->gen.reset_source;
05602                     context = conf->gen.reset_scontext;
05603                 }
05604 
05605                 if (prohibitValueChange)
05606                 {
05607                     if (*conf->variable != newval)
05608                     {
05609                         ereport(elevel,
05610                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05611                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
05612                                         name)));
05613                         return 0;
05614                     }
05615                     return -1;
05616                 }
05617 
05618                 if (changeVal)
05619                 {
05620                     /* Save old value to support transaction abort */
05621                     if (!makeDefault)
05622                         push_old_value(&conf->gen, action);
05623 
05624                     if (conf->assign_hook)
05625                         (*conf->assign_hook) (newval, newextra);
05626                     *conf->variable = newval;
05627                     set_extra_field(&conf->gen, &conf->gen.extra,
05628                                     newextra);
05629                     conf->gen.source = source;
05630                     conf->gen.scontext = context;
05631                 }
05632                 if (makeDefault)
05633                 {
05634                     GucStack   *stack;
05635 
05636                     if (conf->gen.reset_source <= source)
05637                     {
05638                         conf->reset_val = newval;
05639                         set_extra_field(&conf->gen, &conf->reset_extra,
05640                                         newextra);
05641                         conf->gen.reset_source = source;
05642                         conf->gen.reset_scontext = context;
05643                     }
05644                     for (stack = conf->gen.stack; stack; stack = stack->prev)
05645                     {
05646                         if (stack->source <= source)
05647                         {
05648                             stack->prior.val.realval = newval;
05649                             set_extra_field(&conf->gen, &stack->prior.extra,
05650                                             newextra);
05651                             stack->source = source;
05652                             stack->scontext = context;
05653                         }
05654                     }
05655                 }
05656 
05657                 /* Perhaps we didn't install newextra anywhere */
05658                 if (newextra && !extra_field_used(&conf->gen, newextra))
05659                     free(newextra);
05660                 break;
05661             }
05662 
05663         case PGC_STRING:
05664             {
05665                 struct config_string *conf = (struct config_string *) record;
05666                 char       *newval;
05667                 void       *newextra = NULL;
05668 
05669                 if (value)
05670                 {
05671                     /*
05672                      * The value passed by the caller could be transient, so
05673                      * we always strdup it.
05674                      */
05675                     newval = guc_strdup(elevel, value);
05676                     if (newval == NULL)
05677                         return 0;
05678 
05679                     /*
05680                      * The only built-in "parsing" check we have is to apply
05681                      * truncation if GUC_IS_NAME.
05682                      */
05683                     if (conf->gen.flags & GUC_IS_NAME)
05684                         truncate_identifier(newval, strlen(newval), true);
05685 
05686                     if (!call_string_check_hook(conf, &newval, &newextra,
05687                                                 source, elevel))
05688                     {
05689                         free(newval);
05690                         return 0;
05691                     }
05692                 }
05693                 else if (source == PGC_S_DEFAULT)
05694                 {
05695                     /* non-NULL boot_val must always get strdup'd */
05696                     if (conf->boot_val != NULL)
05697                     {
05698                         newval = guc_strdup(elevel, conf->boot_val);
05699                         if (newval == NULL)
05700                             return 0;
05701                     }
05702                     else
05703                         newval = NULL;
05704 
05705                     if (!call_string_check_hook(conf, &newval, &newextra,
05706                                                 source, elevel))
05707                     {
05708                         free(newval);
05709                         return 0;
05710                     }
05711                 }
05712                 else
05713                 {
05714                     /*
05715                      * strdup not needed, since reset_val is already under
05716                      * guc.c's control
05717                      */
05718                     newval = conf->reset_val;
05719                     newextra = conf->reset_extra;
05720                     source = conf->gen.reset_source;
05721                     context = conf->gen.reset_scontext;
05722                 }
05723 
05724                 if (prohibitValueChange)
05725                 {
05726                     /* newval shouldn't be NULL, so we're a bit sloppy here */
05727                     if (*conf->variable == NULL || newval == NULL ||
05728                         strcmp(*conf->variable, newval) != 0)
05729                     {
05730                         ereport(elevel,
05731                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05732                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
05733                                         name)));
05734                         return 0;
05735                     }
05736                     return -1;
05737                 }
05738 
05739                 if (changeVal)
05740                 {
05741                     /* Save old value to support transaction abort */
05742                     if (!makeDefault)
05743                         push_old_value(&conf->gen, action);
05744 
05745                     if (conf->assign_hook)
05746                         (*conf->assign_hook) (newval, newextra);
05747                     set_string_field(conf, conf->variable, newval);
05748                     set_extra_field(&conf->gen, &conf->gen.extra,
05749                                     newextra);
05750                     conf->gen.source = source;
05751                     conf->gen.scontext = context;
05752                 }
05753 
05754                 if (makeDefault)
05755                 {
05756                     GucStack   *stack;
05757 
05758                     if (conf->gen.reset_source <= source)
05759                     {
05760                         set_string_field(conf, &conf->reset_val, newval);
05761                         set_extra_field(&conf->gen, &conf->reset_extra,
05762                                         newextra);
05763                         conf->gen.reset_source = source;
05764                         conf->gen.reset_scontext = context;
05765                     }
05766                     for (stack = conf->gen.stack; stack; stack = stack->prev)
05767                     {
05768                         if (stack->source <= source)
05769                         {
05770                             set_string_field(conf, &stack->prior.val.stringval,
05771                                              newval);
05772                             set_extra_field(&conf->gen, &stack->prior.extra,
05773                                             newextra);
05774                             stack->source = source;
05775                             stack->scontext = context;
05776                         }
05777                     }
05778                 }
05779 
05780                 /* Perhaps we didn't install newval anywhere */
05781                 if (newval && !string_field_used(conf, newval))
05782                     free(newval);
05783                 /* Perhaps we didn't install newextra anywhere */
05784                 if (newextra && !extra_field_used(&conf->gen, newextra))
05785                     free(newextra);
05786                 break;
05787             }
05788 
05789         case PGC_ENUM:
05790             {
05791                 struct config_enum *conf = (struct config_enum *) record;
05792                 int         newval;
05793                 void       *newextra = NULL;
05794 
05795                 if (value)
05796                 {
05797                     if (!config_enum_lookup_by_name(conf, value, &newval))
05798                     {
05799                         char       *hintmsg;
05800 
05801                         hintmsg = config_enum_get_options(conf,
05802                                                         "Available values: ",
05803                                                           ".", ", ");
05804 
05805                         ereport(elevel,
05806                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05807                          errmsg("invalid value for parameter \"%s\": \"%s\"",
05808                                 name, value),
05809                                  hintmsg ? errhint("%s", _(hintmsg)) : 0));
05810 
05811                         if (hintmsg)
05812                             pfree(hintmsg);
05813                         return 0;
05814                     }
05815                     if (!call_enum_check_hook(conf, &newval, &newextra,
05816                                               source, elevel))
05817                         return 0;
05818                 }
05819                 else if (source == PGC_S_DEFAULT)
05820                 {
05821                     newval = conf->boot_val;
05822                     if (!call_enum_check_hook(conf, &newval, &newextra,
05823                                               source, elevel))
05824                         return 0;
05825                 }
05826                 else
05827                 {
05828                     newval = conf->reset_val;
05829                     newextra = conf->reset_extra;
05830                     source = conf->gen.reset_source;
05831                     context = conf->gen.reset_scontext;
05832                 }
05833 
05834                 if (prohibitValueChange)
05835                 {
05836                     if (*conf->variable != newval)
05837                     {
05838                         ereport(elevel,
05839                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
05840                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
05841                                         name)));
05842                         return 0;
05843                     }
05844                     return -1;
05845                 }
05846 
05847                 if (changeVal)
05848                 {
05849                     /* Save old value to support transaction abort */
05850                     if (!makeDefault)
05851                         push_old_value(&conf->gen, action);
05852 
05853                     if (conf->assign_hook)
05854                         (*conf->assign_hook) (newval, newextra);
05855                     *conf->variable = newval;
05856                     set_extra_field(&conf->gen, &conf->gen.extra,
05857                                     newextra);
05858                     conf->gen.source = source;
05859                     conf->gen.scontext = context;
05860                 }
05861                 if (makeDefault)
05862                 {
05863                     GucStack   *stack;
05864 
05865                     if (conf->gen.reset_source <= source)
05866                     {
05867                         conf->reset_val = newval;
05868                         set_extra_field(&conf->gen, &conf->reset_extra,
05869                                         newextra);
05870                         conf->gen.reset_source = source;
05871                         conf->gen.reset_scontext = context;
05872                     }
05873                     for (stack = conf->gen.stack; stack; stack = stack->prev)
05874                     {
05875                         if (stack->source <= source)
05876                         {
05877                             stack->prior.val.enumval = newval;
05878                             set_extra_field(&conf->gen, &stack->prior.extra,
05879                                             newextra);
05880                             stack->source = source;
05881                             stack->scontext = context;
05882                         }
05883                     }
05884                 }
05885 
05886                 /* Perhaps we didn't install newextra anywhere */
05887                 if (newextra && !extra_field_used(&conf->gen, newextra))
05888                     free(newextra);
05889                 break;
05890             }
05891     }
05892 
05893     if (changeVal && (record->flags & GUC_REPORT))
05894         ReportGUCOption(record);
05895 
05896     return changeVal ? 1 : -1;
05897 }
05898 
05899 
05900 /*
05901  * Set the fields for source file and line number the setting came from.
05902  */
05903 static void
05904 set_config_sourcefile(const char *name, char *sourcefile, int sourceline)
05905 {
05906     struct config_generic *record;
05907     int         elevel;
05908 
05909     /*
05910      * To avoid cluttering the log, only the postmaster bleats loudly about
05911      * problems with the config file.
05912      */
05913     elevel = IsUnderPostmaster ? DEBUG3 : LOG;
05914 
05915     record = find_option(name, true, elevel);
05916     /* should not happen */
05917     if (record == NULL)
05918         elog(ERROR, "unrecognized configuration parameter \"%s\"", name);
05919 
05920     sourcefile = guc_strdup(elevel, sourcefile);
05921     if (record->sourcefile)
05922         free(record->sourcefile);
05923     record->sourcefile = sourcefile;
05924     record->sourceline = sourceline;
05925 }
05926 
05927 /*
05928  * Set a config option to the given value.
05929  *
05930  * See also set_config_option; this is just the wrapper to be called from
05931  * outside GUC.  (This function should be used when possible, because its API
05932  * is more stable than set_config_option's.)
05933  *
05934  * Note: there is no support here for setting source file/line, as it
05935  * is currently not needed.
05936  */
05937 void
05938 SetConfigOption(const char *name, const char *value,
05939                 GucContext context, GucSource source)
05940 {
05941     (void) set_config_option(name, value, context, source,
05942                              GUC_ACTION_SET, true, 0);
05943 }
05944 
05945 
05946 
05947 /*
05948  * Fetch the current value of the option `name', as a string.
05949  *
05950  * If the option doesn't exist, return NULL if missing_ok is true (NOTE that
05951  * this cannot be distinguished from a string variable with a NULL value!),
05952  * otherwise throw an ereport and don't return.
05953  *
05954  * If restrict_superuser is true, we also enforce that only superusers can
05955  * see GUC_SUPERUSER_ONLY variables.  This should only be passed as true
05956  * in user-driven calls.
05957  *
05958  * The string is *not* allocated for modification and is really only
05959  * valid until the next call to configuration related functions.
05960  */
05961 const char *
05962 GetConfigOption(const char *name, bool missing_ok, bool restrict_superuser)
05963 {
05964     struct config_generic *record;
05965     static char buffer[256];
05966 
05967     record = find_option(name, false, ERROR);
05968     if (record == NULL)
05969     {
05970         if (missing_ok)
05971             return NULL;
05972         ereport(ERROR,
05973                 (errcode(ERRCODE_UNDEFINED_OBJECT),
05974                  errmsg("unrecognized configuration parameter \"%s\"",
05975                         name)));
05976     }
05977     if (restrict_superuser &&
05978         (record->flags & GUC_SUPERUSER_ONLY) &&
05979         !superuser())
05980         ereport(ERROR,
05981                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
05982                  errmsg("must be superuser to examine \"%s\"", name)));
05983 
05984     switch (record->vartype)
05985     {
05986         case PGC_BOOL:
05987             return *((struct config_bool *) record)->variable ? "on" : "off";
05988 
05989         case PGC_INT:
05990             snprintf(buffer, sizeof(buffer), "%d",
05991                      *((struct config_int *) record)->variable);
05992             return buffer;
05993 
05994         case PGC_REAL:
05995             snprintf(buffer, sizeof(buffer), "%g",
05996                      *((struct config_real *) record)->variable);
05997             return buffer;
05998 
05999         case PGC_STRING:
06000             return *((struct config_string *) record)->variable;
06001 
06002         case PGC_ENUM:
06003             return config_enum_lookup_by_value((struct config_enum *) record,
06004                                  *((struct config_enum *) record)->variable);
06005     }
06006     return NULL;
06007 }
06008 
06009 /*
06010  * Get the RESET value associated with the given option.
06011  *
06012  * Note: this is not re-entrant, due to use of static result buffer;
06013  * not to mention that a string variable could have its reset_val changed.
06014  * Beware of assuming the result value is good for very long.
06015  */
06016 const char *
06017 GetConfigOptionResetString(const char *name)
06018 {
06019     struct config_generic *record;
06020     static char buffer[256];
06021 
06022     record = find_option(name, false, ERROR);
06023     if (record == NULL)
06024         ereport(ERROR,
06025                 (errcode(ERRCODE_UNDEFINED_OBJECT),
06026                errmsg("unrecognized configuration parameter \"%s\"", name)));
06027     if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
06028         ereport(ERROR,
06029                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
06030                  errmsg("must be superuser to examine \"%s\"", name)));
06031 
06032     switch (record->vartype)
06033     {
06034         case PGC_BOOL:
06035             return ((struct config_bool *) record)->reset_val ? "on" : "off";
06036 
06037         case PGC_INT:
06038             snprintf(buffer, sizeof(buffer), "%d",
06039                      ((struct config_int *) record)->reset_val);
06040             return buffer;
06041 
06042         case PGC_REAL:
06043             snprintf(buffer, sizeof(buffer), "%g",
06044                      ((struct config_real *) record)->reset_val);
06045             return buffer;
06046 
06047         case PGC_STRING:
06048             return ((struct config_string *) record)->reset_val;
06049 
06050         case PGC_ENUM:
06051             return config_enum_lookup_by_value((struct config_enum *) record,
06052                                  ((struct config_enum *) record)->reset_val);
06053     }
06054     return NULL;
06055 }
06056 
06057 
06058 /*
06059  * flatten_set_variable_args
06060  *      Given a parsenode List as emitted by the grammar for SET,
06061  *      convert to the flat string representation used by GUC.
06062  *
06063  * We need to be told the name of the variable the args are for, because
06064  * the flattening rules vary (ugh).
06065  *
06066  * The result is NULL if args is NIL (ie, SET ... TO DEFAULT), otherwise
06067  * a palloc'd string.
06068  */
06069 static char *
06070 flatten_set_variable_args(const char *name, List *args)
06071 {
06072     struct config_generic *record;
06073     int         flags;
06074     StringInfoData buf;
06075     ListCell   *l;
06076 
06077     /* Fast path if just DEFAULT */
06078     if (args == NIL)
06079         return NULL;
06080 
06081     /*
06082      * Get flags for the variable; if it's not known, use default flags.
06083      * (Caller might throw error later, but not our business to do so here.)
06084      */
06085     record = find_option(name, false, WARNING);
06086     if (record)
06087         flags = record->flags;
06088     else
06089         flags = 0;
06090 
06091     /* Complain if list input and non-list variable */
06092     if ((flags & GUC_LIST_INPUT) == 0 &&
06093         list_length(args) != 1)
06094         ereport(ERROR,
06095                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
06096                  errmsg("SET %s takes only one argument", name)));
06097 
06098     initStringInfo(&buf);
06099 
06100     /*
06101      * Each list member may be a plain A_Const node, or an A_Const within a
06102      * TypeCast; the latter case is supported only for ConstInterval arguments
06103      * (for SET TIME ZONE).
06104      */
06105     foreach(l, args)
06106     {
06107         Node       *arg = (Node *) lfirst(l);
06108         char       *val;
06109         TypeName   *typeName = NULL;
06110         A_Const    *con;
06111 
06112         if (l != list_head(args))
06113             appendStringInfo(&buf, ", ");
06114 
06115         if (IsA(arg, TypeCast))
06116         {
06117             TypeCast   *tc = (TypeCast *) arg;
06118 
06119             arg = tc->arg;
06120             typeName = tc->typeName;
06121         }
06122 
06123         if (!IsA(arg, A_Const))
06124             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
06125         con = (A_Const *) arg;
06126 
06127         switch (nodeTag(&con->val))
06128         {
06129             case T_Integer:
06130                 appendStringInfo(&buf, "%ld", intVal(&con->val));
06131                 break;
06132             case T_Float:
06133                 /* represented as a string, so just copy it */
06134                 appendStringInfoString(&buf, strVal(&con->val));
06135                 break;
06136             case T_String:
06137                 val = strVal(&con->val);
06138                 if (typeName != NULL)
06139                 {
06140                     /*
06141                      * Must be a ConstInterval argument for TIME ZONE. Coerce
06142                      * to interval and back to normalize the value and account
06143                      * for any typmod.
06144                      */
06145                     Oid         typoid;
06146                     int32       typmod;
06147                     Datum       interval;
06148                     char       *intervalout;
06149 
06150                     typenameTypeIdAndMod(NULL, typeName, &typoid, &typmod);
06151                     Assert(typoid == INTERVALOID);
06152 
06153                     interval =
06154                         DirectFunctionCall3(interval_in,
06155                                             CStringGetDatum(val),
06156                                             ObjectIdGetDatum(InvalidOid),
06157                                             Int32GetDatum(typmod));
06158 
06159                     intervalout =
06160                         DatumGetCString(DirectFunctionCall1(interval_out,
06161                                                             interval));
06162                     appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
06163                 }
06164                 else
06165                 {
06166                     /*
06167                      * Plain string literal or identifier.  For quote mode,
06168                      * quote it if it's not a vanilla identifier.
06169                      */
06170                     if (flags & GUC_LIST_QUOTE)
06171                         appendStringInfoString(&buf, quote_identifier(val));
06172                     else
06173                         appendStringInfoString(&buf, val);
06174                 }
06175                 break;
06176             default:
06177                 elog(ERROR, "unrecognized node type: %d",
06178                      (int) nodeTag(&con->val));
06179                 break;
06180         }
06181     }
06182 
06183     return buf.data;
06184 }
06185 
06186 
06187 /*
06188  * SET command
06189  */
06190 void
06191 ExecSetVariableStmt(VariableSetStmt *stmt)
06192 {
06193     GucAction   action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
06194 
06195     switch (stmt->kind)
06196     {
06197         case VAR_SET_VALUE:
06198         case VAR_SET_CURRENT:
06199             (void) set_config_option(stmt->name,
06200                                      ExtractSetVariableArgs(stmt),
06201                                      (superuser() ? PGC_SUSET : PGC_USERSET),
06202                                      PGC_S_SESSION,
06203                                      action,
06204                                      true,
06205                                      0);
06206             break;
06207         case VAR_SET_MULTI:
06208 
06209             /*
06210              * Special-case SQL syntaxes.  The TRANSACTION and SESSION
06211              * CHARACTERISTICS cases effectively set more than one variable
06212              * per statement.  TRANSACTION SNAPSHOT only takes one argument,
06213              * but we put it here anyway since it's a special case and not
06214              * related to any GUC variable.
06215              */
06216             if (strcmp(stmt->name, "TRANSACTION") == 0)
06217             {
06218                 ListCell   *head;
06219 
06220                 foreach(head, stmt->args)
06221                 {
06222                     DefElem    *item = (DefElem *) lfirst(head);
06223 
06224                     if (strcmp(item->defname, "transaction_isolation") == 0)
06225                         SetPGVariable("transaction_isolation",
06226                                       list_make1(item->arg), stmt->is_local);
06227                     else if (strcmp(item->defname, "transaction_read_only") == 0)
06228                         SetPGVariable("transaction_read_only",
06229                                       list_make1(item->arg), stmt->is_local);
06230                     else if (strcmp(item->defname, "transaction_deferrable") == 0)
06231                         SetPGVariable("transaction_deferrable",
06232                                       list_make1(item->arg), stmt->is_local);
06233                     else
06234                         elog(ERROR, "unexpected SET TRANSACTION element: %s",
06235                              item->defname);
06236                 }
06237             }
06238             else if (strcmp(stmt->name, "SESSION CHARACTERISTICS") == 0)
06239             {
06240                 ListCell   *head;
06241 
06242                 foreach(head, stmt->args)
06243                 {
06244                     DefElem    *item = (DefElem *) lfirst(head);
06245 
06246                     if (strcmp(item->defname, "transaction_isolation") == 0)
06247                         SetPGVariable("default_transaction_isolation",
06248                                       list_make1(item->arg), stmt->is_local);
06249                     else if (strcmp(item->defname, "transaction_read_only") == 0)
06250                         SetPGVariable("default_transaction_read_only",
06251                                       list_make1(item->arg), stmt->is_local);
06252                     else if (strcmp(item->defname, "transaction_deferrable") == 0)
06253                         SetPGVariable("default_transaction_deferrable",
06254                                       list_make1(item->arg), stmt->is_local);
06255                     else
06256                         elog(ERROR, "unexpected SET SESSION element: %s",
06257                              item->defname);
06258                 }
06259             }
06260             else if (strcmp(stmt->name, "TRANSACTION SNAPSHOT") == 0)
06261             {
06262                 A_Const    *con = (A_Const *) linitial(stmt->args);
06263 
06264                 if (stmt->is_local)
06265                     ereport(ERROR,
06266                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
06267                              errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
06268                 Assert(IsA(con, A_Const));
06269                 Assert(nodeTag(&con->val) == T_String);
06270                 ImportSnapshot(strVal(&con->val));
06271             }
06272             else
06273                 elog(ERROR, "unexpected SET MULTI element: %s",
06274                      stmt->name);
06275             break;
06276         case VAR_SET_DEFAULT:
06277         case VAR_RESET:
06278             (void) set_config_option(stmt->name,
06279                                      NULL,
06280                                      (superuser() ? PGC_SUSET : PGC_USERSET),
06281                                      PGC_S_SESSION,
06282                                      action,
06283                                      true,
06284                                      0);
06285             break;
06286         case VAR_RESET_ALL:
06287             ResetAllOptions();
06288             break;
06289     }
06290 }
06291 
06292 /*
06293  * Get the value to assign for a VariableSetStmt, or NULL if it's RESET.
06294  * The result is palloc'd.
06295  *
06296  * This is exported for use by actions such as ALTER ROLE SET.
06297  */
06298 char *
06299 ExtractSetVariableArgs(VariableSetStmt *stmt)
06300 {
06301     switch (stmt->kind)
06302     {
06303         case VAR_SET_VALUE:
06304             return flatten_set_variable_args(stmt->name, stmt->args);
06305         case VAR_SET_CURRENT:
06306             return GetConfigOptionByName(stmt->name, NULL);
06307         default:
06308             return NULL;
06309     }
06310 }
06311 
06312 /*
06313  * SetPGVariable - SET command exported as an easily-C-callable function.
06314  *
06315  * This provides access to SET TO value, as well as SET TO DEFAULT (expressed
06316  * by passing args == NIL), but not SET FROM CURRENT functionality.
06317  */
06318 void
06319 SetPGVariable(const char *name, List *args, bool is_local)
06320 {
06321     char       *argstring = flatten_set_variable_args(name, args);
06322 
06323     /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
06324     (void) set_config_option(name,
06325                              argstring,
06326                              (superuser() ? PGC_SUSET : PGC_USERSET),
06327                              PGC_S_SESSION,
06328                              is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
06329                              true,
06330                              0);
06331 }
06332 
06333 /*
06334  * SET command wrapped as a SQL callable function.
06335  */
06336 Datum
06337 set_config_by_name(PG_FUNCTION_ARGS)
06338 {
06339     char       *name;
06340     char       *value;
06341     char       *new_value;
06342     bool        is_local;
06343 
06344     if (PG_ARGISNULL(0))
06345         ereport(ERROR,
06346                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
06347                  errmsg("SET requires parameter name")));
06348 
06349     /* Get the GUC variable name */
06350     name = TextDatumGetCString(PG_GETARG_DATUM(0));
06351 
06352     /* Get the desired value or set to NULL for a reset request */
06353     if (PG_ARGISNULL(1))
06354         value = NULL;
06355     else
06356         value = TextDatumGetCString(PG_GETARG_DATUM(1));
06357 
06358     /*
06359      * Get the desired state of is_local. Default to false if provided value
06360      * is NULL
06361      */
06362     if (PG_ARGISNULL(2))
06363         is_local = false;
06364     else
06365         is_local = PG_GETARG_BOOL(2);
06366 
06367     /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
06368     (void) set_config_option(name,
06369                              value,
06370                              (superuser() ? PGC_SUSET : PGC_USERSET),
06371                              PGC_S_SESSION,
06372                              is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
06373                              true,
06374                              0);
06375 
06376     /* get the new current value */
06377     new_value = GetConfigOptionByName(name, NULL);
06378 
06379     /* Convert return string to text */
06380     PG_RETURN_TEXT_P(cstring_to_text(new_value));
06381 }
06382 
06383 
06384 /*
06385  * Common code for DefineCustomXXXVariable subroutines: allocate the
06386  * new variable's config struct and fill in generic fields.
06387  */
06388 static struct config_generic *
06389 init_custom_variable(const char *name,
06390                      const char *short_desc,
06391                      const char *long_desc,
06392                      GucContext context,
06393                      int flags,
06394                      enum config_type type,
06395                      size_t sz)
06396 {
06397     struct config_generic *gen;
06398 
06399     /*
06400      * Only allow custom PGC_POSTMASTER variables to be created during shared
06401      * library preload; any later than that, we can't ensure that the value
06402      * doesn't change after startup.  This is a fatal elog if it happens; just
06403      * erroring out isn't safe because we don't know what the calling loadable
06404      * module might already have hooked into.
06405      */
06406     if (context == PGC_POSTMASTER &&
06407         !process_shared_preload_libraries_in_progress)
06408         elog(FATAL, "cannot create PGC_POSTMASTER variables after startup");
06409 
06410     gen = (struct config_generic *) guc_malloc(ERROR, sz);
06411     memset(gen, 0, sz);
06412 
06413     gen->name = guc_strdup(ERROR, name);
06414     gen->context = context;
06415     gen->group = CUSTOM_OPTIONS;
06416     gen->short_desc = short_desc;
06417     gen->long_desc = long_desc;
06418     gen->flags = flags;
06419     gen->vartype = type;
06420 
06421     return gen;
06422 }
06423 
06424 /*
06425  * Common code for DefineCustomXXXVariable subroutines: insert the new
06426  * variable into the GUC variable array, replacing any placeholder.
06427  */
06428 static void
06429 define_custom_variable(struct config_generic * variable)
06430 {
06431     const char *name = variable->name;
06432     const char **nameAddr = &name;
06433     struct config_string *pHolder;
06434     struct config_generic **res;
06435 
06436     /*
06437      * See if there's a placeholder by the same name.
06438      */
06439     res = (struct config_generic **) bsearch((void *) &nameAddr,
06440                                              (void *) guc_variables,
06441                                              num_guc_variables,
06442                                              sizeof(struct config_generic *),
06443                                              guc_var_compare);
06444     if (res == NULL)
06445     {
06446         /*
06447          * No placeholder to replace, so we can just add it ... but first,
06448          * make sure it's initialized to its default value.
06449          */
06450         InitializeOneGUCOption(variable);
06451         add_guc_variable(variable, ERROR);
06452         return;
06453     }
06454 
06455     /*
06456      * This better be a placeholder
06457      */
06458     if (((*res)->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
06459         ereport(ERROR,
06460                 (errcode(ERRCODE_INTERNAL_ERROR),
06461                  errmsg("attempt to redefine parameter \"%s\"", name)));
06462 
06463     Assert((*res)->vartype == PGC_STRING);
06464     pHolder = (struct config_string *) (*res);
06465 
06466     /*
06467      * First, set the variable to its default value.  We must do this even
06468      * though we intend to immediately apply a new value, since it's possible
06469      * that the new value is invalid.
06470      */
06471     InitializeOneGUCOption(variable);
06472 
06473     /*
06474      * Replace the placeholder. We aren't changing the name, so no re-sorting
06475      * is necessary
06476      */
06477     *res = variable;
06478 
06479     /*
06480      * Assign the string value(s) stored in the placeholder to the real
06481      * variable.  Essentially, we need to duplicate all the active and stacked
06482      * values, but with appropriate validation and datatype adjustment.
06483      *
06484      * If an assignment fails, we report a WARNING and keep going.  We don't
06485      * want to throw ERROR for bad values, because it'd bollix the add-on
06486      * module that's presumably halfway through getting loaded.  In such cases
06487      * the default or previous state will become active instead.
06488      */
06489 
06490     /* First, apply the reset value if any */
06491     if (pHolder->reset_val)
06492         (void) set_config_option(name, pHolder->reset_val,
06493                                  pHolder->gen.reset_scontext,
06494                                  pHolder->gen.reset_source,
06495                                  GUC_ACTION_SET, true, WARNING);
06496     /* That should not have resulted in stacking anything */
06497     Assert(variable->stack == NULL);
06498 
06499     /* Now, apply current and stacked values, in the order they were stacked */
06500     reapply_stacked_values(variable, pHolder, pHolder->gen.stack,
06501                            *(pHolder->variable),
06502                            pHolder->gen.scontext, pHolder->gen.source);
06503 
06504     /* Also copy over any saved source-location information */
06505     if (pHolder->gen.sourcefile)
06506         set_config_sourcefile(name, pHolder->gen.sourcefile,
06507                               pHolder->gen.sourceline);
06508 
06509     /*
06510      * Free up as much as we conveniently can of the placeholder structure.
06511      * (This neglects any stack items, so it's possible for some memory to be
06512      * leaked.  Since this can only happen once per session per variable, it
06513      * doesn't seem worth spending much code on.)
06514      */
06515     set_string_field(pHolder, pHolder->variable, NULL);
06516     set_string_field(pHolder, &pHolder->reset_val, NULL);
06517 
06518     free(pHolder);
06519 }
06520 
06521 /*
06522  * Recursive subroutine for define_custom_variable: reapply non-reset values
06523  *
06524  * We recurse so that the values are applied in the same order as originally.
06525  * At each recursion level, apply the upper-level value (passed in) in the
06526  * fashion implied by the stack entry.
06527  */
06528 static void
06529 reapply_stacked_values(struct config_generic * variable,
06530                        struct config_string * pHolder,
06531                        GucStack *stack,
06532                        const char *curvalue,
06533                        GucContext curscontext, GucSource cursource)
06534 {
06535     const char *name = variable->name;
06536     GucStack   *oldvarstack = variable->stack;
06537 
06538     if (stack != NULL)
06539     {
06540         /* First, recurse, so that stack items are processed bottom to top */
06541         reapply_stacked_values(variable, pHolder, stack->prev,
06542                                stack->prior.val.stringval,
06543                                stack->scontext, stack->source);
06544 
06545         /* See how to apply the passed-in value */
06546         switch (stack->state)
06547         {
06548             case GUC_SAVE:
06549                 (void) set_config_option(name, curvalue,
06550                                          curscontext, cursource,
06551                                          GUC_ACTION_SAVE, true, WARNING);
06552                 break;
06553 
06554             case GUC_SET:
06555                 (void) set_config_option(name, curvalue,
06556                                          curscontext, cursource,
06557                                          GUC_ACTION_SET, true, WARNING);
06558                 break;
06559 
06560             case GUC_LOCAL:
06561                 (void) set_config_option(name, curvalue,
06562                                          curscontext, cursource,
06563                                          GUC_ACTION_LOCAL, true, WARNING);
06564                 break;
06565 
06566             case GUC_SET_LOCAL:
06567                 /* first, apply the masked value as SET */
06568                 (void) set_config_option(name, stack->masked.val.stringval,
06569                                        stack->masked_scontext, PGC_S_SESSION,
06570                                          GUC_ACTION_SET, true, WARNING);
06571                 /* then apply the current value as LOCAL */
06572                 (void) set_config_option(name, curvalue,
06573                                          curscontext, cursource,
06574                                          GUC_ACTION_LOCAL, true, WARNING);
06575                 break;
06576         }
06577 
06578         /* If we successfully made a stack entry, adjust its nest level */
06579         if (variable->stack != oldvarstack)
06580             variable->stack->nest_level = stack->nest_level;
06581     }
06582     else
06583     {
06584         /*
06585          * We are at the end of the stack.  If the active/previous value is
06586          * different from the reset value, it must represent a previously
06587          * committed session value.  Apply it, and then drop the stack entry
06588          * that set_config_option will have created under the impression that
06589          * this is to be just a transactional assignment.  (We leak the stack
06590          * entry.)
06591          */
06592         if (curvalue != pHolder->reset_val ||
06593             curscontext != pHolder->gen.reset_scontext ||
06594             cursource != pHolder->gen.reset_source)
06595         {
06596             (void) set_config_option(name, curvalue,
06597                                      curscontext, cursource,
06598                                      GUC_ACTION_SET, true, WARNING);
06599             variable->stack = NULL;
06600         }
06601     }
06602 }
06603 
06604 void
06605 DefineCustomBoolVariable(const char *name,
06606                          const char *short_desc,
06607                          const char *long_desc,
06608                          bool *valueAddr,
06609                          bool bootValue,
06610                          GucContext context,
06611                          int flags,
06612                          GucBoolCheckHook check_hook,
06613                          GucBoolAssignHook assign_hook,
06614                          GucShowHook show_hook)
06615 {
06616     struct config_bool *var;
06617 
06618     var = (struct config_bool *)
06619         init_custom_variable(name, short_desc, long_desc, context, flags,
06620                              PGC_BOOL, sizeof(struct config_bool));
06621     var->variable = valueAddr;
06622     var->boot_val = bootValue;
06623     var->reset_val = bootValue;
06624     var->check_hook = check_hook;
06625     var->assign_hook = assign_hook;
06626     var->show_hook = show_hook;
06627     define_custom_variable(&var->gen);
06628 }
06629 
06630 void
06631 DefineCustomIntVariable(const char *name,
06632                         const char *short_desc,
06633                         const char *long_desc,
06634                         int *valueAddr,
06635                         int bootValue,
06636                         int minValue,
06637                         int maxValue,
06638                         GucContext context,
06639                         int flags,
06640                         GucIntCheckHook check_hook,
06641                         GucIntAssignHook assign_hook,
06642                         GucShowHook show_hook)
06643 {
06644     struct config_int *var;
06645 
06646     var = (struct config_int *)
06647         init_custom_variable(name, short_desc, long_desc, context, flags,
06648                              PGC_INT, sizeof(struct config_int));
06649     var->variable = valueAddr;
06650     var->boot_val = bootValue;
06651     var->reset_val = bootValue;
06652     var->min = minValue;
06653     var->max = maxValue;
06654     var->check_hook = check_hook;
06655     var->assign_hook = assign_hook;
06656     var->show_hook = show_hook;
06657     define_custom_variable(&var->gen);
06658 }
06659 
06660 void
06661 DefineCustomRealVariable(const char *name,
06662                          const char *short_desc,
06663                          const char *long_desc,
06664                          double *valueAddr,
06665                          double bootValue,
06666                          double minValue,
06667                          double maxValue,
06668                          GucContext context,
06669                          int flags,
06670                          GucRealCheckHook check_hook,
06671                          GucRealAssignHook assign_hook,
06672                          GucShowHook show_hook)
06673 {
06674     struct config_real *var;
06675 
06676     var = (struct config_real *)
06677         init_custom_variable(name, short_desc, long_desc, context, flags,
06678                              PGC_REAL, sizeof(struct config_real));
06679     var->variable = valueAddr;
06680     var->boot_val = bootValue;
06681     var->reset_val = bootValue;
06682     var->min = minValue;
06683     var->max = maxValue;
06684     var->check_hook = check_hook;
06685     var->assign_hook = assign_hook;
06686     var->show_hook = show_hook;
06687     define_custom_variable(&var->gen);
06688 }
06689 
06690 void
06691 DefineCustomStringVariable(const char *name,
06692                            const char *short_desc,
06693                            const char *long_desc,
06694                            char **valueAddr,
06695                            const char *bootValue,
06696                            GucContext context,
06697                            int flags,
06698                            GucStringCheckHook check_hook,
06699                            GucStringAssignHook assign_hook,
06700                            GucShowHook show_hook)
06701 {
06702     struct config_string *var;
06703 
06704     var = (struct config_string *)
06705         init_custom_variable(name, short_desc, long_desc, context, flags,
06706                              PGC_STRING, sizeof(struct config_string));
06707     var->variable = valueAddr;
06708     var->boot_val = bootValue;
06709     var->check_hook = check_hook;
06710     var->assign_hook = assign_hook;
06711     var->show_hook = show_hook;
06712     define_custom_variable(&var->gen);
06713 }
06714 
06715 void
06716 DefineCustomEnumVariable(const char *name,
06717                          const char *short_desc,
06718                          const char *long_desc,
06719                          int *valueAddr,
06720                          int bootValue,
06721                          const struct config_enum_entry * options,
06722                          GucContext context,
06723                          int flags,
06724                          GucEnumCheckHook check_hook,
06725                          GucEnumAssignHook assign_hook,
06726                          GucShowHook show_hook)
06727 {
06728     struct config_enum *var;
06729 
06730     var = (struct config_enum *)
06731         init_custom_variable(name, short_desc, long_desc, context, flags,
06732                              PGC_ENUM, sizeof(struct config_enum));
06733     var->variable = valueAddr;
06734     var->boot_val = bootValue;
06735     var->reset_val = bootValue;
06736     var->options = options;
06737     var->check_hook = check_hook;
06738     var->assign_hook = assign_hook;
06739     var->show_hook = show_hook;
06740     define_custom_variable(&var->gen);
06741 }
06742 
06743 void
06744 EmitWarningsOnPlaceholders(const char *className)
06745 {
06746     int         classLen = strlen(className);
06747     int         i;
06748 
06749     for (i = 0; i < num_guc_variables; i++)
06750     {
06751         struct config_generic *var = guc_variables[i];
06752 
06753         if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
06754             strncmp(className, var->name, classLen) == 0 &&
06755             var->name[classLen] == GUC_QUALIFIER_SEPARATOR)
06756         {
06757             ereport(WARNING,
06758                     (errcode(ERRCODE_UNDEFINED_OBJECT),
06759                      errmsg("unrecognized configuration parameter \"%s\"",
06760                             var->name)));
06761         }
06762     }
06763 }
06764 
06765 
06766 /*
06767  * SHOW command
06768  */
06769 void
06770 GetPGVariable(const char *name, DestReceiver *dest)
06771 {
06772     if (guc_name_compare(name, "all") == 0)
06773         ShowAllGUCConfig(dest);
06774     else
06775         ShowGUCConfigOption(name, dest);
06776 }
06777 
06778 TupleDesc
06779 GetPGVariableResultDesc(const char *name)
06780 {
06781     TupleDesc   tupdesc;
06782 
06783     if (guc_name_compare(name, "all") == 0)
06784     {
06785         /* need a tuple descriptor representing three TEXT columns */
06786         tupdesc = CreateTemplateTupleDesc(3, false);
06787         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
06788                            TEXTOID, -1, 0);
06789         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
06790                            TEXTOID, -1, 0);
06791         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
06792                            TEXTOID, -1, 0);
06793     }
06794     else
06795     {
06796         const char *varname;
06797 
06798         /* Get the canonical spelling of name */
06799         (void) GetConfigOptionByName(name, &varname);
06800 
06801         /* need a tuple descriptor representing a single TEXT column */
06802         tupdesc = CreateTemplateTupleDesc(1, false);
06803         TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
06804                            TEXTOID, -1, 0);
06805     }
06806     return tupdesc;
06807 }
06808 
06809 
06810 /*
06811  * SHOW command
06812  */
06813 static void
06814 ShowGUCConfigOption(const char *name, DestReceiver *dest)
06815 {
06816     TupOutputState *tstate;
06817     TupleDesc   tupdesc;
06818     const char *varname;
06819     char       *value;
06820 
06821     /* Get the value and canonical spelling of name */
06822     value = GetConfigOptionByName(name, &varname);
06823 
06824     /* need a tuple descriptor representing a single TEXT column */
06825     tupdesc = CreateTemplateTupleDesc(1, false);
06826     TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
06827                        TEXTOID, -1, 0);
06828 
06829     /* prepare for projection of tuples */
06830     tstate = begin_tup_output_tupdesc(dest, tupdesc);
06831 
06832     /* Send it */
06833     do_text_output_oneline(tstate, value);
06834 
06835     end_tup_output(tstate);
06836 }
06837 
06838 /*
06839  * SHOW ALL command
06840  */
06841 static void
06842 ShowAllGUCConfig(DestReceiver *dest)
06843 {
06844     bool        am_superuser = superuser();
06845     int         i;
06846     TupOutputState *tstate;
06847     TupleDesc   tupdesc;
06848     Datum       values[3];
06849     bool        isnull[3] = {false, false, false};
06850 
06851     /* need a tuple descriptor representing three TEXT columns */
06852     tupdesc = CreateTemplateTupleDesc(3, false);
06853     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
06854                        TEXTOID, -1, 0);
06855     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
06856                        TEXTOID, -1, 0);
06857     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
06858                        TEXTOID, -1, 0);
06859 
06860     /* prepare for projection of tuples */
06861     tstate = begin_tup_output_tupdesc(dest, tupdesc);
06862 
06863     for (i = 0; i < num_guc_variables; i++)
06864     {
06865         struct config_generic *conf = guc_variables[i];
06866         char       *setting;
06867 
06868         if ((conf->flags & GUC_NO_SHOW_ALL) ||
06869             ((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser))
06870             continue;
06871 
06872         /* assign to the values array */
06873         values[0] = PointerGetDatum(cstring_to_text(conf->name));
06874 
06875         setting = _ShowOption(conf, true);
06876         if (setting)
06877         {
06878             values[1] = PointerGetDatum(cstring_to_text(setting));
06879             isnull[1] = false;
06880         }
06881         else
06882         {
06883             values[1] = PointerGetDatum(NULL);
06884             isnull[1] = true;
06885         }
06886 
06887         values[2] = PointerGetDatum(cstring_to_text(conf->short_desc));
06888 
06889         /* send it to dest */
06890         do_tup_output(tstate, values, isnull);
06891 
06892         /* clean up */
06893         pfree(DatumGetPointer(values[0]));
06894         if (setting)
06895         {
06896             pfree(setting);
06897             pfree(DatumGetPointer(values[1]));
06898         }
06899         pfree(DatumGetPointer(values[2]));
06900     }
06901 
06902     end_tup_output(tstate);
06903 }
06904 
06905 /*
06906  * Return GUC variable value by name; optionally return canonical
06907  * form of name.  Return value is palloc'd.
06908  */
06909 char *
06910 GetConfigOptionByName(const char *name, const char **varname)
06911 {
06912     struct config_generic *record;
06913 
06914     record = find_option(name, false, ERROR);
06915     if (record == NULL)
06916         ereport(ERROR,
06917                 (errcode(ERRCODE_UNDEFINED_OBJECT),
06918                errmsg("unrecognized configuration parameter \"%s\"", name)));
06919     if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
06920         ereport(ERROR,
06921                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
06922                  errmsg("must be superuser to examine \"%s\"", name)));
06923 
06924     if (varname)
06925         *varname = record->name;
06926 
06927     return _ShowOption(record, true);
06928 }
06929 
06930 /*
06931  * Return GUC variable value by variable number; optionally return canonical
06932  * form of name.  Return value is palloc'd.
06933  */
06934 void
06935 GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
06936 {
06937     char        buffer[256];
06938     struct config_generic *conf;
06939 
06940     /* check requested variable number valid */
06941     Assert((varnum >= 0) && (varnum < num_guc_variables));
06942 
06943     conf = guc_variables[varnum];
06944 
06945     if (noshow)
06946     {
06947         if ((conf->flags & GUC_NO_SHOW_ALL) ||
06948             ((conf->flags & GUC_SUPERUSER_ONLY) && !superuser()))
06949             *noshow = true;
06950         else
06951             *noshow = false;
06952     }
06953 
06954     /* first get the generic attributes */
06955 
06956     /* name */
06957     values[0] = conf->name;
06958 
06959     /* setting : use _ShowOption in order to avoid duplicating the logic */
06960     values[1] = _ShowOption(conf, false);
06961 
06962     /* unit */
06963     if (conf->vartype == PGC_INT)
06964     {
06965         static char buf[8];
06966 
06967         switch (conf->flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME))
06968         {
06969             case GUC_UNIT_KB:
06970                 values[2] = "kB";
06971                 break;
06972             case GUC_UNIT_BLOCKS:
06973                 snprintf(buf, sizeof(buf), "%dkB", BLCKSZ / 1024);
06974                 values[2] = buf;
06975                 break;
06976             case GUC_UNIT_XBLOCKS:
06977                 snprintf(buf, sizeof(buf), "%dkB", XLOG_BLCKSZ / 1024);
06978                 values[2] = buf;
06979                 break;
06980             case GUC_UNIT_MS:
06981                 values[2] = "ms";
06982                 break;
06983             case GUC_UNIT_S:
06984                 values[2] = "s";
06985                 break;
06986             case GUC_UNIT_MIN:
06987                 values[2] = "min";
06988                 break;
06989             default:
06990                 values[2] = "";
06991                 break;
06992         }
06993     }
06994     else
06995         values[2] = NULL;
06996 
06997     /* group */
06998     values[3] = config_group_names[conf->group];
06999 
07000     /* short_desc */
07001     values[4] = conf->short_desc;
07002 
07003     /* extra_desc */
07004     values[5] = conf->long_desc;
07005 
07006     /* context */
07007     values[6] = GucContext_Names[conf->context];
07008 
07009     /* vartype */
07010     values[7] = config_type_names[conf->vartype];
07011 
07012     /* source */
07013     values[8] = GucSource_Names[conf->source];
07014 
07015     /* now get the type specifc attributes */
07016     switch (conf->vartype)
07017     {
07018         case PGC_BOOL:
07019             {
07020                 struct config_bool *lconf = (struct config_bool *) conf;
07021 
07022                 /* min_val */
07023                 values[9] = NULL;
07024 
07025                 /* max_val */
07026                 values[10] = NULL;
07027 
07028                 /* enumvals */
07029                 values[11] = NULL;
07030 
07031                 /* boot_val */
07032                 values[12] = pstrdup(lconf->boot_val ? "on" : "off");
07033 
07034                 /* reset_val */
07035                 values[13] = pstrdup(lconf->reset_val ? "on" : "off");
07036             }
07037             break;
07038 
07039         case PGC_INT:
07040             {
07041                 struct config_int *lconf = (struct config_int *) conf;
07042 
07043                 /* min_val */
07044                 snprintf(buffer, sizeof(buffer), "%d", lconf->min);
07045                 values[9] = pstrdup(buffer);
07046 
07047                 /* max_val */
07048                 snprintf(buffer, sizeof(buffer), "%d", lconf->max);
07049                 values[10] = pstrdup(buffer);
07050 
07051                 /* enumvals */
07052                 values[11] = NULL;
07053 
07054                 /* boot_val */
07055                 snprintf(buffer, sizeof(buffer), "%d", lconf->boot_val);
07056                 values[12] = pstrdup(buffer);
07057 
07058                 /* reset_val */
07059                 snprintf(buffer, sizeof(buffer), "%d", lconf->reset_val);
07060                 values[13] = pstrdup(buffer);
07061             }
07062             break;
07063 
07064         case PGC_REAL:
07065             {
07066                 struct config_real *lconf = (struct config_real *) conf;
07067 
07068                 /* min_val */
07069                 snprintf(buffer, sizeof(buffer), "%g", lconf->min);
07070                 values[9] = pstrdup(buffer);
07071 
07072                 /* max_val */
07073                 snprintf(buffer, sizeof(buffer), "%g", lconf->max);
07074                 values[10] = pstrdup(buffer);
07075 
07076                 /* enumvals */
07077                 values[11] = NULL;
07078 
07079                 /* boot_val */
07080                 snprintf(buffer, sizeof(buffer), "%g", lconf->boot_val);
07081                 values[12] = pstrdup(buffer);
07082 
07083                 /* reset_val */
07084                 snprintf(buffer, sizeof(buffer), "%g", lconf->reset_val);
07085                 values[13] = pstrdup(buffer);
07086             }
07087             break;
07088 
07089         case PGC_STRING:
07090             {
07091                 struct config_string *lconf = (struct config_string *) conf;
07092 
07093                 /* min_val */
07094                 values[9] = NULL;
07095 
07096                 /* max_val */
07097                 values[10] = NULL;
07098 
07099                 /* enumvals */
07100                 values[11] = NULL;
07101 
07102                 /* boot_val */
07103                 if (lconf->boot_val == NULL)
07104                     values[12] = NULL;
07105                 else
07106                     values[12] = pstrdup(lconf->boot_val);
07107 
07108                 /* reset_val */
07109                 if (lconf->reset_val == NULL)
07110                     values[13] = NULL;
07111                 else
07112                     values[13] = pstrdup(lconf->reset_val);
07113             }
07114             break;
07115 
07116         case PGC_ENUM:
07117             {
07118                 struct config_enum *lconf = (struct config_enum *) conf;
07119 
07120                 /* min_val */
07121                 values[9] = NULL;
07122 
07123                 /* max_val */
07124                 values[10] = NULL;
07125 
07126                 /* enumvals */
07127 
07128                 /*
07129                  * NOTE! enumvals with double quotes in them are not
07130                  * supported!
07131                  */
07132                 values[11] = config_enum_get_options((struct config_enum *) conf,
07133                                                      "{\"", "\"}", "\",\"");
07134 
07135                 /* boot_val */
07136                 values[12] = pstrdup(config_enum_lookup_by_value(lconf,
07137                                                            lconf->boot_val));
07138 
07139                 /* reset_val */
07140                 values[13] = pstrdup(config_enum_lookup_by_value(lconf,
07141                                                           lconf->reset_val));
07142             }
07143             break;
07144 
07145         default:
07146             {
07147                 /*
07148                  * should never get here, but in case we do, set 'em to NULL
07149                  */
07150 
07151                 /* min_val */
07152                 values[9] = NULL;
07153 
07154                 /* max_val */
07155                 values[10] = NULL;
07156 
07157                 /* enumvals */
07158                 values[11] = NULL;
07159 
07160                 /* boot_val */
07161                 values[12] = NULL;
07162 
07163                 /* reset_val */
07164                 values[13] = NULL;
07165             }
07166             break;
07167     }
07168 
07169     /*
07170      * If the setting came from a config file, set the source location. For
07171      * security reasons, we don't show source file/line number for
07172      * non-superusers.
07173      */
07174     if (conf->source == PGC_S_FILE && superuser())
07175     {
07176         values[14] = conf->sourcefile;
07177         snprintf(buffer, sizeof(buffer), "%d", conf->sourceline);
07178         values[15] = pstrdup(buffer);
07179     }
07180     else
07181     {
07182         values[14] = NULL;
07183         values[15] = NULL;
07184     }
07185 }
07186 
07187 /*
07188  * Return the total number of GUC variables
07189  */
07190 int
07191 GetNumConfigOptions(void)
07192 {
07193     return num_guc_variables;
07194 }
07195 
07196 /*
07197  * show_config_by_name - equiv to SHOW X command but implemented as
07198  * a function.
07199  */
07200 Datum
07201 show_config_by_name(PG_FUNCTION_ARGS)
07202 {
07203     char       *varname;
07204     char       *varval;
07205 
07206     /* Get the GUC variable name */
07207     varname = TextDatumGetCString(PG_GETARG_DATUM(0));
07208 
07209     /* Get the value */
07210     varval = GetConfigOptionByName(varname, NULL);
07211 
07212     /* Convert to text */
07213     PG_RETURN_TEXT_P(cstring_to_text(varval));
07214 }
07215 
07216 /*
07217  * show_all_settings - equiv to SHOW ALL command but implemented as
07218  * a Table Function.
07219  */
07220 #define NUM_PG_SETTINGS_ATTS    16
07221 
07222 Datum
07223 show_all_settings(PG_FUNCTION_ARGS)
07224 {
07225     FuncCallContext *funcctx;
07226     TupleDesc   tupdesc;
07227     int         call_cntr;
07228     int         max_calls;
07229     AttInMetadata *attinmeta;
07230     MemoryContext oldcontext;
07231 
07232     /* stuff done only on the first call of the function */
07233     if (SRF_IS_FIRSTCALL())
07234     {
07235         /* create a function context for cross-call persistence */
07236         funcctx = SRF_FIRSTCALL_INIT();
07237 
07238         /*
07239          * switch to memory context appropriate for multiple function calls
07240          */
07241         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
07242 
07243         /*
07244          * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
07245          * of the appropriate types
07246          */
07247         tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS, false);
07248         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
07249                            TEXTOID, -1, 0);
07250         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
07251                            TEXTOID, -1, 0);
07252         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit",
07253                            TEXTOID, -1, 0);
07254         TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category",
07255                            TEXTOID, -1, 0);
07256         TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc",
07257                            TEXTOID, -1, 0);
07258         TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc",
07259                            TEXTOID, -1, 0);
07260         TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context",
07261                            TEXTOID, -1, 0);
07262         TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype",
07263                            TEXTOID, -1, 0);
07264         TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source",
07265                            TEXTOID, -1, 0);
07266         TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val",
07267                            TEXTOID, -1, 0);
07268         TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
07269                            TEXTOID, -1, 0);
07270         TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
07271                            TEXTARRAYOID, -1, 0);
07272         TupleDescInitEntry(tupdesc, (AttrNumber) 13, "boot_val",
07273                            TEXTOID, -1, 0);
07274         TupleDescInitEntry(tupdesc, (AttrNumber) 14, "reset_val",
07275                            TEXTOID, -1, 0);
07276         TupleDescInitEntry(tupdesc, (AttrNumber) 15, "sourcefile",
07277                            TEXTOID, -1, 0);
07278         TupleDescInitEntry(tupdesc, (AttrNumber) 16, "sourceline",
07279                            INT4OID, -1, 0);
07280 
07281         /*
07282          * Generate attribute metadata needed later to produce tuples from raw
07283          * C strings
07284          */
07285         attinmeta = TupleDescGetAttInMetadata(tupdesc);
07286         funcctx->attinmeta = attinmeta;
07287 
07288         /* total number of tuples to be returned */
07289         funcctx->max_calls = GetNumConfigOptions();
07290 
07291         MemoryContextSwitchTo(oldcontext);
07292     }
07293 
07294     /* stuff done on every call of the function */
07295     funcctx = SRF_PERCALL_SETUP();
07296 
07297     call_cntr = funcctx->call_cntr;
07298     max_calls = funcctx->max_calls;
07299     attinmeta = funcctx->attinmeta;
07300 
07301     if (call_cntr < max_calls)  /* do when there is more left to send */
07302     {
07303         char       *values[NUM_PG_SETTINGS_ATTS];
07304         bool        noshow;
07305         HeapTuple   tuple;
07306         Datum       result;
07307 
07308         /*
07309          * Get the next visible GUC variable name and value
07310          */
07311         do
07312         {
07313             GetConfigOptionByNum(call_cntr, (const char **) values, &noshow);
07314             if (noshow)
07315             {
07316                 /* bump the counter and get the next config setting */
07317                 call_cntr = ++funcctx->call_cntr;
07318 
07319                 /* make sure we haven't gone too far now */
07320                 if (call_cntr >= max_calls)
07321                     SRF_RETURN_DONE(funcctx);
07322             }
07323         } while (noshow);
07324 
07325         /* build a tuple */
07326         tuple = BuildTupleFromCStrings(attinmeta, values);
07327 
07328         /* make the tuple into a datum */
07329         result = HeapTupleGetDatum(tuple);
07330 
07331         SRF_RETURN_NEXT(funcctx, result);
07332     }
07333     else
07334     {
07335         /* do when there is no more left */
07336         SRF_RETURN_DONE(funcctx);
07337     }
07338 }
07339 
07340 static char *
07341 _ShowOption(struct config_generic * record, bool use_units)
07342 {
07343     char        buffer[256];
07344     const char *val;
07345 
07346     switch (record->vartype)
07347     {
07348         case PGC_BOOL:
07349             {
07350                 struct config_bool *conf = (struct config_bool *) record;
07351 
07352                 if (conf->show_hook)
07353                     val = (*conf->show_hook) ();
07354                 else
07355                     val = *conf->variable ? "on" : "off";
07356             }
07357             break;
07358 
07359         case PGC_INT:
07360             {
07361                 struct config_int *conf = (struct config_int *) record;
07362 
07363                 if (conf->show_hook)
07364                     val = (*conf->show_hook) ();
07365                 else
07366                 {
07367                     /*
07368                      * Use int64 arithmetic to avoid overflows in units
07369                      * conversion.
07370                      */
07371                     int64       result = *conf->variable;
07372                     const char *unit;
07373 
07374                     if (use_units && result > 0 &&
07375                         (record->flags & GUC_UNIT_MEMORY))
07376                     {
07377                         switch (record->flags & GUC_UNIT_MEMORY)
07378                         {
07379                             case GUC_UNIT_BLOCKS:
07380                                 result *= BLCKSZ / 1024;
07381                                 break;
07382                             case GUC_UNIT_XBLOCKS:
07383                                 result *= XLOG_BLCKSZ / 1024;
07384                                 break;
07385                         }
07386 
07387                         if (result % KB_PER_GB == 0)
07388                         {
07389                             result /= KB_PER_GB;
07390                             unit = "GB";
07391                         }
07392                         else if (result % KB_PER_MB == 0)
07393                         {
07394                             result /= KB_PER_MB;
07395                             unit = "MB";
07396                         }
07397                         else
07398                         {
07399                             unit = "kB";
07400                         }
07401                     }
07402                     else if (use_units && result > 0 &&
07403                              (record->flags & GUC_UNIT_TIME))
07404                     {
07405                         switch (record->flags & GUC_UNIT_TIME)
07406                         {
07407                             case GUC_UNIT_S:
07408                                 result *= MS_PER_S;
07409                                 break;
07410                             case GUC_UNIT_MIN:
07411                                 result *= MS_PER_MIN;
07412                                 break;
07413                         }
07414 
07415                         if (result % MS_PER_D == 0)
07416                         {
07417                             result /= MS_PER_D;
07418                             unit = "d";
07419                         }
07420                         else if (result % MS_PER_H == 0)
07421                         {
07422                             result /= MS_PER_H;
07423                             unit = "h";
07424                         }
07425                         else if (result % MS_PER_MIN == 0)
07426                         {
07427                             result /= MS_PER_MIN;
07428                             unit = "min";
07429                         }
07430                         else if (result % MS_PER_S == 0)
07431                         {
07432                             result /= MS_PER_S;
07433                             unit = "s";
07434                         }
07435                         else
07436                         {
07437                             unit = "ms";
07438                         }
07439                     }
07440                     else
07441                         unit = "";
07442 
07443                     snprintf(buffer, sizeof(buffer), INT64_FORMAT "%s",
07444                              result, unit);
07445                     val = buffer;
07446                 }
07447             }
07448             break;
07449 
07450         case PGC_REAL:
07451             {
07452                 struct config_real *conf = (struct config_real *) record;
07453 
07454                 if (conf->show_hook)
07455                     val = (*conf->show_hook) ();
07456                 else
07457                 {
07458                     snprintf(buffer, sizeof(buffer), "%g",
07459                              *conf->variable);
07460                     val = buffer;
07461                 }
07462             }
07463             break;
07464 
07465         case PGC_STRING:
07466             {
07467                 struct config_string *conf = (struct config_string *) record;
07468 
07469                 if (conf->show_hook)
07470                     val = (*conf->show_hook) ();
07471                 else if (*conf->variable && **conf->variable)
07472                     val = *conf->variable;
07473                 else
07474                     val = "";
07475             }
07476             break;
07477 
07478         case PGC_ENUM:
07479             {
07480                 struct config_enum *conf = (struct config_enum *) record;
07481 
07482                 if (conf->show_hook)
07483                     val = (*conf->show_hook) ();
07484                 else
07485                     val = config_enum_lookup_by_value(conf, *conf->variable);
07486             }
07487             break;
07488 
07489         default:
07490             /* just to keep compiler quiet */
07491             val = "???";
07492             break;
07493     }
07494 
07495     return pstrdup(val);
07496 }
07497 
07498 
07499 #ifdef EXEC_BACKEND
07500 
07501 /*
07502  *  These routines dump out all non-default GUC options into a binary
07503  *  file that is read by all exec'ed backends.  The format is:
07504  *
07505  *      variable name, string, null terminated
07506  *      variable value, string, null terminated
07507  *      variable sourcefile, string, null terminated (empty if none)
07508  *      variable sourceline, integer
07509  *      variable source, integer
07510  *      variable scontext, integer
07511  */
07512 static void
07513 write_one_nondefault_variable(FILE *fp, struct config_generic * gconf)
07514 {
07515     if (gconf->source == PGC_S_DEFAULT)
07516         return;
07517 
07518     fprintf(fp, "%s", gconf->name);
07519     fputc(0, fp);
07520 
07521     switch (gconf->vartype)
07522     {
07523         case PGC_BOOL:
07524             {
07525                 struct config_bool *conf = (struct config_bool *) gconf;
07526 
07527                 if (*conf->variable)
07528                     fprintf(fp, "true");
07529                 else
07530                     fprintf(fp, "false");
07531             }
07532             break;
07533 
07534         case PGC_INT:
07535             {
07536                 struct config_int *conf = (struct config_int *) gconf;
07537 
07538                 fprintf(fp, "%d", *conf->variable);
07539             }
07540             break;
07541 
07542         case PGC_REAL:
07543             {
07544                 struct config_real *conf = (struct config_real *) gconf;
07545 
07546                 fprintf(fp, "%.17g", *conf->variable);
07547             }
07548             break;
07549 
07550         case PGC_STRING:
07551             {
07552                 struct config_string *conf = (struct config_string *) gconf;
07553 
07554                 fprintf(fp, "%s", *conf->variable);
07555             }
07556             break;
07557 
07558         case PGC_ENUM:
07559             {
07560                 struct config_enum *conf = (struct config_enum *) gconf;
07561 
07562                 fprintf(fp, "%s",
07563                         config_enum_lookup_by_value(conf, *conf->variable));
07564             }
07565             break;
07566     }
07567 
07568     fputc(0, fp);
07569 
07570     if (gconf->sourcefile)
07571         fprintf(fp, "%s", gconf->sourcefile);
07572     fputc(0, fp);
07573 
07574     fwrite(&gconf->sourceline, 1, sizeof(gconf->sourceline), fp);
07575     fwrite(&gconf->source, 1, sizeof(gconf->source), fp);
07576     fwrite(&gconf->scontext, 1, sizeof(gconf->scontext), fp);
07577 }
07578 
07579 void
07580 write_nondefault_variables(GucContext context)
07581 {
07582     int         elevel;
07583     FILE       *fp;
07584     int         i;
07585 
07586     Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
07587 
07588     elevel = (context == PGC_SIGHUP) ? LOG : ERROR;
07589 
07590     /*
07591      * Open file
07592      */
07593     fp = AllocateFile(CONFIG_EXEC_PARAMS_NEW, "w");
07594     if (!fp)
07595     {
07596         ereport(elevel,
07597                 (errcode_for_file_access(),
07598                  errmsg("could not write to file \"%s\": %m",
07599                         CONFIG_EXEC_PARAMS_NEW)));
07600         return;
07601     }
07602 
07603     for (i = 0; i < num_guc_variables; i++)
07604     {
07605         write_one_nondefault_variable(fp, guc_variables[i]);
07606     }
07607 
07608     if (FreeFile(fp))
07609     {
07610         ereport(elevel,
07611                 (errcode_for_file_access(),
07612                  errmsg("could not write to file \"%s\": %m",
07613                         CONFIG_EXEC_PARAMS_NEW)));
07614         return;
07615     }
07616 
07617     /*
07618      * Put new file in place.  This could delay on Win32, but we don't hold
07619      * any exclusive locks.
07620      */
07621     rename(CONFIG_EXEC_PARAMS_NEW, CONFIG_EXEC_PARAMS);
07622 }
07623 
07624 
07625 /*
07626  *  Read string, including null byte from file
07627  *
07628  *  Return NULL on EOF and nothing read
07629  */
07630 static char *
07631 read_string_with_null(FILE *fp)
07632 {
07633     int         i = 0,
07634                 ch,
07635                 maxlen = 256;
07636     char       *str = NULL;
07637 
07638     do
07639     {
07640         if ((ch = fgetc(fp)) == EOF)
07641         {
07642             if (i == 0)
07643                 return NULL;
07644             else
07645                 elog(FATAL, "invalid format of exec config params file");
07646         }
07647         if (i == 0)
07648             str = guc_malloc(FATAL, maxlen);
07649         else if (i == maxlen)
07650             str = guc_realloc(FATAL, str, maxlen *= 2);
07651         str[i++] = ch;
07652     } while (ch != 0);
07653 
07654     return str;
07655 }
07656 
07657 
07658 /*
07659  *  This routine loads a previous postmaster dump of its non-default
07660  *  settings.
07661  */
07662 void
07663 read_nondefault_variables(void)
07664 {
07665     FILE       *fp;
07666     char       *varname,
07667                *varvalue,
07668                *varsourcefile;
07669     int         varsourceline;
07670     GucSource   varsource;
07671     GucContext  varscontext;
07672 
07673     /*
07674      * Open file
07675      */
07676     fp = AllocateFile(CONFIG_EXEC_PARAMS, "r");
07677     if (!fp)
07678     {
07679         /* File not found is fine */
07680         if (errno != ENOENT)
07681             ereport(FATAL,
07682                     (errcode_for_file_access(),
07683                      errmsg("could not read from file \"%s\": %m",
07684                             CONFIG_EXEC_PARAMS)));
07685         return;
07686     }
07687 
07688     for (;;)
07689     {
07690         struct config_generic *record;
07691 
07692         if ((varname = read_string_with_null(fp)) == NULL)
07693             break;
07694 
07695         if ((record = find_option(varname, true, FATAL)) == NULL)
07696             elog(FATAL, "failed to locate variable \"%s\" in exec config params file", varname);
07697 
07698         if ((varvalue = read_string_with_null(fp)) == NULL)
07699             elog(FATAL, "invalid format of exec config params file");
07700         if ((varsourcefile = read_string_with_null(fp)) == NULL)
07701             elog(FATAL, "invalid format of exec config params file");
07702         if (fread(&varsourceline, 1, sizeof(varsourceline), fp) != sizeof(varsourceline))
07703             elog(FATAL, "invalid format of exec config params file");
07704         if (fread(&varsource, 1, sizeof(varsource), fp) != sizeof(varsource))
07705             elog(FATAL, "invalid format of exec config params file");
07706         if (fread(&varscontext, 1, sizeof(varscontext), fp) != sizeof(varscontext))
07707             elog(FATAL, "invalid format of exec config params file");
07708 
07709         (void) set_config_option(varname, varvalue,
07710                                  varscontext, varsource,
07711                                  GUC_ACTION_SET, true, 0);
07712         if (varsourcefile[0])
07713             set_config_sourcefile(varname, varsourcefile, varsourceline);
07714 
07715         free(varname);
07716         free(varvalue);
07717         free(varsourcefile);
07718     }
07719 
07720     FreeFile(fp);
07721 }
07722 #endif   /* EXEC_BACKEND */
07723 
07724 
07725 /*
07726  * A little "long argument" simulation, although not quite GNU
07727  * compliant. Takes a string of the form "some-option=some value" and
07728  * returns name = "some_option" and value = "some value" in malloc'ed
07729  * storage. Note that '-' is converted to '_' in the option name. If
07730  * there is no '=' in the input string then value will be NULL.
07731  */
07732 void
07733 ParseLongOption(const char *string, char **name, char **value)
07734 {
07735     size_t      equal_pos;
07736     char       *cp;
07737 
07738     AssertArg(string);
07739     AssertArg(name);
07740     AssertArg(value);
07741 
07742     equal_pos = strcspn(string, "=");
07743 
07744     if (string[equal_pos] == '=')
07745     {
07746         *name = guc_malloc(FATAL, equal_pos + 1);
07747         strlcpy(*name, string, equal_pos + 1);
07748 
07749         *value = guc_strdup(FATAL, &string[equal_pos + 1]);
07750     }
07751     else
07752     {
07753         /* no equal sign in string */
07754         *name = guc_strdup(FATAL, string);
07755         *value = NULL;
07756     }
07757 
07758     for (cp = *name; *cp; cp++)
07759         if (*cp == '-')
07760             *cp = '_';
07761 }
07762 
07763 
07764 /*
07765  * Handle options fetched from pg_db_role_setting.setconfig,
07766  * pg_proc.proconfig, etc.  Caller must specify proper context/source/action.
07767  *
07768  * The array parameter must be an array of TEXT (it must not be NULL).
07769  */
07770 void
07771 ProcessGUCArray(ArrayType *array,
07772                 GucContext context, GucSource source, GucAction action)
07773 {
07774     int         i;
07775 
07776     Assert(array != NULL);
07777     Assert(ARR_ELEMTYPE(array) == TEXTOID);
07778     Assert(ARR_NDIM(array) == 1);
07779     Assert(ARR_LBOUND(array)[0] == 1);
07780 
07781     for (i = 1; i <= ARR_DIMS(array)[0]; i++)
07782     {
07783         Datum       d;
07784         bool        isnull;
07785         char       *s;
07786         char       *name;
07787         char       *value;
07788 
07789         d = array_ref(array, 1, &i,
07790                       -1 /* varlenarray */ ,
07791                       -1 /* TEXT's typlen */ ,
07792                       false /* TEXT's typbyval */ ,
07793                       'i' /* TEXT's typalign */ ,
07794                       &isnull);
07795 
07796         if (isnull)
07797             continue;
07798 
07799         s = TextDatumGetCString(d);
07800 
07801         ParseLongOption(s, &name, &value);
07802         if (!value)
07803         {
07804             ereport(WARNING,
07805                     (errcode(ERRCODE_SYNTAX_ERROR),
07806                      errmsg("could not parse setting for parameter \"%s\"",
07807                             name)));
07808             free(name);
07809             continue;
07810         }
07811 
07812         (void) set_config_option(name, value,
07813                                  context, source,
07814                                  action, true, 0);
07815 
07816         free(name);
07817         if (value)
07818             free(value);
07819         pfree(s);
07820     }
07821 }
07822 
07823 
07824 /*
07825  * Add an entry to an option array.  The array parameter may be NULL
07826  * to indicate the current table entry is NULL.
07827  */
07828 ArrayType *
07829 GUCArrayAdd(ArrayType *array, const char *name, const char *value)
07830 {
07831     struct config_generic *record;
07832     Datum       datum;
07833     char       *newval;
07834     ArrayType  *a;
07835 
07836     Assert(name);
07837     Assert(value);
07838 
07839     /* test if the option is valid and we're allowed to set it */
07840     (void) validate_option_array_item(name, value, false);
07841 
07842     /* normalize name (converts obsolete GUC names to modern spellings) */
07843     record = find_option(name, false, WARNING);
07844     if (record)
07845         name = record->name;
07846 
07847     /* build new item for array */
07848     newval = palloc(strlen(name) + 1 + strlen(value) + 1);
07849     sprintf(newval, "%s=%s", name, value);
07850     datum = CStringGetTextDatum(newval);
07851 
07852     if (array)
07853     {
07854         int         index;
07855         bool        isnull;
07856         int         i;
07857 
07858         Assert(ARR_ELEMTYPE(array) == TEXTOID);
07859         Assert(ARR_NDIM(array) == 1);
07860         Assert(ARR_LBOUND(array)[0] == 1);
07861 
07862         index = ARR_DIMS(array)[0] + 1; /* add after end */
07863 
07864         for (i = 1; i <= ARR_DIMS(array)[0]; i++)
07865         {
07866             Datum       d;
07867             char       *current;
07868 
07869             d = array_ref(array, 1, &i,
07870                           -1 /* varlenarray */ ,
07871                           -1 /* TEXT's typlen */ ,
07872                           false /* TEXT's typbyval */ ,
07873                           'i' /* TEXT's typalign */ ,
07874                           &isnull);
07875             if (isnull)
07876                 continue;
07877             current = TextDatumGetCString(d);
07878 
07879             /* check for match up through and including '=' */
07880             if (strncmp(current, newval, strlen(name) + 1) == 0)
07881             {
07882                 index = i;
07883                 break;
07884             }
07885         }
07886 
07887         a = array_set(array, 1, &index,
07888                       datum,
07889                       false,
07890                       -1 /* varlena array */ ,
07891                       -1 /* TEXT's typlen */ ,
07892                       false /* TEXT's typbyval */ ,
07893                       'i' /* TEXT's typalign */ );
07894     }
07895     else
07896         a = construct_array(&datum, 1,
07897                             TEXTOID,
07898                             -1, false, 'i');
07899 
07900     return a;
07901 }
07902 
07903 
07904 /*
07905  * Delete an entry from an option array.  The array parameter may be NULL
07906  * to indicate the current table entry is NULL.  Also, if the return value
07907  * is NULL then a null should be stored.
07908  */
07909 ArrayType *
07910 GUCArrayDelete(ArrayType *array, const char *name)
07911 {
07912     struct config_generic *record;
07913     ArrayType  *newarray;
07914     int         i;
07915     int         index;
07916 
07917     Assert(name);
07918 
07919     /* test if the option is valid and we're allowed to set it */
07920     (void) validate_option_array_item(name, NULL, false);
07921 
07922     /* normalize name (converts obsolete GUC names to modern spellings) */
07923     record = find_option(name, false, WARNING);
07924     if (record)
07925         name = record->name;
07926 
07927     /* if array is currently null, then surely nothing to delete */
07928     if (!array)
07929         return NULL;
07930 
07931     newarray = NULL;
07932     index = 1;
07933 
07934     for (i = 1; i <= ARR_DIMS(array)[0]; i++)
07935     {
07936         Datum       d;
07937         char       *val;
07938         bool        isnull;
07939 
07940         d = array_ref(array, 1, &i,
07941                       -1 /* varlenarray */ ,
07942                       -1 /* TEXT's typlen */ ,
07943                       false /* TEXT's typbyval */ ,
07944                       'i' /* TEXT's typalign */ ,
07945                       &isnull);
07946         if (isnull)
07947             continue;
07948         val = TextDatumGetCString(d);
07949 
07950         /* ignore entry if it's what we want to delete */
07951         if (strncmp(val, name, strlen(name)) == 0
07952             && val[strlen(name)] == '=')
07953             continue;
07954 
07955         /* else add it to the output array */
07956         if (newarray)
07957             newarray = array_set(newarray, 1, &index,
07958                                  d,
07959                                  false,
07960                                  -1 /* varlenarray */ ,
07961                                  -1 /* TEXT's typlen */ ,
07962                                  false /* TEXT's typbyval */ ,
07963                                  'i' /* TEXT's typalign */ );
07964         else
07965             newarray = construct_array(&d, 1,
07966                                        TEXTOID,
07967                                        -1, false, 'i');
07968 
07969         index++;
07970     }
07971 
07972     return newarray;
07973 }
07974 
07975 
07976 /*
07977  * Given a GUC array, delete all settings from it that our permission
07978  * level allows: if superuser, delete them all; if regular user, only
07979  * those that are PGC_USERSET
07980  */
07981 ArrayType *
07982 GUCArrayReset(ArrayType *array)
07983 {
07984     ArrayType  *newarray;
07985     int         i;
07986     int         index;
07987 
07988     /* if array is currently null, nothing to do */
07989     if (!array)
07990         return NULL;
07991 
07992     /* if we're superuser, we can delete everything, so just do it */
07993     if (superuser())
07994         return NULL;
07995 
07996     newarray = NULL;
07997     index = 1;
07998 
07999     for (i = 1; i <= ARR_DIMS(array)[0]; i++)
08000     {
08001         Datum       d;
08002         char       *val;
08003         char       *eqsgn;
08004         bool        isnull;
08005 
08006         d = array_ref(array, 1, &i,
08007                       -1 /* varlenarray */ ,
08008                       -1 /* TEXT's typlen */ ,
08009                       false /* TEXT's typbyval */ ,
08010                       'i' /* TEXT's typalign */ ,
08011                       &isnull);
08012         if (isnull)
08013             continue;
08014         val = TextDatumGetCString(d);
08015 
08016         eqsgn = strchr(val, '=');
08017         *eqsgn = '\0';
08018 
08019         /* skip if we have permission to delete it */
08020         if (validate_option_array_item(val, NULL, true))
08021             continue;
08022 
08023         /* else add it to the output array */
08024         if (newarray)
08025             newarray = array_set(newarray, 1, &index,
08026                                  d,
08027                                  false,
08028                                  -1 /* varlenarray */ ,
08029                                  -1 /* TEXT's typlen */ ,
08030                                  false /* TEXT's typbyval */ ,
08031                                  'i' /* TEXT's typalign */ );
08032         else
08033             newarray = construct_array(&d, 1,
08034                                        TEXTOID,
08035                                        -1, false, 'i');
08036 
08037         index++;
08038         pfree(val);
08039     }
08040 
08041     return newarray;
08042 }
08043 
08044 /*
08045  * Validate a proposed option setting for GUCArrayAdd/Delete/Reset.
08046  *
08047  * name is the option name.  value is the proposed value for the Add case,
08048  * or NULL for the Delete/Reset cases.  If skipIfNoPermissions is true, it's
08049  * not an error to have no permissions to set the option.
08050  *
08051  * Returns TRUE if OK, FALSE if skipIfNoPermissions is true and user does not
08052  * have permission to change this option (all other error cases result in an
08053  * error being thrown).
08054  */
08055 static bool
08056 validate_option_array_item(const char *name, const char *value,
08057                            bool skipIfNoPermissions)
08058 
08059 {
08060     struct config_generic *gconf;
08061 
08062     /*
08063      * There are three cases to consider:
08064      *
08065      * name is a known GUC variable.  Check the value normally, check
08066      * permissions normally (ie, allow if variable is USERSET, or if it's
08067      * SUSET and user is superuser).
08068      *
08069      * name is not known, but exists or can be created as a placeholder (i.e.,
08070      * it has a prefixed name).  We allow this case if you're a superuser,
08071      * otherwise not.  Superusers are assumed to know what they're doing. We
08072      * can't allow it for other users, because when the placeholder is
08073      * resolved it might turn out to be a SUSET variable;
08074      * define_custom_variable assumes we checked that.
08075      *
08076      * name is not known and can't be created as a placeholder.  Throw error,
08077      * unless skipIfNoPermissions is true, in which case return FALSE.
08078      */
08079     gconf = find_option(name, true, WARNING);
08080     if (!gconf)
08081     {
08082         /* not known, failed to make a placeholder */
08083         if (skipIfNoPermissions)
08084             return false;
08085         ereport(ERROR,
08086                 (errcode(ERRCODE_UNDEFINED_OBJECT),
08087                  errmsg("unrecognized configuration parameter \"%s\"",
08088                         name)));
08089     }
08090 
08091     if (gconf->flags & GUC_CUSTOM_PLACEHOLDER)
08092     {
08093         /*
08094          * We cannot do any meaningful check on the value, so only permissions
08095          * are useful to check.
08096          */
08097         if (superuser())
08098             return true;
08099         if (skipIfNoPermissions)
08100             return false;
08101         ereport(ERROR,
08102                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
08103                  errmsg("permission denied to set parameter \"%s\"", name)));
08104     }
08105 
08106     /* manual permissions check so we can avoid an error being thrown */
08107     if (gconf->context == PGC_USERSET)
08108          /* ok */ ;
08109     else if (gconf->context == PGC_SUSET && superuser())
08110          /* ok */ ;
08111     else if (skipIfNoPermissions)
08112         return false;
08113     /* if a permissions error should be thrown, let set_config_option do it */
08114 
08115     /* test for permissions and valid option value */
08116     (void) set_config_option(name, value,
08117                              superuser() ? PGC_SUSET : PGC_USERSET,
08118                              PGC_S_TEST, GUC_ACTION_SET, false, 0);
08119 
08120     return true;
08121 }
08122 
08123 
08124 /*
08125  * Called by check_hooks that want to override the normal
08126  * ERRCODE_INVALID_PARAMETER_VALUE SQLSTATE for check hook failures.
08127  *
08128  * Note that GUC_check_errmsg() etc are just macros that result in a direct
08129  * assignment to the associated variables.  That is ugly, but forced by the
08130  * limitations of C's macro mechanisms.
08131  */
08132 void
08133 GUC_check_errcode(int sqlerrcode)
08134 {
08135     GUC_check_errcode_value = sqlerrcode;
08136 }
08137 
08138 
08139 /*
08140  * Convenience functions to manage calling a variable's check_hook.
08141  * These mostly take care of the protocol for letting check hooks supply
08142  * portions of the error report on failure.
08143  */
08144 
08145 static bool
08146 call_bool_check_hook(struct config_bool * conf, bool *newval, void **extra,
08147                      GucSource source, int elevel)
08148 {
08149     /* Quick success if no hook */
08150     if (!conf->check_hook)
08151         return true;
08152 
08153     /* Reset variables that might be set by hook */
08154     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
08155     GUC_check_errmsg_string = NULL;
08156     GUC_check_errdetail_string = NULL;
08157     GUC_check_errhint_string = NULL;
08158 
08159     if (!(*conf->check_hook) (newval, extra, source))
08160     {
08161         ereport(elevel,
08162                 (errcode(GUC_check_errcode_value),
08163                  GUC_check_errmsg_string ?
08164                  errmsg_internal("%s", GUC_check_errmsg_string) :
08165                  errmsg("invalid value for parameter \"%s\": %d",
08166                         conf->gen.name, (int) *newval),
08167                  GUC_check_errdetail_string ?
08168                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
08169                  GUC_check_errhint_string ?
08170                  errhint("%s", GUC_check_errhint_string) : 0));
08171         /* Flush any strings created in ErrorContext */
08172         FlushErrorState();
08173         return false;
08174     }
08175 
08176     return true;
08177 }
08178 
08179 static bool
08180 call_int_check_hook(struct config_int * conf, int *newval, void **extra,
08181                     GucSource source, int elevel)
08182 {
08183     /* Quick success if no hook */
08184     if (!conf->check_hook)
08185         return true;
08186 
08187     /* Reset variables that might be set by hook */
08188     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
08189     GUC_check_errmsg_string = NULL;
08190     GUC_check_errdetail_string = NULL;
08191     GUC_check_errhint_string = NULL;
08192 
08193     if (!(*conf->check_hook) (newval, extra, source))
08194     {
08195         ereport(elevel,
08196                 (errcode(GUC_check_errcode_value),
08197                  GUC_check_errmsg_string ?
08198                  errmsg_internal("%s", GUC_check_errmsg_string) :
08199                  errmsg("invalid value for parameter \"%s\": %d",
08200                         conf->gen.name, *newval),
08201                  GUC_check_errdetail_string ?
08202                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
08203                  GUC_check_errhint_string ?
08204                  errhint("%s", GUC_check_errhint_string) : 0));
08205         /* Flush any strings created in ErrorContext */
08206         FlushErrorState();
08207         return false;
08208     }
08209 
08210     return true;
08211 }
08212 
08213 static bool
08214 call_real_check_hook(struct config_real * conf, double *newval, void **extra,
08215                      GucSource source, int elevel)
08216 {
08217     /* Quick success if no hook */
08218     if (!conf->check_hook)
08219         return true;
08220 
08221     /* Reset variables that might be set by hook */
08222     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
08223     GUC_check_errmsg_string = NULL;
08224     GUC_check_errdetail_string = NULL;
08225     GUC_check_errhint_string = NULL;
08226 
08227     if (!(*conf->check_hook) (newval, extra, source))
08228     {
08229         ereport(elevel,
08230                 (errcode(GUC_check_errcode_value),
08231                  GUC_check_errmsg_string ?
08232                  errmsg_internal("%s", GUC_check_errmsg_string) :
08233                  errmsg("invalid value for parameter \"%s\": %g",
08234                         conf->gen.name, *newval),
08235                  GUC_check_errdetail_string ?
08236                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
08237                  GUC_check_errhint_string ?
08238                  errhint("%s", GUC_check_errhint_string) : 0));
08239         /* Flush any strings created in ErrorContext */
08240         FlushErrorState();
08241         return false;
08242     }
08243 
08244     return true;
08245 }
08246 
08247 static bool
08248 call_string_check_hook(struct config_string * conf, char **newval, void **extra,
08249                        GucSource source, int elevel)
08250 {
08251     /* Quick success if no hook */
08252     if (!conf->check_hook)
08253         return true;
08254 
08255     /* Reset variables that might be set by hook */
08256     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
08257     GUC_check_errmsg_string = NULL;
08258     GUC_check_errdetail_string = NULL;
08259     GUC_check_errhint_string = NULL;
08260 
08261     if (!(*conf->check_hook) (newval, extra, source))
08262     {
08263         ereport(elevel,
08264                 (errcode(GUC_check_errcode_value),
08265                  GUC_check_errmsg_string ?
08266                  errmsg_internal("%s", GUC_check_errmsg_string) :
08267                  errmsg("invalid value for parameter \"%s\": \"%s\"",
08268                         conf->gen.name, *newval ? *newval : ""),
08269                  GUC_check_errdetail_string ?
08270                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
08271                  GUC_check_errhint_string ?
08272                  errhint("%s", GUC_check_errhint_string) : 0));
08273         /* Flush any strings created in ErrorContext */
08274         FlushErrorState();
08275         return false;
08276     }
08277 
08278     return true;
08279 }
08280 
08281 static bool
08282 call_enum_check_hook(struct config_enum * conf, int *newval, void **extra,
08283                      GucSource source, int elevel)
08284 {
08285     /* Quick success if no hook */
08286     if (!conf->check_hook)
08287         return true;
08288 
08289     /* Reset variables that might be set by hook */
08290     GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
08291     GUC_check_errmsg_string = NULL;
08292     GUC_check_errdetail_string = NULL;
08293     GUC_check_errhint_string = NULL;
08294 
08295     if (!(*conf->check_hook) (newval, extra, source))
08296     {
08297         ereport(elevel,
08298                 (errcode(GUC_check_errcode_value),
08299                  GUC_check_errmsg_string ?
08300                  errmsg_internal("%s", GUC_check_errmsg_string) :
08301                  errmsg("invalid value for parameter \"%s\": \"%s\"",
08302                         conf->gen.name,
08303                         config_enum_lookup_by_value(conf, *newval)),
08304                  GUC_check_errdetail_string ?
08305                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
08306                  GUC_check_errhint_string ?
08307                  errhint("%s", GUC_check_errhint_string) : 0));
08308         /* Flush any strings created in ErrorContext */
08309         FlushErrorState();
08310         return false;
08311     }
08312 
08313     return true;
08314 }
08315 
08316 
08317 /*
08318  * check_hook, assign_hook and show_hook subroutines
08319  */
08320 
08321 static bool
08322 check_log_destination(char **newval, void **extra, GucSource source)
08323 {
08324     char       *rawstring;
08325     List       *elemlist;
08326     ListCell   *l;
08327     int         newlogdest = 0;
08328     int        *myextra;
08329 
08330     /* Need a modifiable copy of string */
08331     rawstring = pstrdup(*newval);
08332 
08333     /* Parse string into list of identifiers */
08334     if (!SplitIdentifierString(rawstring, ',', &elemlist))
08335     {
08336         /* syntax error in list */
08337         GUC_check_errdetail("List syntax is invalid.");
08338         pfree(rawstring);
08339         list_free(elemlist);
08340         return false;
08341     }
08342 
08343     foreach(l, elemlist)
08344     {
08345         char       *tok = (char *) lfirst(l);
08346 
08347         if (pg_strcasecmp(tok, "stderr") == 0)
08348             newlogdest |= LOG_DESTINATION_STDERR;
08349         else if (pg_strcasecmp(tok, "csvlog") == 0)
08350             newlogdest |= LOG_DESTINATION_CSVLOG;
08351 #ifdef HAVE_SYSLOG
08352         else if (pg_strcasecmp(tok, "syslog") == 0)
08353             newlogdest |= LOG_DESTINATION_SYSLOG;
08354 #endif
08355 #ifdef WIN32
08356         else if (pg_strcasecmp(tok, "eventlog") == 0)
08357             newlogdest |= LOG_DESTINATION_EVENTLOG;
08358 #endif
08359         else
08360         {
08361             GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
08362             pfree(rawstring);
08363             list_free(elemlist);
08364             return false;
08365         }
08366     }
08367 
08368     pfree(rawstring);
08369     list_free(elemlist);
08370 
08371     myextra = (int *) guc_malloc(ERROR, sizeof(int));
08372     *myextra = newlogdest;
08373     *extra = (void *) myextra;
08374 
08375     return true;
08376 }
08377 
08378 static void
08379 assign_log_destination(const char *newval, void *extra)
08380 {
08381     Log_destination = *((int *) extra);
08382 }
08383 
08384 static void
08385 assign_syslog_facility(int newval, void *extra)
08386 {
08387 #ifdef HAVE_SYSLOG
08388     set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
08389                           newval);
08390 #endif
08391     /* Without syslog support, just ignore it */
08392 }
08393 
08394 static void
08395 assign_syslog_ident(const char *newval, void *extra)
08396 {
08397 #ifdef HAVE_SYSLOG
08398     set_syslog_parameters(newval, syslog_facility);
08399 #endif
08400     /* Without syslog support, it will always be set to "none", so ignore */
08401 }
08402 
08403 
08404 static void
08405 assign_session_replication_role(int newval, void *extra)
08406 {
08407     /*
08408      * Must flush the plan cache when changing replication role; but don't
08409      * flush unnecessarily.
08410      */
08411     if (SessionReplicationRole != newval)
08412         ResetPlanCache();
08413 }
08414 
08415 static bool
08416 check_temp_buffers(int *newval, void **extra, GucSource source)
08417 {
08418     /*
08419      * Once local buffers have been initialized, it's too late to change this.
08420      */
08421     if (NLocBuffer && NLocBuffer != *newval)
08422     {
08423         GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session.");
08424         return false;
08425     }
08426     return true;
08427 }
08428 
08429 static bool
08430 check_phony_autocommit(bool *newval, void **extra, GucSource source)
08431 {
08432     if (!*newval)
08433     {
08434         GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
08435         GUC_check_errmsg("SET AUTOCOMMIT TO OFF is no longer supported");
08436         return false;
08437     }
08438     return true;
08439 }
08440 
08441 static bool
08442 check_debug_assertions(bool *newval, void **extra, GucSource source)
08443 {
08444 #ifndef USE_ASSERT_CHECKING
08445     if (*newval)
08446     {
08447         GUC_check_errmsg("assertion checking is not supported by this build");
08448         return false;
08449     }
08450 #endif
08451     return true;
08452 }
08453 
08454 static bool
08455 check_bonjour(bool *newval, void **extra, GucSource source)
08456 {
08457 #ifndef USE_BONJOUR
08458     if (*newval)
08459     {
08460         GUC_check_errmsg("Bonjour is not supported by this build");
08461         return false;
08462     }
08463 #endif
08464     return true;
08465 }
08466 
08467 static bool
08468 check_ssl(bool *newval, void **extra, GucSource source)
08469 {
08470 #ifndef USE_SSL
08471     if (*newval)
08472     {
08473         GUC_check_errmsg("SSL is not supported by this build");
08474         return false;
08475     }
08476 #endif
08477     return true;
08478 }
08479 
08480 static bool
08481 check_stage_log_stats(bool *newval, void **extra, GucSource source)
08482 {
08483     if (*newval && log_statement_stats)
08484     {
08485         GUC_check_errdetail("Cannot enable parameter when \"log_statement_stats\" is true.");
08486         return false;
08487     }
08488     return true;
08489 }
08490 
08491 static bool
08492 check_log_stats(bool *newval, void **extra, GucSource source)
08493 {
08494     if (*newval &&
08495         (log_parser_stats || log_planner_stats || log_executor_stats))
08496     {
08497         GUC_check_errdetail("Cannot enable \"log_statement_stats\" when "
08498                             "\"log_parser_stats\", \"log_planner_stats\", "
08499                             "or \"log_executor_stats\" is true.");
08500         return false;
08501     }
08502     return true;
08503 }
08504 
08505 static bool
08506 check_canonical_path(char **newval, void **extra, GucSource source)
08507 {
08508     /*
08509      * Since canonicalize_path never enlarges the string, we can just modify
08510      * newval in-place.  But watch out for NULL, which is the default value
08511      * for external_pid_file.
08512      */
08513     if (*newval)
08514         canonicalize_path(*newval);
08515     return true;
08516 }
08517 
08518 static bool
08519 check_timezone_abbreviations(char **newval, void **extra, GucSource source)
08520 {
08521     /*
08522      * The boot_val given above for timezone_abbreviations is NULL. When we
08523      * see this we just do nothing.  If this value isn't overridden from the
08524      * config file then pg_timezone_abbrev_initialize() will eventually
08525      * replace it with "Default".  This hack has two purposes: to avoid
08526      * wasting cycles loading values that might soon be overridden from the
08527      * config file, and to avoid trying to read the timezone abbrev files
08528      * during InitializeGUCOptions().  The latter doesn't work in an
08529      * EXEC_BACKEND subprocess because my_exec_path hasn't been set yet and so
08530      * we can't locate PGSHAREDIR.
08531      */
08532     if (*newval == NULL)
08533     {
08534         Assert(source == PGC_S_DEFAULT);
08535         return true;
08536     }
08537 
08538     /* OK, load the file and produce a malloc'd TimeZoneAbbrevTable */
08539     *extra = load_tzoffsets(*newval);
08540 
08541     /* tzparser.c returns NULL on failure, reporting via GUC_check_errmsg */
08542     if (!*extra)
08543         return false;
08544 
08545     return true;
08546 }
08547 
08548 static void
08549 assign_timezone_abbreviations(const char *newval, void *extra)
08550 {
08551     /* Do nothing for the boot_val default of NULL */
08552     if (!extra)
08553         return;
08554 
08555     InstallTimeZoneAbbrevs((TimeZoneAbbrevTable *) extra);
08556 }
08557 
08558 /*
08559  * pg_timezone_abbrev_initialize --- set default value if not done already
08560  *
08561  * This is called after initial loading of postgresql.conf.  If no
08562  * timezone_abbreviations setting was found therein, select default.
08563  * If a non-default value is already installed, nothing will happen.
08564  *
08565  * This can also be called from ProcessConfigFile to establish the default
08566  * value after a postgresql.conf entry for it is removed.
08567  */
08568 static void
08569 pg_timezone_abbrev_initialize(void)
08570 {
08571     SetConfigOption("timezone_abbreviations", "Default",
08572                     PGC_POSTMASTER, PGC_S_DYNAMIC_DEFAULT);
08573 }
08574 
08575 static const char *
08576 show_archive_command(void)
08577 {
08578     if (XLogArchivingActive())
08579         return XLogArchiveCommand;
08580     else
08581         return "(disabled)";
08582 }
08583 
08584 static void
08585 assign_tcp_keepalives_idle(int newval, void *extra)
08586 {
08587     /*
08588      * The kernel API provides no way to test a value without setting it; and
08589      * once we set it we might fail to unset it.  So there seems little point
08590      * in fully implementing the check-then-assign GUC API for these
08591      * variables.  Instead we just do the assignment on demand.  pqcomm.c
08592      * reports any problems via elog(LOG).
08593      *
08594      * This approach means that the GUC value might have little to do with the
08595      * actual kernel value, so we use a show_hook that retrieves the kernel
08596      * value rather than trusting GUC's copy.
08597      */
08598     (void) pq_setkeepalivesidle(newval, MyProcPort);
08599 }
08600 
08601 static const char *
08602 show_tcp_keepalives_idle(void)
08603 {
08604     /* See comments in assign_tcp_keepalives_idle */
08605     static char nbuf[16];
08606 
08607     snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
08608     return nbuf;
08609 }
08610 
08611 static void
08612 assign_tcp_keepalives_interval(int newval, void *extra)
08613 {
08614     /* See comments in assign_tcp_keepalives_idle */
08615     (void) pq_setkeepalivesinterval(newval, MyProcPort);
08616 }
08617 
08618 static const char *
08619 show_tcp_keepalives_interval(void)
08620 {
08621     /* See comments in assign_tcp_keepalives_idle */
08622     static char nbuf[16];
08623 
08624     snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
08625     return nbuf;
08626 }
08627 
08628 static void
08629 assign_tcp_keepalives_count(int newval, void *extra)
08630 {
08631     /* See comments in assign_tcp_keepalives_idle */
08632     (void) pq_setkeepalivescount(newval, MyProcPort);
08633 }
08634 
08635 static const char *
08636 show_tcp_keepalives_count(void)
08637 {
08638     /* See comments in assign_tcp_keepalives_idle */
08639     static char nbuf[16];
08640 
08641     snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
08642     return nbuf;
08643 }
08644 
08645 static bool
08646 check_maxconnections(int *newval, void **extra, GucSource source)
08647 {
08648     if (*newval + GetNumShmemAttachedBgworkers() + autovacuum_max_workers + 1 >
08649         MAX_BACKENDS)
08650         return false;
08651     return true;
08652 }
08653 
08654 static bool
08655 check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
08656 {
08657     if (MaxConnections + *newval + 1 + GetNumShmemAttachedBgworkers() >
08658         MAX_BACKENDS)
08659         return false;
08660     return true;
08661 }
08662 
08663 static bool
08664 check_effective_io_concurrency(int *newval, void **extra, GucSource source)
08665 {
08666 #ifdef USE_PREFETCH
08667     double      new_prefetch_pages = 0.0;
08668     int         i;
08669 
08670     /*----------
08671      * The user-visible GUC parameter is the number of drives (spindles),
08672      * which we need to translate to a number-of-pages-to-prefetch target.
08673      * The target value is stashed in *extra and then assigned to the actual
08674      * variable by assign_effective_io_concurrency.
08675      *
08676      * The expected number of prefetch pages needed to keep N drives busy is:
08677      *
08678      * drives |   I/O requests
08679      * -------+----------------
08680      *      1 |   1
08681      *      2 |   2/1 + 2/2 = 3
08682      *      3 |   3/1 + 3/2 + 3/3 = 5 1/2
08683      *      4 |   4/1 + 4/2 + 4/3 + 4/4 = 8 1/3
08684      *      n |   n * H(n)
08685      *
08686      * This is called the "coupon collector problem" and H(n) is called the
08687      * harmonic series.  This could be approximated by n * ln(n), but for
08688      * reasonable numbers of drives we might as well just compute the series.
08689      *
08690      * Alternatively we could set the target to the number of pages necessary
08691      * so that the expected number of active spindles is some arbitrary
08692      * percentage of the total.  This sounds the same but is actually slightly
08693      * different.  The result ends up being ln(1-P)/ln((n-1)/n) where P is
08694      * that desired fraction.
08695      *
08696      * Experimental results show that both of these formulas aren't aggressive
08697      * enough, but we don't really have any better proposals.
08698      *
08699      * Note that if *newval = 0 (disabled), we must set target = 0.
08700      *----------
08701      */
08702 
08703     for (i = 1; i <= *newval; i++)
08704         new_prefetch_pages += (double) *newval / (double) i;
08705 
08706     /* This range check shouldn't fail, but let's be paranoid */
08707     if (new_prefetch_pages >= 0.0 && new_prefetch_pages < (double) INT_MAX)
08708     {
08709         int        *myextra = (int *) guc_malloc(ERROR, sizeof(int));
08710 
08711         *myextra = (int) rint(new_prefetch_pages);
08712         *extra = (void *) myextra;
08713 
08714         return true;
08715     }
08716     else
08717         return false;
08718 #else
08719     return true;
08720 #endif   /* USE_PREFETCH */
08721 }
08722 
08723 static void
08724 assign_effective_io_concurrency(int newval, void *extra)
08725 {
08726 #ifdef USE_PREFETCH
08727     target_prefetch_pages = *((int *) extra);
08728 #endif   /* USE_PREFETCH */
08729 }
08730 
08731 static void
08732 assign_pgstat_temp_directory(const char *newval, void *extra)
08733 {
08734     /* check_canonical_path already canonicalized newval for us */
08735     char       *dname;
08736     char       *tname;
08737     char       *fname;
08738 
08739     /* directory */
08740     dname = guc_malloc(ERROR, strlen(newval) + 1);      /* runtime dir */
08741     sprintf(dname, "%s", newval);
08742 
08743     /* global stats */
08744     tname = guc_malloc(ERROR, strlen(newval) + 12);     /* /global.tmp */
08745     sprintf(tname, "%s/global.tmp", newval);
08746     fname = guc_malloc(ERROR, strlen(newval) + 13);     /* /global.stat */
08747     sprintf(fname, "%s/global.stat", newval);
08748 
08749     if (pgstat_stat_directory)
08750         free(pgstat_stat_directory);
08751     pgstat_stat_directory = dname;
08752     if (pgstat_stat_tmpname)
08753         free(pgstat_stat_tmpname);
08754     pgstat_stat_tmpname = tname;
08755     if (pgstat_stat_filename)
08756         free(pgstat_stat_filename);
08757     pgstat_stat_filename = fname;
08758 }
08759 
08760 static bool
08761 check_application_name(char **newval, void **extra, GucSource source)
08762 {
08763     /* Only allow clean ASCII chars in the application name */
08764     char       *p;
08765 
08766     for (p = *newval; *p; p++)
08767     {
08768         if (*p < 32 || *p > 126)
08769             *p = '?';
08770     }
08771 
08772     return true;
08773 }
08774 
08775 static void
08776 assign_application_name(const char *newval, void *extra)
08777 {
08778     /* Update the pg_stat_activity view */
08779     pgstat_report_appname(newval);
08780 }
08781 
08782 static const char *
08783 show_unix_socket_permissions(void)
08784 {
08785     static char buf[8];
08786 
08787     snprintf(buf, sizeof(buf), "%04o", Unix_socket_permissions);
08788     return buf;
08789 }
08790 
08791 static const char *
08792 show_log_file_mode(void)
08793 {
08794     static char buf[8];
08795 
08796     snprintf(buf, sizeof(buf), "%04o", Log_file_mode);
08797     return buf;
08798 }
08799 
08800 #include "guc-file.c"