OSDN Git Service

bde3be91cf3548e7995d3aab8329abda2cd77bf0
[pg-rex/syncrep.git] / src / backend / utils / misc / guc.c
1 /*--------------------------------------------------------------------
2  * guc.c
3  *
4  * Support for grand unified configuration scheme, including SET
5  * command, configuration file, and command line options.
6  * See src/backend/utils/misc/README for more information.
7  *
8  *
9  * Copyright (c) 2000-2010, PostgreSQL Global Development Group
10  * Written by Peter Eisentraut <peter_e@gmx.net>.
11  *
12  * IDENTIFICATION
13  *        $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.541 2010/02/17 04:19:40 tgl Exp $
14  *
15  *--------------------------------------------------------------------
16  */
17 #include "postgres.h"
18
19 #include <ctype.h>
20 #include <float.h>
21 #include <math.h>
22 #include <limits.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #ifdef HAVE_SYSLOG
26 #include <syslog.h>
27 #endif
28
29 #include "access/gin.h"
30 #include "access/transam.h"
31 #include "access/twophase.h"
32 #include "access/xact.h"
33 #include "catalog/namespace.h"
34 #include "commands/async.h"
35 #include "commands/prepare.h"
36 #include "commands/vacuum.h"
37 #include "commands/variable.h"
38 #include "commands/trigger.h"
39 #include "funcapi.h"
40 #include "libpq/auth.h"
41 #include "libpq/be-fsstubs.h"
42 #include "libpq/pqformat.h"
43 #include "miscadmin.h"
44 #include "optimizer/cost.h"
45 #include "optimizer/geqo.h"
46 #include "optimizer/paths.h"
47 #include "optimizer/planmain.h"
48 #include "parser/parse_expr.h"
49 #include "parser/parse_type.h"
50 #include "parser/parser.h"
51 #include "parser/scansup.h"
52 #include "pgstat.h"
53 #include "postmaster/autovacuum.h"
54 #include "postmaster/bgwriter.h"
55 #include "postmaster/postmaster.h"
56 #include "postmaster/syslogger.h"
57 #include "postmaster/walwriter.h"
58 #include "replication/walsender.h"
59 #include "storage/bufmgr.h"
60 #include "storage/fd.h"
61 #include "tcop/tcopprot.h"
62 #include "tsearch/ts_cache.h"
63 #include "utils/builtins.h"
64 #include "utils/bytea.h"
65 #include "utils/guc_tables.h"
66 #include "utils/memutils.h"
67 #include "utils/pg_locale.h"
68 #include "utils/plancache.h"
69 #include "utils/portal.h"
70 #include "utils/ps_status.h"
71 #include "utils/tzparser.h"
72 #include "utils/xml.h"
73
74 #ifndef PG_KRB_SRVTAB
75 #define PG_KRB_SRVTAB ""
76 #endif
77 #ifndef PG_KRB_SRVNAM
78 #define PG_KRB_SRVNAM ""
79 #endif
80
81 #define CONFIG_FILENAME "postgresql.conf"
82 #define HBA_FILENAME    "pg_hba.conf"
83 #define IDENT_FILENAME  "pg_ident.conf"
84
85 #ifdef EXEC_BACKEND
86 #define CONFIG_EXEC_PARAMS "global/config_exec_params"
87 #define CONFIG_EXEC_PARAMS_NEW "global/config_exec_params.new"
88 #endif
89
90 /* upper limit for GUC variables measured in kilobytes of memory */
91 /* note that various places assume the byte size fits in a "long" variable */
92 #if SIZEOF_SIZE_T > 4 && SIZEOF_LONG > 4
93 #define MAX_KILOBYTES   INT_MAX
94 #else
95 #define MAX_KILOBYTES   (INT_MAX / 1024)
96 #endif
97
98 #define KB_PER_MB (1024)
99 #define KB_PER_GB (1024*1024)
100
101 #define MS_PER_S 1000
102 #define S_PER_MIN 60
103 #define MS_PER_MIN (1000 * 60)
104 #define MIN_PER_H 60
105 #define S_PER_H (60 * 60)
106 #define MS_PER_H (1000 * 60 * 60)
107 #define MIN_PER_D (60 * 24)
108 #define S_PER_D (60 * 60 * 24)
109 #define MS_PER_D (1000 * 60 * 60 * 24)
110
111 /* XXX these should appear in other modules' header files */
112 extern bool Log_disconnections;
113 extern int      CommitDelay;
114 extern int      CommitSiblings;
115 extern char *default_tablespace;
116 extern char *temp_tablespaces;
117 extern bool synchronize_seqscans;
118 extern bool fullPageWrites;
119 extern int      vacuum_defer_cleanup_age;
120
121 int     trace_recovery_messages = LOG;
122
123 #ifdef TRACE_SORT
124 extern bool trace_sort;
125 #endif
126 #ifdef TRACE_SYNCSCAN
127 extern bool trace_syncscan;
128 #endif
129 #ifdef DEBUG_BOUNDED_SORT
130 extern bool optimize_bounded_sort;
131 #endif
132
133 #ifdef USE_SSL
134 extern char *SSLCipherSuites;
135 #endif
136
137 static void set_config_sourcefile(const char *name, char *sourcefile,
138                                           int sourceline);
139
140 static const char *assign_log_destination(const char *value,
141                                            bool doit, GucSource source);
142
143 #ifdef HAVE_SYSLOG
144 static int      syslog_facility = LOG_LOCAL0;
145
146 static bool assign_syslog_facility(int newval,
147                                            bool doit, GucSource source);
148 static const char *assign_syslog_ident(const char *ident,
149                                         bool doit, GucSource source);
150 #endif
151
152 static bool assign_session_replication_role(int newval, bool doit,
153                                                                 GucSource source);
154 static const char *show_num_temp_buffers(void);
155 static bool assign_phony_autocommit(bool newval, bool doit, GucSource source);
156 static const char *assign_custom_variable_classes(const char *newval, bool doit,
157                                                            GucSource source);
158 static bool assign_debug_assertions(bool newval, bool doit, GucSource source);
159 static bool assign_bonjour(bool newval, bool doit, GucSource source);
160 static bool assign_ssl(bool newval, bool doit, GucSource source);
161 static bool assign_stage_log_stats(bool newval, bool doit, GucSource source);
162 static bool assign_log_stats(bool newval, bool doit, GucSource source);
163 static bool assign_transaction_read_only(bool newval, bool doit, GucSource source);
164 static const char *assign_canonical_path(const char *newval, bool doit, GucSource source);
165 static const char *assign_timezone_abbreviations(const char *newval, bool doit, GucSource source);
166 static const char *show_archive_command(void);
167 static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
168 static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
169 static bool assign_tcp_keepalives_count(int newval, bool doit, GucSource source);
170 static const char *show_tcp_keepalives_idle(void);
171 static const char *show_tcp_keepalives_interval(void);
172 static const char *show_tcp_keepalives_count(void);
173 static bool assign_maxconnections(int newval, bool doit, GucSource source);
174 static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source);
175 static bool assign_effective_io_concurrency(int newval, bool doit, GucSource source);
176 static const char *assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source);
177 static const char *assign_application_name(const char *newval, bool doit, GucSource source);
178
179 static char *config_enum_get_options(struct config_enum * record,
180                                                 const char *prefix, const char *suffix,
181                                                 const char *separator);
182
183
184 /*
185  * Options for enum values defined in this module.
186  *
187  * NOTE! Option values may not contain double quotes!
188  */
189
190 static const struct config_enum_entry bytea_output_options[] = {
191         {"escape", BYTEA_OUTPUT_ESCAPE, false},
192         {"hex", BYTEA_OUTPUT_HEX, false},
193         {NULL, 0, false}
194 };
195
196 /*
197  * We have different sets for client and server message level options because
198  * they sort slightly different (see "log" level)
199  */
200 static const struct config_enum_entry client_message_level_options[] = {
201         {"debug", DEBUG2, true},
202         {"debug5", DEBUG5, false},
203         {"debug4", DEBUG4, false},
204         {"debug3", DEBUG3, false},
205         {"debug2", DEBUG2, false},
206         {"debug1", DEBUG1, false},
207         {"log", LOG, false},
208         {"info", INFO, true},
209         {"notice", NOTICE, false},
210         {"warning", WARNING, false},
211         {"error", ERROR, false},
212         {"fatal", FATAL, true},
213         {"panic", PANIC, true},
214         {NULL, 0, false}
215 };
216
217 static const struct config_enum_entry server_message_level_options[] = {
218         {"debug", DEBUG2, true},
219         {"debug5", DEBUG5, false},
220         {"debug4", DEBUG4, false},
221         {"debug3", DEBUG3, false},
222         {"debug2", DEBUG2, false},
223         {"debug1", DEBUG1, false},
224         {"info", INFO, false},
225         {"notice", NOTICE, false},
226         {"warning", WARNING, false},
227         {"error", ERROR, false},
228         {"log", LOG, false},
229         {"fatal", FATAL, false},
230         {"panic", PANIC, false},
231         {NULL, 0, false}
232 };
233
234 static const struct config_enum_entry intervalstyle_options[] = {
235         {"postgres", INTSTYLE_POSTGRES, false},
236         {"postgres_verbose", INTSTYLE_POSTGRES_VERBOSE, false},
237         {"sql_standard", INTSTYLE_SQL_STANDARD, false},
238         {"iso_8601", INTSTYLE_ISO_8601, false},
239         {NULL, 0, false}
240 };
241
242 static const struct config_enum_entry log_error_verbosity_options[] = {
243         {"terse", PGERROR_TERSE, false},
244         {"default", PGERROR_DEFAULT, false},
245         {"verbose", PGERROR_VERBOSE, false},
246         {NULL, 0, false}
247 };
248
249 static const struct config_enum_entry log_statement_options[] = {
250         {"none", LOGSTMT_NONE, false},
251         {"ddl", LOGSTMT_DDL, false},
252         {"mod", LOGSTMT_MOD, false},
253         {"all", LOGSTMT_ALL, false},
254         {NULL, 0, false}
255 };
256
257 static const struct config_enum_entry isolation_level_options[] = {
258         {"serializable", XACT_SERIALIZABLE, false},
259         {"repeatable read", XACT_REPEATABLE_READ, false},
260         {"read committed", XACT_READ_COMMITTED, false},
261         {"read uncommitted", XACT_READ_UNCOMMITTED, false},
262         {NULL, 0}
263 };
264
265 static const struct config_enum_entry session_replication_role_options[] = {
266         {"origin", SESSION_REPLICATION_ROLE_ORIGIN, false},
267         {"replica", SESSION_REPLICATION_ROLE_REPLICA, false},
268         {"local", SESSION_REPLICATION_ROLE_LOCAL, false},
269         {NULL, 0, false}
270 };
271
272 #ifdef HAVE_SYSLOG
273 static const struct config_enum_entry syslog_facility_options[] = {
274         {"local0", LOG_LOCAL0, false},
275         {"local1", LOG_LOCAL1, false},
276         {"local2", LOG_LOCAL2, false},
277         {"local3", LOG_LOCAL3, false},
278         {"local4", LOG_LOCAL4, false},
279         {"local5", LOG_LOCAL5, false},
280         {"local6", LOG_LOCAL6, false},
281         {"local7", LOG_LOCAL7, false},
282         {NULL, 0}
283 };
284 #endif
285
286 static const struct config_enum_entry track_function_options[] = {
287         {"none", TRACK_FUNC_OFF, false},
288         {"pl", TRACK_FUNC_PL, false},
289         {"all", TRACK_FUNC_ALL, false},
290         {NULL, 0, false}
291 };
292
293 static const struct config_enum_entry xmlbinary_options[] = {
294         {"base64", XMLBINARY_BASE64, false},
295         {"hex", XMLBINARY_HEX, false},
296         {NULL, 0, false}
297 };
298
299 static const struct config_enum_entry xmloption_options[] = {
300         {"content", XMLOPTION_CONTENT, false},
301         {"document", XMLOPTION_DOCUMENT, false},
302         {NULL, 0, false}
303 };
304
305 /*
306  * Although only "on", "off", and "safe_encoding" are documented, we
307  * accept all the likely variants of "on" and "off".
308  */
309 static const struct config_enum_entry backslash_quote_options[] = {
310         {"safe_encoding", BACKSLASH_QUOTE_SAFE_ENCODING, false},
311         {"on", BACKSLASH_QUOTE_ON, false},
312         {"off", BACKSLASH_QUOTE_OFF, false},
313         {"true", BACKSLASH_QUOTE_ON, true},
314         {"false", BACKSLASH_QUOTE_OFF, true},
315         {"yes", BACKSLASH_QUOTE_ON, true},
316         {"no", BACKSLASH_QUOTE_OFF, true},
317         {"1", BACKSLASH_QUOTE_ON, true},
318         {"0", BACKSLASH_QUOTE_OFF, true},
319         {NULL, 0, false}
320 };
321
322 /*
323  * Although only "on", "off", and "partition" are documented, we
324  * accept all the likely variants of "on" and "off".
325  */
326 static const struct config_enum_entry constraint_exclusion_options[] = {
327         {"partition", CONSTRAINT_EXCLUSION_PARTITION, false},
328         {"on", CONSTRAINT_EXCLUSION_ON, false},
329         {"off", CONSTRAINT_EXCLUSION_OFF, false},
330         {"true", CONSTRAINT_EXCLUSION_ON, true},
331         {"false", CONSTRAINT_EXCLUSION_OFF, true},
332         {"yes", CONSTRAINT_EXCLUSION_ON, true},
333         {"no", CONSTRAINT_EXCLUSION_OFF, true},
334         {"1", CONSTRAINT_EXCLUSION_ON, true},
335         {"0", CONSTRAINT_EXCLUSION_OFF, true},
336         {NULL, 0, false}
337 };
338
339 /*
340  * Options for enum values stored in other modules
341  */
342 extern const struct config_enum_entry sync_method_options[];
343
344 /*
345  * GUC option variables that are exported from this module
346  */
347 #ifdef USE_ASSERT_CHECKING
348 bool            assert_enabled = true;
349 #else
350 bool            assert_enabled = false;
351 #endif
352 bool            log_duration = false;
353 bool            Debug_print_plan = false;
354 bool            Debug_print_parse = false;
355 bool            Debug_print_rewritten = false;
356 bool            Debug_pretty_print = true;
357
358 bool            log_parser_stats = false;
359 bool            log_planner_stats = false;
360 bool            log_executor_stats = false;
361 bool            log_statement_stats = false;            /* this is sort of all three
362                                                                                                  * above together */
363 bool            log_btree_build_stats = false;
364
365 bool            check_function_bodies = true;
366 bool            default_with_oids = false;
367 bool            SQL_inheritance = true;
368
369 bool            Password_encryption = true;
370
371 int                     log_min_error_statement = ERROR;
372 int                     log_min_messages = WARNING;
373 int                     client_min_messages = NOTICE;
374 int                     log_min_duration_statement = -1;
375 int                     log_temp_files = -1;
376
377 int                     num_temp_buffers = 1000;
378
379 char       *ConfigFileName;
380 char       *HbaFileName;
381 char       *IdentFileName;
382 char       *external_pid_file;
383
384 char       *pgstat_temp_directory;
385
386 char       *application_name;
387
388 int                     tcp_keepalives_idle;
389 int                     tcp_keepalives_interval;
390 int                     tcp_keepalives_count;
391
392 /*
393  * These variables are all dummies that don't do anything, except in some
394  * cases provide the value for SHOW to display.  The real state is elsewhere
395  * and is kept in sync by assign_hooks.
396  */
397 static char *log_destination_string;
398
399 #ifdef HAVE_SYSLOG
400 static char *syslog_ident_str;
401 #endif
402 static bool phony_autocommit;
403 static bool session_auth_is_superuser;
404 static double phony_random_seed;
405 static char *client_encoding_string;
406 static char *datestyle_string;
407 static char *locale_collate;
408 static char *locale_ctype;
409 static char *server_encoding_string;
410 static char *server_version_string;
411 static int      server_version_num;
412 static char *timezone_string;
413 static char *log_timezone_string;
414 static char *timezone_abbreviations_string;
415 static char *XactIsoLevel_string;
416 static char *data_directory;
417 static char *custom_variable_classes;
418 static int      max_function_args;
419 static int      max_index_keys;
420 static int      max_identifier_length;
421 static int      block_size;
422 static int      segment_size;
423 static int      wal_block_size;
424 static int      wal_segment_size;
425 static bool integer_datetimes;
426 static int      effective_io_concurrency;
427
428 /* should be static, but commands/variable.c needs to get at these */
429 char       *role_string;
430 char       *session_authorization_string;
431
432
433 /*
434  * Displayable names for context types (enum GucContext)
435  *
436  * Note: these strings are deliberately not localized.
437  */
438 const char *const GucContext_Names[] =
439 {
440          /* PGC_INTERNAL */ "internal",
441          /* PGC_POSTMASTER */ "postmaster",
442          /* PGC_SIGHUP */ "sighup",
443          /* PGC_BACKEND */ "backend",
444          /* PGC_SUSET */ "superuser",
445          /* PGC_USERSET */ "user"
446 };
447
448 /*
449  * Displayable names for source types (enum GucSource)
450  *
451  * Note: these strings are deliberately not localized.
452  */
453 const char *const GucSource_Names[] =
454 {
455          /* PGC_S_DEFAULT */ "default",
456          /* PGC_S_ENV_VAR */ "environment variable",
457          /* PGC_S_FILE */ "configuration file",
458          /* PGC_S_ARGV */ "command line",
459          /* PGC_S_DATABASE */ "database",
460          /* PGC_S_USER */ "user",
461          /* PGC_S_DATABASE_USER */ "database user",
462          /* PGC_S_CLIENT */ "client",
463          /* PGC_S_OVERRIDE */ "override",
464          /* PGC_S_INTERACTIVE */ "interactive",
465          /* PGC_S_TEST */ "test",
466          /* PGC_S_SESSION */ "session"
467 };
468
469 /*
470  * Displayable names for the groupings defined in enum config_group
471  */
472 const char *const config_group_names[] =
473 {
474         /* UNGROUPED */
475         gettext_noop("Ungrouped"),
476         /* FILE_LOCATIONS */
477         gettext_noop("File Locations"),
478         /* CONN_AUTH */
479         gettext_noop("Connections and Authentication"),
480         /* CONN_AUTH_SETTINGS */
481         gettext_noop("Connections and Authentication / Connection Settings"),
482         /* CONN_AUTH_SECURITY */
483         gettext_noop("Connections and Authentication / Security and Authentication"),
484         /* RESOURCES */
485         gettext_noop("Resource Usage"),
486         /* RESOURCES_MEM */
487         gettext_noop("Resource Usage / Memory"),
488         /* RESOURCES_KERNEL */
489         gettext_noop("Resource Usage / Kernel Resources"),
490         /* WAL */
491         gettext_noop("Write-Ahead Log"),
492         /* WAL_SETTINGS */
493         gettext_noop("Write-Ahead Log / Settings"),
494         /* WAL_CHECKPOINTS */
495         gettext_noop("Write-Ahead Log / Checkpoints"),
496         /* WAL_REPLICATION */
497         gettext_noop("Write-Ahead Log / Replication"),
498         /* QUERY_TUNING */
499         gettext_noop("Query Tuning"),
500         /* QUERY_TUNING_METHOD */
501         gettext_noop("Query Tuning / Planner Method Configuration"),
502         /* QUERY_TUNING_COST */
503         gettext_noop("Query Tuning / Planner Cost Constants"),
504         /* QUERY_TUNING_GEQO */
505         gettext_noop("Query Tuning / Genetic Query Optimizer"),
506         /* QUERY_TUNING_OTHER */
507         gettext_noop("Query Tuning / Other Planner Options"),
508         /* LOGGING */
509         gettext_noop("Reporting and Logging"),
510         /* LOGGING_WHERE */
511         gettext_noop("Reporting and Logging / Where to Log"),
512         /* LOGGING_WHEN */
513         gettext_noop("Reporting and Logging / When to Log"),
514         /* LOGGING_WHAT */
515         gettext_noop("Reporting and Logging / What to Log"),
516         /* STATS */
517         gettext_noop("Statistics"),
518         /* STATS_MONITORING */
519         gettext_noop("Statistics / Monitoring"),
520         /* STATS_COLLECTOR */
521         gettext_noop("Statistics / Query and Index Statistics Collector"),
522         /* AUTOVACUUM */
523         gettext_noop("Autovacuum"),
524         /* CLIENT_CONN */
525         gettext_noop("Client Connection Defaults"),
526         /* CLIENT_CONN_STATEMENT */
527         gettext_noop("Client Connection Defaults / Statement Behavior"),
528         /* CLIENT_CONN_LOCALE */
529         gettext_noop("Client Connection Defaults / Locale and Formatting"),
530         /* CLIENT_CONN_OTHER */
531         gettext_noop("Client Connection Defaults / Other Defaults"),
532         /* LOCK_MANAGEMENT */
533         gettext_noop("Lock Management"),
534         /* COMPAT_OPTIONS */
535         gettext_noop("Version and Platform Compatibility"),
536         /* COMPAT_OPTIONS_PREVIOUS */
537         gettext_noop("Version and Platform Compatibility / Previous PostgreSQL Versions"),
538         /* COMPAT_OPTIONS_CLIENT */
539         gettext_noop("Version and Platform Compatibility / Other Platforms and Clients"),
540         /* PRESET_OPTIONS */
541         gettext_noop("Preset Options"),
542         /* CUSTOM_OPTIONS */
543         gettext_noop("Customized Options"),
544         /* DEVELOPER_OPTIONS */
545         gettext_noop("Developer Options"),
546         /* help_config wants this array to be null-terminated */
547         NULL
548 };
549
550 /*
551  * Displayable names for GUC variable types (enum config_type)
552  *
553  * Note: these strings are deliberately not localized.
554  */
555 const char *const config_type_names[] =
556 {
557          /* PGC_BOOL */ "bool",
558          /* PGC_INT */ "integer",
559          /* PGC_REAL */ "real",
560          /* PGC_STRING */ "string",
561          /* PGC_ENUM */ "enum"
562 };
563
564
565 /*
566  * Contents of GUC tables
567  *
568  * See src/backend/utils/misc/README for design notes.
569  *
570  * TO ADD AN OPTION:
571  *
572  * 1. Declare a global variable of type bool, int, double, or char*
573  *        and make use of it.
574  *
575  * 2. Decide at what times it's safe to set the option. See guc.h for
576  *        details.
577  *
578  * 3. Decide on a name, a default value, upper and lower bounds (if
579  *        applicable), etc.
580  *
581  * 4. Add a record below.
582  *
583  * 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
584  *        appropriate.
585  *
586  * 6. Don't forget to document the option (at least in config.sgml).
587  *
588  * 7. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure
589  *        it is not single quoted at dump time.
590  */
591
592
593 /******** option records follow ********/
594
595 static struct config_bool ConfigureNamesBool[] =
596 {
597         {
598                 {"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
599                         gettext_noop("Enables the planner's use of sequential-scan plans."),
600                         NULL
601                 },
602                 &enable_seqscan,
603                 true, NULL, NULL
604         },
605         {
606                 {"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
607                         gettext_noop("Enables the planner's use of index-scan plans."),
608                         NULL
609                 },
610                 &enable_indexscan,
611                 true, NULL, NULL
612         },
613         {
614                 {"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
615                         gettext_noop("Enables the planner's use of bitmap-scan plans."),
616                         NULL
617                 },
618                 &enable_bitmapscan,
619                 true, NULL, NULL
620         },
621         {
622                 {"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
623                         gettext_noop("Enables the planner's use of TID scan plans."),
624                         NULL
625                 },
626                 &enable_tidscan,
627                 true, NULL, NULL
628         },
629         {
630                 {"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
631                         gettext_noop("Enables the planner's use of explicit sort steps."),
632                         NULL
633                 },
634                 &enable_sort,
635                 true, NULL, NULL
636         },
637         {
638                 {"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
639                         gettext_noop("Enables the planner's use of hashed aggregation plans."),
640                         NULL
641                 },
642                 &enable_hashagg,
643                 true, NULL, NULL
644         },
645         {
646                 {"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
647                         gettext_noop("Enables the planner's use of nested-loop join plans."),
648                         NULL
649                 },
650                 &enable_nestloop,
651                 true, NULL, NULL
652         },
653         {
654                 {"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
655                         gettext_noop("Enables the planner's use of merge join plans."),
656                         NULL
657                 },
658                 &enable_mergejoin,
659                 true, NULL, NULL
660         },
661         {
662                 {"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
663                         gettext_noop("Enables the planner's use of hash join plans."),
664                         NULL
665                 },
666                 &enable_hashjoin,
667                 true, NULL, NULL
668         },
669         {
670                 {"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
671                         gettext_noop("Enables genetic query optimization."),
672                         gettext_noop("This algorithm attempts to do planning without "
673                                                  "exhaustive searching.")
674                 },
675                 &enable_geqo,
676                 true, NULL, NULL
677         },
678         {
679                 /* Not for general use --- used by SET SESSION AUTHORIZATION */
680                 {"is_superuser", PGC_INTERNAL, UNGROUPED,
681                         gettext_noop("Shows whether the current user is a superuser."),
682                         NULL,
683                         GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
684                 },
685                 &session_auth_is_superuser,
686                 false, NULL, NULL
687         },
688         {
689                 {"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
690                         gettext_noop("Enables advertising the server via Bonjour."),
691                         NULL
692                 },
693                 &enable_bonjour,
694                 false, assign_bonjour, NULL
695         },
696         {
697                 {"ssl", PGC_POSTMASTER, CONN_AUTH_SECURITY,
698                         gettext_noop("Enables SSL connections."),
699                         NULL
700                 },
701                 &EnableSSL,
702                 false, assign_ssl, NULL
703         },
704         {
705                 {"fsync", PGC_SIGHUP, WAL_SETTINGS,
706                         gettext_noop("Forces synchronization of updates to disk."),
707                         gettext_noop("The server will use the fsync() system call in several places to make "
708                         "sure that updates are physically written to disk. This insures "
709                                                  "that a database cluster will recover to a consistent state after "
710                                                  "an operating system or hardware crash.")
711                 },
712                 &enableFsync,
713                 true, NULL, NULL
714         },
715         {
716                 {"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
717                         gettext_noop("Sets immediate fsync at commit."),
718                         NULL
719                 },
720                 &XactSyncCommit,
721                 true, NULL, NULL
722         },
723         {
724                 {"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
725                         gettext_noop("Continues processing past damaged page headers."),
726                         gettext_noop("Detection of a damaged page header normally causes PostgreSQL to "
727                                 "report an error, aborting the current transaction. Setting "
728                                                  "zero_damaged_pages to true causes the system to instead report a "
729                                                  "warning, zero out the damaged page, and continue processing. This "
730                                                  "behavior will destroy data, namely all the rows on the damaged page."),
731                         GUC_NOT_IN_SAMPLE
732                 },
733                 &zero_damaged_pages,
734                 false, NULL, NULL
735         },
736         {
737                 {"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
738                         gettext_noop("Writes full pages to WAL when first modified after a checkpoint."),
739                         gettext_noop("A page write in process during an operating system crash might be "
740                                                  "only partially written to disk.  During recovery, the row changes "
741                           "stored in WAL are not enough to recover.  This option writes "
742                                                  "pages when first modified after a checkpoint to WAL so full recovery "
743                                                  "is possible.")
744                 },
745                 &fullPageWrites,
746                 true, NULL, NULL
747         },
748         {
749                 {"silent_mode", PGC_POSTMASTER, LOGGING_WHERE,
750                         gettext_noop("Runs the server silently."),
751                         gettext_noop("If this parameter is set, the server will automatically run in the "
752                                  "background and any controlling terminals are dissociated.")
753                 },
754                 &SilentMode,
755                 false, NULL, NULL
756         },
757         {
758                 {"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
759                         gettext_noop("Logs each checkpoint."),
760                         NULL
761                 },
762                 &log_checkpoints,
763                 false, NULL, NULL
764         },
765         {
766                 {"log_connections", PGC_BACKEND, LOGGING_WHAT,
767                         gettext_noop("Logs each successful connection."),
768                         NULL
769                 },
770                 &Log_connections,
771                 false, NULL, NULL
772         },
773         {
774                 {"log_disconnections", PGC_BACKEND, LOGGING_WHAT,
775                         gettext_noop("Logs end of a session, including duration."),
776                         NULL
777                 },
778                 &Log_disconnections,
779                 false, NULL, NULL
780         },
781         {
782                 {"debug_assertions", PGC_USERSET, DEVELOPER_OPTIONS,
783                         gettext_noop("Turns on various assertion checks."),
784                         gettext_noop("This is a debugging aid."),
785                         GUC_NOT_IN_SAMPLE
786                 },
787                 &assert_enabled,
788 #ifdef USE_ASSERT_CHECKING
789                 true,
790 #else
791                 false,
792 #endif
793                 assign_debug_assertions, NULL
794         },
795         {
796                 /* currently undocumented, so don't show in SHOW ALL */
797                 {"exit_on_error", PGC_USERSET, UNGROUPED,
798                         gettext_noop("No description available."),
799                         NULL,
800                         GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
801                 },
802                 &ExitOnAnyError,
803                 false, NULL, NULL
804         },
805         {
806                 {"log_duration", PGC_SUSET, LOGGING_WHAT,
807                         gettext_noop("Logs the duration of each completed SQL statement."),
808                         NULL
809                 },
810                 &log_duration,
811                 false, NULL, NULL
812         },
813         {
814                 {"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
815                         gettext_noop("Logs each query's parse tree."),
816                         NULL
817                 },
818                 &Debug_print_parse,
819                 false, NULL, NULL
820         },
821         {
822                 {"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
823                         gettext_noop("Logs each query's rewritten parse tree."),
824                         NULL
825                 },
826                 &Debug_print_rewritten,
827                 false, NULL, NULL
828         },
829         {
830                 {"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
831                         gettext_noop("Logs each query's execution plan."),
832                         NULL
833                 },
834                 &Debug_print_plan,
835                 false, NULL, NULL
836         },
837         {
838                 {"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
839                         gettext_noop("Indents parse and plan tree displays."),
840                         NULL
841                 },
842                 &Debug_pretty_print,
843                 true, NULL, NULL
844         },
845         {
846                 {"log_parser_stats", PGC_SUSET, STATS_MONITORING,
847                         gettext_noop("Writes parser performance statistics to the server log."),
848                         NULL
849                 },
850                 &log_parser_stats,
851                 false, assign_stage_log_stats, NULL
852         },
853         {
854                 {"log_planner_stats", PGC_SUSET, STATS_MONITORING,
855                         gettext_noop("Writes planner performance statistics to the server log."),
856                         NULL
857                 },
858                 &log_planner_stats,
859                 false, assign_stage_log_stats, NULL
860         },
861         {
862                 {"log_executor_stats", PGC_SUSET, STATS_MONITORING,
863                         gettext_noop("Writes executor performance statistics to the server log."),
864                         NULL
865                 },
866                 &log_executor_stats,
867                 false, assign_stage_log_stats, NULL
868         },
869         {
870                 {"log_statement_stats", PGC_SUSET, STATS_MONITORING,
871                         gettext_noop("Writes cumulative performance statistics to the server log."),
872                         NULL
873                 },
874                 &log_statement_stats,
875                 false, assign_log_stats, NULL
876         },
877 #ifdef BTREE_BUILD_STATS
878         {
879                 {"log_btree_build_stats", PGC_SUSET, DEVELOPER_OPTIONS,
880                         gettext_noop("No description available."),
881                         NULL,
882                         GUC_NOT_IN_SAMPLE
883                 },
884                 &log_btree_build_stats,
885                 false, NULL, NULL
886         },
887 #endif
888
889         {
890                 {"track_activities", PGC_SUSET, STATS_COLLECTOR,
891                         gettext_noop("Collects information about executing commands."),
892                         gettext_noop("Enables the collection of information on the currently "
893                                                  "executing command of each session, along with "
894                                                  "the time at which that command began execution.")
895                 },
896                 &pgstat_track_activities,
897                 true, NULL, NULL
898         },
899         {
900                 {"track_counts", PGC_SUSET, STATS_COLLECTOR,
901                         gettext_noop("Collects statistics on database activity."),
902                         NULL
903                 },
904                 &pgstat_track_counts,
905                 true, NULL, NULL
906         },
907
908         {
909                 {"update_process_title", PGC_SUSET, STATS_COLLECTOR,
910                         gettext_noop("Updates the process title to show the active SQL command."),
911                         gettext_noop("Enables updating of the process title every time a new SQL command is received by the server.")
912                 },
913                 &update_process_title,
914                 true, NULL, NULL
915         },
916
917         {
918                 {"autovacuum", PGC_SIGHUP, AUTOVACUUM,
919                         gettext_noop("Starts the autovacuum subprocess."),
920                         NULL
921                 },
922                 &autovacuum_start_daemon,
923                 true, NULL, NULL
924         },
925
926         {
927                 {"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
928                         gettext_noop("Generates debugging output for LISTEN and NOTIFY."),
929                         NULL,
930                         GUC_NOT_IN_SAMPLE
931                 },
932                 &Trace_notify,
933                 false, NULL, NULL
934         },
935
936 #ifdef LOCK_DEBUG
937         {
938                 {"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
939                         gettext_noop("No description available."),
940                         NULL,
941                         GUC_NOT_IN_SAMPLE
942                 },
943                 &Trace_locks,
944                 false, NULL, NULL
945         },
946         {
947                 {"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
948                         gettext_noop("No description available."),
949                         NULL,
950                         GUC_NOT_IN_SAMPLE
951                 },
952                 &Trace_userlocks,
953                 false, NULL, NULL
954         },
955         {
956                 {"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
957                         gettext_noop("No description available."),
958                         NULL,
959                         GUC_NOT_IN_SAMPLE
960                 },
961                 &Trace_lwlocks,
962                 false, NULL, NULL
963         },
964         {
965                 {"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
966                         gettext_noop("No description available."),
967                         NULL,
968                         GUC_NOT_IN_SAMPLE
969                 },
970                 &Debug_deadlocks,
971                 false, NULL, NULL
972         },
973 #endif
974
975         {
976                 {"log_lock_waits", PGC_SUSET, LOGGING_WHAT,
977                         gettext_noop("Logs long lock waits."),
978                         NULL
979                 },
980                 &log_lock_waits,
981                 false, NULL, NULL
982         },
983
984         {
985                 {"log_hostname", PGC_SIGHUP, LOGGING_WHAT,
986                         gettext_noop("Logs the host name in the connection logs."),
987                         gettext_noop("By default, connection logs only show the IP address "
988                                                  "of the connecting host. If you want them to show the host name you "
989                           "can turn this on, but depending on your host name resolution "
990                            "setup it might impose a non-negligible performance penalty.")
991                 },
992                 &log_hostname,
993                 false, NULL, NULL
994         },
995         {
996                 {"sql_inheritance", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
997                         gettext_noop("Causes subtables to be included by default in various commands."),
998                         NULL
999                 },
1000                 &SQL_inheritance,
1001                 true, NULL, NULL
1002         },
1003         {
1004                 {"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
1005                         gettext_noop("Encrypt passwords."),
1006                         gettext_noop("When a password is specified in CREATE USER or "
1007                            "ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
1008                                                  "this parameter determines whether the password is to be encrypted.")
1009                 },
1010                 &Password_encryption,
1011                 true, NULL, NULL
1012         },
1013         {
1014                 {"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
1015                         gettext_noop("Treats \"expr=NULL\" as \"expr IS NULL\"."),
1016                         gettext_noop("When turned on, expressions of the form expr = NULL "
1017                            "(or NULL = expr) are treated as expr IS NULL, that is, they "
1018                                 "return true if expr evaluates to the null value, and false "
1019                            "otherwise. The correct behavior of expr = NULL is to always "
1020                                                  "return null (unknown).")
1021                 },
1022                 &Transform_null_equals,
1023                 false, NULL, NULL
1024         },
1025         {
1026                 {"db_user_namespace", PGC_SIGHUP, CONN_AUTH_SECURITY,
1027                         gettext_noop("Enables per-database user names."),
1028                         NULL
1029                 },
1030                 &Db_user_namespace,
1031                 false, NULL, NULL
1032         },
1033         {
1034                 /* only here for backwards compatibility */
1035                 {"autocommit", PGC_USERSET, CLIENT_CONN_STATEMENT,
1036                         gettext_noop("This parameter doesn't do anything."),
1037                         gettext_noop("It's just here so that we won't choke on SET AUTOCOMMIT TO ON from 7.3-vintage clients."),
1038                         GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
1039                 },
1040                 &phony_autocommit,
1041                 true, assign_phony_autocommit, NULL
1042         },
1043         {
1044                 {"default_transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
1045                         gettext_noop("Sets the default read-only status of new transactions."),
1046                         NULL
1047                 },
1048                 &DefaultXactReadOnly,
1049                 false, NULL, NULL
1050         },
1051         {
1052                 {"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
1053                         gettext_noop("Sets the current transaction's read-only status."),
1054                         NULL,
1055                         GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1056                 },
1057                 &XactReadOnly,
1058                 false, assign_transaction_read_only, NULL
1059         },
1060         {
1061                 {"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
1062                         gettext_noop("Check function bodies during CREATE FUNCTION."),
1063                         NULL
1064                 },
1065                 &check_function_bodies,
1066                 true, NULL, NULL
1067         },
1068         {
1069                 {"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1070                         gettext_noop("Enable input of NULL elements in arrays."),
1071                         gettext_noop("When turned on, unquoted NULL in an array input "
1072                                                  "value means a null value; "
1073                                                  "otherwise it is taken literally.")
1074                 },
1075                 &Array_nulls,
1076                 true, NULL, NULL
1077         },
1078         {
1079                 {"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1080                         gettext_noop("Create new tables with OIDs by default."),
1081                         NULL
1082                 },
1083                 &default_with_oids,
1084                 false, NULL, NULL
1085         },
1086         {
1087                 {"logging_collector", PGC_POSTMASTER, LOGGING_WHERE,
1088                         gettext_noop("Start a subprocess to capture stderr output and/or csvlogs into log files."),
1089                         NULL
1090                 },
1091                 &Logging_collector,
1092                 false, NULL, NULL
1093         },
1094         {
1095                 {"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
1096                         gettext_noop("Truncate existing log files of same name during log rotation."),
1097                         NULL
1098                 },
1099                 &Log_truncate_on_rotation,
1100                 false, NULL, NULL
1101         },
1102
1103 #ifdef TRACE_SORT
1104         {
1105                 {"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
1106                         gettext_noop("Emit information about resource usage in sorting."),
1107                         NULL,
1108                         GUC_NOT_IN_SAMPLE
1109                 },
1110                 &trace_sort,
1111                 false, NULL, NULL
1112         },
1113 #endif
1114
1115 #ifdef TRACE_SYNCSCAN
1116         /* this is undocumented because not exposed in a standard build */
1117         {
1118                 {"trace_syncscan", PGC_USERSET, DEVELOPER_OPTIONS,
1119                         gettext_noop("Generate debugging output for synchronized scanning."),
1120                         NULL,
1121                         GUC_NOT_IN_SAMPLE
1122                 },
1123                 &trace_syncscan,
1124                 false, NULL, NULL
1125         },
1126 #endif
1127
1128 #ifdef DEBUG_BOUNDED_SORT
1129         /* this is undocumented because not exposed in a standard build */
1130         {
1131                 {
1132                         "optimize_bounded_sort", PGC_USERSET, QUERY_TUNING_METHOD,
1133                         gettext_noop("Enable bounded sorting using heap sort."),
1134                         NULL,
1135                         GUC_NOT_IN_SAMPLE
1136                 },
1137                 &optimize_bounded_sort,
1138                 true, NULL, NULL
1139         },
1140 #endif
1141
1142 #ifdef WAL_DEBUG
1143         {
1144                 {"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
1145                         gettext_noop("Emit WAL-related debugging output."),
1146                         NULL,
1147                         GUC_NOT_IN_SAMPLE
1148                 },
1149                 &XLOG_DEBUG,
1150                 false, NULL, NULL
1151         },
1152 #endif
1153
1154         {
1155                 {"integer_datetimes", PGC_INTERNAL, PRESET_OPTIONS,
1156                         gettext_noop("Datetimes are integer based."),
1157                         NULL,
1158                         GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1159                 },
1160                 &integer_datetimes,
1161 #ifdef HAVE_INT64_TIMESTAMP
1162                 true, NULL, NULL
1163 #else
1164                 false, NULL, NULL
1165 #endif
1166         },
1167
1168         {
1169                 {"krb_caseins_users", PGC_SIGHUP, CONN_AUTH_SECURITY,
1170                         gettext_noop("Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."),
1171                         NULL
1172                 },
1173                 &pg_krb_caseins_users,
1174                 false, NULL, NULL
1175         },
1176
1177         {
1178                 {"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1179                         gettext_noop("Warn about backslash escapes in ordinary string literals."),
1180                         NULL
1181                 },
1182                 &escape_string_warning,
1183                 true, NULL, NULL
1184         },
1185
1186         {
1187                 {"standard_conforming_strings", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1188                         gettext_noop("Causes '...' strings to treat backslashes literally."),
1189                         NULL,
1190                         GUC_REPORT
1191                 },
1192                 &standard_conforming_strings,
1193                 false, NULL, NULL
1194         },
1195
1196         {
1197                 {"synchronize_seqscans", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1198                         gettext_noop("Enable synchronized sequential scans."),
1199                         NULL
1200                 },
1201                 &synchronize_seqscans,
1202                 true, NULL, NULL
1203         },
1204
1205         {
1206                 {"archive_mode", PGC_POSTMASTER, WAL_SETTINGS,
1207                         gettext_noop("Allows archiving of WAL files using archive_command."),
1208                         NULL
1209                 },
1210                 &XLogArchiveMode,
1211                 false, NULL, NULL
1212         },
1213
1214         {
1215                 {"recovery_connections", PGC_POSTMASTER, WAL_SETTINGS,
1216                         gettext_noop("During recovery, allows connections and queries. "
1217                                                  " During normal running, causes additional info to be written"
1218                                                  " to WAL to enable hot standby mode on WAL standby nodes."),
1219                         NULL
1220                 },
1221                 &XLogRequestRecoveryConnections,
1222                 true, NULL, NULL
1223         },
1224
1225         {
1226                 {"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS,
1227                         gettext_noop("Allows modifications of the structure of system tables."),
1228                         NULL,
1229                         GUC_NOT_IN_SAMPLE
1230                 },
1231                 &allowSystemTableMods,
1232                 false, NULL, NULL
1233         },
1234
1235         {
1236                 {"ignore_system_indexes", PGC_BACKEND, DEVELOPER_OPTIONS,
1237                         gettext_noop("Disables reading from system indexes."),
1238                         gettext_noop("It does not prevent updating the indexes, so it is safe "
1239                                                  "to use.  The worst consequence is slowness."),
1240                         GUC_NOT_IN_SAMPLE
1241                 },
1242                 &IgnoreSystemIndexes,
1243                 false, NULL, NULL
1244         },
1245
1246         {
1247                 {"lo_compat_privileges", PGC_SUSET, COMPAT_OPTIONS_PREVIOUS,
1248                         gettext_noop("Enables backward compatibility mode for privilege checks on large objects"),
1249                         gettext_noop("Skips privilege checks when reading or modifying large objects, "
1250                                                  "for compatibility with PostgreSQL releases prior to 9.0.")
1251                 },
1252                 &lo_compat_privileges,
1253                 false, NULL, NULL
1254         },
1255
1256         /* End-of-list marker */
1257         {
1258                 {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL
1259         }
1260 };
1261
1262
1263 static struct config_int ConfigureNamesInt[] =
1264 {
1265         {
1266                 {"archive_timeout", PGC_SIGHUP, WAL_SETTINGS,
1267                         gettext_noop("Forces a switch to the next xlog file if a "
1268                                                  "new file has not been started within N seconds."),
1269                         NULL,
1270                         GUC_UNIT_S
1271                 },
1272                 &XLogArchiveTimeout,
1273                 0, 0, INT_MAX, NULL, NULL
1274         },
1275         {
1276                 {"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
1277                         gettext_noop("Waits N seconds on connection startup after authentication."),
1278                         gettext_noop("This allows attaching a debugger to the process."),
1279                         GUC_NOT_IN_SAMPLE | GUC_UNIT_S
1280                 },
1281                 &PostAuthDelay,
1282                 0, 0, INT_MAX, NULL, NULL
1283         },
1284         {
1285                 {"default_statistics_target", PGC_USERSET, QUERY_TUNING_OTHER,
1286                         gettext_noop("Sets the default statistics target."),
1287                         gettext_noop("This applies to table columns that have not had a "
1288                                 "column-specific target set via ALTER TABLE SET STATISTICS.")
1289                 },
1290                 &default_statistics_target,
1291                 100, 1, 10000, NULL, NULL
1292         },
1293         {
1294                 {"from_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
1295                         gettext_noop("Sets the FROM-list size beyond which subqueries "
1296                                                  "are not collapsed."),
1297                         gettext_noop("The planner will merge subqueries into upper "
1298                                 "queries if the resulting FROM list would have no more than "
1299                                                  "this many items.")
1300                 },
1301                 &from_collapse_limit,
1302                 8, 1, INT_MAX, NULL, NULL
1303         },
1304         {
1305                 {"join_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
1306                         gettext_noop("Sets the FROM-list size beyond which JOIN "
1307                                                  "constructs are not flattened."),
1308                         gettext_noop("The planner will flatten explicit JOIN "
1309                                                  "constructs into lists of FROM items whenever a "
1310                                                  "list of no more than this many items would result.")
1311                 },
1312                 &join_collapse_limit,
1313                 8, 1, INT_MAX, NULL, NULL
1314         },
1315         {
1316                 {"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
1317                         gettext_noop("Sets the threshold of FROM items beyond which GEQO is used."),
1318                         NULL
1319                 },
1320                 &geqo_threshold,
1321                 12, 2, INT_MAX, NULL, NULL
1322         },
1323         {
1324                 {"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
1325                         gettext_noop("GEQO: effort is used to set the default for other GEQO parameters."),
1326                         NULL
1327                 },
1328                 &Geqo_effort,
1329                 DEFAULT_GEQO_EFFORT, MIN_GEQO_EFFORT, MAX_GEQO_EFFORT, NULL, NULL
1330         },
1331         {
1332                 {"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
1333                         gettext_noop("GEQO: number of individuals in the population."),
1334                         gettext_noop("Zero selects a suitable default value.")
1335                 },
1336                 &Geqo_pool_size,
1337                 0, 0, INT_MAX, NULL, NULL
1338         },
1339         {
1340                 {"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
1341                         gettext_noop("GEQO: number of iterations of the algorithm."),
1342                         gettext_noop("Zero selects a suitable default value.")
1343                 },
1344                 &Geqo_generations,
1345                 0, 0, INT_MAX, NULL, NULL
1346         },
1347
1348         {
1349                 /* This is PGC_SIGHUP so all backends have the same value. */
1350                 {"deadlock_timeout", PGC_SIGHUP, LOCK_MANAGEMENT,
1351                         gettext_noop("Sets the time to wait on a lock before checking for deadlock."),
1352                         NULL,
1353                         GUC_UNIT_MS
1354                 },
1355                 &DeadlockTimeout,
1356                 1000, 1, INT_MAX / 1000, NULL, NULL
1357         },
1358
1359         /*
1360          * Note: MaxBackends is limited to INT_MAX/4 because some places compute
1361          * 4*MaxBackends without any overflow check.  This check is made in
1362          * assign_maxconnections, since MaxBackends is computed as MaxConnections
1363          * plus autovacuum_max_workers plus one (for the autovacuum launcher).
1364          *
1365          * Likewise we have to limit NBuffers to INT_MAX/2.
1366          *
1367          * See also CheckRequiredParameterValues() if this parameter changes
1368          */
1369         {
1370                 {"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1371                         gettext_noop("Sets the maximum number of concurrent connections."),
1372                         NULL
1373                 },
1374                 &MaxConnections,
1375                 100, 1, INT_MAX / 4, assign_maxconnections, NULL
1376         },
1377
1378         {
1379                 {"max_standby_delay", PGC_SIGHUP, WAL_SETTINGS,
1380                         gettext_noop("Sets the maximum delay to avoid conflict processing on Hot Standby servers."),
1381                         NULL
1382                 },
1383                 &MaxStandbyDelay,
1384                 30, -1, INT_MAX, NULL, NULL
1385         },
1386
1387         {
1388                 {"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1389                         gettext_noop("Sets the number of connection slots reserved for superusers."),
1390                         NULL
1391                 },
1392                 &ReservedBackends,
1393                 3, 0, INT_MAX / 4, NULL, NULL
1394         },
1395
1396         {
1397                 {"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
1398                         gettext_noop("Sets the number of shared memory buffers used by the server."),
1399                         NULL,
1400                         GUC_UNIT_BLOCKS
1401                 },
1402                 &NBuffers,
1403                 1024, 16, INT_MAX / 2, NULL, NULL
1404         },
1405
1406         {
1407                 {"temp_buffers", PGC_USERSET, RESOURCES_MEM,
1408                         gettext_noop("Sets the maximum number of temporary buffers used by each session."),
1409                         NULL,
1410                         GUC_UNIT_BLOCKS
1411                 },
1412                 &num_temp_buffers,
1413                 1024, 100, INT_MAX / 2, NULL, show_num_temp_buffers
1414         },
1415
1416         {
1417                 {"port", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1418                         gettext_noop("Sets the TCP port the server listens on."),
1419                         NULL
1420                 },
1421                 &PostPortNumber,
1422                 DEF_PGPORT, 1, 65535, NULL, NULL
1423         },
1424
1425         {
1426                 {"unix_socket_permissions", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1427                         gettext_noop("Sets the access permissions of the Unix-domain socket."),
1428                         gettext_noop("Unix-domain sockets use the usual Unix file system "
1429                                                  "permission set. The parameter value is expected to be a numeric mode "
1430                                                  "specification in the form accepted by the chmod and umask system "
1431                                                  "calls. (To use the customary octal format the number must start with "
1432                                                  "a 0 (zero).)")
1433                 },
1434                 &Unix_socket_permissions,
1435                 0777, 0000, 0777, NULL, NULL
1436         },
1437
1438         {
1439                 {"work_mem", PGC_USERSET, RESOURCES_MEM,
1440                         gettext_noop("Sets the maximum memory to be used for query workspaces."),
1441                         gettext_noop("This much memory can be used by each internal "
1442                                                  "sort operation and hash table before switching to "
1443                                                  "temporary disk files."),
1444                         GUC_UNIT_KB
1445                 },
1446                 &work_mem,
1447                 1024, 64, MAX_KILOBYTES, NULL, NULL
1448         },
1449
1450         {
1451                 {"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
1452                         gettext_noop("Sets the maximum memory to be used for maintenance operations."),
1453                         gettext_noop("This includes operations such as VACUUM and CREATE INDEX."),
1454                         GUC_UNIT_KB
1455                 },
1456                 &maintenance_work_mem,
1457                 16384, 1024, MAX_KILOBYTES, NULL, NULL
1458         },
1459
1460         {
1461                 {"max_stack_depth", PGC_SUSET, RESOURCES_MEM,
1462                         gettext_noop("Sets the maximum stack depth, in kilobytes."),
1463                         NULL,
1464                         GUC_UNIT_KB
1465                 },
1466                 &max_stack_depth,
1467                 100, 100, MAX_KILOBYTES, assign_max_stack_depth, NULL
1468         },
1469
1470         {
1471                 {"vacuum_cost_page_hit", PGC_USERSET, RESOURCES,
1472                         gettext_noop("Vacuum cost for a page found in the buffer cache."),
1473                         NULL
1474                 },
1475                 &VacuumCostPageHit,
1476                 1, 0, 10000, NULL, NULL
1477         },
1478
1479         {
1480                 {"vacuum_cost_page_miss", PGC_USERSET, RESOURCES,
1481                         gettext_noop("Vacuum cost for a page not found in the buffer cache."),
1482                         NULL
1483                 },
1484                 &VacuumCostPageMiss,
1485                 10, 0, 10000, NULL, NULL
1486         },
1487
1488         {
1489                 {"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES,
1490                         gettext_noop("Vacuum cost for a page dirtied by vacuum."),
1491                         NULL
1492                 },
1493                 &VacuumCostPageDirty,
1494                 20, 0, 10000, NULL, NULL
1495         },
1496
1497         {
1498                 {"vacuum_cost_limit", PGC_USERSET, RESOURCES,
1499                         gettext_noop("Vacuum cost amount available before napping."),
1500                         NULL
1501                 },
1502                 &VacuumCostLimit,
1503                 200, 1, 10000, NULL, NULL
1504         },
1505
1506         {
1507                 {"vacuum_cost_delay", PGC_USERSET, RESOURCES,
1508                         gettext_noop("Vacuum cost delay in milliseconds."),
1509                         NULL,
1510                         GUC_UNIT_MS
1511                 },
1512                 &VacuumCostDelay,
1513                 0, 0, 100, NULL, NULL
1514         },
1515
1516         {
1517                 {"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
1518                         gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
1519                         NULL,
1520                         GUC_UNIT_MS
1521                 },
1522                 &autovacuum_vac_cost_delay,
1523                 20, -1, 100, NULL, NULL
1524         },
1525
1526         {
1527                 {"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
1528                         gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
1529                         NULL
1530                 },
1531                 &autovacuum_vac_cost_limit,
1532                 -1, -1, 10000, NULL, NULL
1533         },
1534
1535         {
1536                 {"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
1537                         gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
1538                         NULL
1539                 },
1540                 &max_files_per_process,
1541                 1000, 25, INT_MAX, NULL, NULL
1542         },
1543
1544         /*
1545          * See also CheckRequiredParameterValues() if this parameter changes
1546          */
1547         {
1548                 {"max_prepared_transactions", PGC_POSTMASTER, RESOURCES,
1549                         gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
1550                         NULL
1551                 },
1552                 &max_prepared_xacts,
1553                 0, 0, INT_MAX / 4, NULL, NULL
1554         },
1555
1556 #ifdef LOCK_DEBUG
1557         {
1558                 {"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
1559                         gettext_noop("No description available."),
1560                         NULL,
1561                         GUC_NOT_IN_SAMPLE
1562                 },
1563                 &Trace_lock_oidmin,
1564                 FirstNormalObjectId, 0, INT_MAX, NULL, NULL
1565         },
1566         {
1567                 {"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
1568                         gettext_noop("No description available."),
1569                         NULL,
1570                         GUC_NOT_IN_SAMPLE
1571                 },
1572                 &Trace_lock_table,
1573                 0, 0, INT_MAX, NULL, NULL
1574         },
1575 #endif
1576
1577         {
1578                 {"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
1579                         gettext_noop("Sets the maximum allowed duration of any statement."),
1580                         gettext_noop("A value of 0 turns off the timeout."),
1581                         GUC_UNIT_MS
1582                 },
1583                 &StatementTimeout,
1584                 0, 0, INT_MAX, NULL, NULL
1585         },
1586
1587         {
1588                 {"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
1589                         gettext_noop("Minimum age at which VACUUM should freeze a table row."),
1590                         NULL
1591                 },
1592                 &vacuum_freeze_min_age,
1593                 50000000, 0, 1000000000, NULL, NULL
1594         },
1595
1596         {
1597                 {"vacuum_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
1598                         gettext_noop("Age at which VACUUM should scan whole table to freeze tuples."),
1599                         NULL
1600                 },
1601                 &vacuum_freeze_table_age,
1602                 150000000, 0, 2000000000, NULL, NULL
1603         },
1604
1605         {
1606                 {"vacuum_defer_cleanup_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
1607                         gettext_noop("Age by which VACUUM and HOT cleanup should be deferred, if any."),
1608                         NULL
1609                 },
1610                 &vacuum_defer_cleanup_age,
1611                 0, 0, 1000000, NULL, NULL
1612         },
1613
1614         /*
1615          * See also CheckRequiredParameterValues() if this parameter changes
1616          */
1617         {
1618                 {"max_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
1619                         gettext_noop("Sets the maximum number of locks per transaction."),
1620                         gettext_noop("The shared lock table is sized on the assumption that "
1621                           "at most max_locks_per_transaction * max_connections distinct "
1622                                                  "objects will need to be locked at any one time.")
1623                 },
1624                 &max_locks_per_xact,
1625                 64, 10, INT_MAX, NULL, NULL
1626         },
1627
1628         {
1629                 {"authentication_timeout", PGC_SIGHUP, CONN_AUTH_SECURITY,
1630                         gettext_noop("Sets the maximum allowed time to complete client authentication."),
1631                         NULL,
1632                         GUC_UNIT_S
1633                 },
1634                 &AuthenticationTimeout,
1635                 60, 1, 600, NULL, NULL
1636         },
1637
1638         {
1639                 /* Not for general use */
1640                 {"pre_auth_delay", PGC_SIGHUP, DEVELOPER_OPTIONS,
1641                         gettext_noop("Waits N seconds on connection startup before authentication."),
1642                         gettext_noop("This allows attaching a debugger to the process."),
1643                         GUC_NOT_IN_SAMPLE | GUC_UNIT_S
1644                 },
1645                 &PreAuthDelay,
1646                 0, 0, 60, NULL, NULL
1647         },
1648
1649         {
1650                 {"checkpoint_segments", PGC_SIGHUP, WAL_CHECKPOINTS,
1651                         gettext_noop("Sets the maximum distance in log segments between automatic WAL checkpoints."),
1652                         NULL
1653                 },
1654                 &CheckPointSegments,
1655                 3, 1, INT_MAX, NULL, NULL
1656         },
1657
1658         {
1659                 {"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS,
1660                         gettext_noop("Sets the maximum time between automatic WAL checkpoints."),
1661                         NULL,
1662                         GUC_UNIT_S
1663                 },
1664                 &CheckPointTimeout,
1665                 300, 30, 3600, NULL, NULL
1666         },
1667
1668         {
1669                 {"checkpoint_warning", PGC_SIGHUP, WAL_CHECKPOINTS,
1670                         gettext_noop("Enables warnings if checkpoint segments are filled more "
1671                                                  "frequently than this."),
1672                         gettext_noop("Write a message to the server log if checkpoints "
1673                         "caused by the filling of checkpoint segment files happens more "
1674                                                  "frequently than this number of seconds. Zero turns off the warning."),
1675                         GUC_UNIT_S
1676                 },
1677                 &CheckPointWarning,
1678                 30, 0, INT_MAX, NULL, NULL
1679         },
1680
1681         {
1682                 {"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
1683                         gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
1684                         NULL,
1685                         GUC_UNIT_XBLOCKS
1686                 },
1687                 &XLOGbuffers,
1688                 8, 4, INT_MAX, NULL, NULL
1689         },
1690
1691         {
1692                 {"wal_writer_delay", PGC_SIGHUP, WAL_SETTINGS,
1693                         gettext_noop("WAL writer sleep time between WAL flushes."),
1694                         NULL,
1695                         GUC_UNIT_MS
1696                 },
1697                 &WalWriterDelay,
1698                 200, 1, 10000, NULL, NULL
1699         },
1700
1701         {
1702                 /* see max_connections */
1703                 {"max_wal_senders", PGC_POSTMASTER, WAL_REPLICATION,
1704                         gettext_noop("Sets the maximum number of simultaneously running WAL sender processes."),
1705                         NULL
1706                 },
1707                 &MaxWalSenders,
1708                 0, 0, INT_MAX / 4, NULL, NULL
1709         },
1710
1711         {
1712                 {"wal_sender_delay", PGC_SIGHUP, WAL_REPLICATION,
1713                         gettext_noop("WAL sender sleep time between WAL replications."),
1714                         NULL,
1715                         GUC_UNIT_MS
1716                 },
1717                 &WalSndDelay,
1718                 200, 1, 10000, NULL, NULL
1719         },
1720
1721         {
1722                 {"commit_delay", PGC_USERSET, WAL_SETTINGS,
1723                         gettext_noop("Sets the delay in microseconds between transaction commit and "
1724                                                  "flushing WAL to disk."),
1725                         NULL
1726                 },
1727                 &CommitDelay,
1728                 0, 0, 100000, NULL, NULL
1729         },
1730
1731         {
1732                 {"commit_siblings", PGC_USERSET, WAL_SETTINGS,
1733                         gettext_noop("Sets the minimum concurrent open transactions before performing "
1734                                                  "commit_delay."),
1735                         NULL
1736                 },
1737                 &CommitSiblings,
1738                 5, 1, 1000, NULL, NULL
1739         },
1740
1741         {
1742                 {"extra_float_digits", PGC_USERSET, CLIENT_CONN_LOCALE,
1743                         gettext_noop("Sets the number of digits displayed for floating-point values."),
1744                         gettext_noop("This affects real, double precision, and geometric data types. "
1745                          "The parameter value is added to the standard number of digits "
1746                                                  "(FLT_DIG or DBL_DIG as appropriate).")
1747                 },
1748                 &extra_float_digits,
1749                 0, -15, 3, NULL, NULL
1750         },
1751
1752         {
1753                 {"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN,
1754                         gettext_noop("Sets the minimum execution time above which "
1755                                                  "statements will be logged."),
1756                         gettext_noop("Zero prints all queries. -1 turns this feature off."),
1757                         GUC_UNIT_MS
1758                 },
1759                 &log_min_duration_statement,
1760                 -1, -1, INT_MAX / 1000, NULL, NULL
1761         },
1762
1763         {
1764                 {"log_autovacuum_min_duration", PGC_SIGHUP, LOGGING_WHAT,
1765                         gettext_noop("Sets the minimum execution time above which "
1766                                                  "autovacuum actions will be logged."),
1767                         gettext_noop("Zero prints all actions. -1 turns autovacuum logging off."),
1768                         GUC_UNIT_MS
1769                 },
1770                 &Log_autovacuum_min_duration,
1771                 -1, -1, INT_MAX / 1000, NULL, NULL
1772         },
1773
1774         {
1775                 {"bgwriter_delay", PGC_SIGHUP, RESOURCES,
1776                         gettext_noop("Background writer sleep time between rounds."),
1777                         NULL,
1778                         GUC_UNIT_MS
1779                 },
1780                 &BgWriterDelay,
1781                 200, 10, 10000, NULL, NULL
1782         },
1783
1784         {
1785                 {"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES,
1786                         gettext_noop("Background writer maximum number of LRU pages to flush per round."),
1787                         NULL
1788                 },
1789                 &bgwriter_lru_maxpages,
1790                 100, 0, 1000, NULL, NULL
1791         },
1792
1793         {
1794                 {"effective_io_concurrency",
1795 #ifdef USE_PREFETCH
1796                         PGC_USERSET,
1797 #else
1798                         PGC_INTERNAL,
1799 #endif
1800                         RESOURCES,
1801                         gettext_noop("Number of simultaneous requests that can be handled efficiently by the disk subsystem."),
1802                         gettext_noop("For RAID arrays, this should be approximately the number of drive spindles in the array.")
1803                 },
1804                 &effective_io_concurrency,
1805 #ifdef USE_PREFETCH
1806                 1, 0, 1000,
1807 #else
1808                 0, 0, 0,
1809 #endif
1810                 assign_effective_io_concurrency, NULL
1811         },
1812
1813         {
1814                 {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
1815                         gettext_noop("Automatic log file rotation will occur after N minutes."),
1816                         NULL,
1817                         GUC_UNIT_MIN
1818                 },
1819                 &Log_RotationAge,
1820                 HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / MINS_PER_HOUR, NULL, NULL
1821         },
1822
1823         {
1824                 {"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
1825                         gettext_noop("Automatic log file rotation will occur after N kilobytes."),
1826                         NULL,
1827                         GUC_UNIT_KB
1828                 },
1829                 &Log_RotationSize,
1830                 10 * 1024, 0, INT_MAX / 1024, NULL, NULL
1831         },
1832
1833         {
1834                 {"max_function_args", PGC_INTERNAL, PRESET_OPTIONS,
1835                         gettext_noop("Shows the maximum number of function arguments."),
1836                         NULL,
1837                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1838                 },
1839                 &max_function_args,
1840                 FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS, NULL, NULL
1841         },
1842
1843         {
1844                 {"max_index_keys", PGC_INTERNAL, PRESET_OPTIONS,
1845                         gettext_noop("Shows the maximum number of index keys."),
1846                         NULL,
1847                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1848                 },
1849                 &max_index_keys,
1850                 INDEX_MAX_KEYS, INDEX_MAX_KEYS, INDEX_MAX_KEYS, NULL, NULL
1851         },
1852
1853         {
1854                 {"max_identifier_length", PGC_INTERNAL, PRESET_OPTIONS,
1855                         gettext_noop("Shows the maximum identifier length."),
1856                         NULL,
1857                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1858                 },
1859                 &max_identifier_length,
1860                 NAMEDATALEN - 1, NAMEDATALEN - 1, NAMEDATALEN - 1, NULL, NULL
1861         },
1862
1863         {
1864                 {"block_size", PGC_INTERNAL, PRESET_OPTIONS,
1865                         gettext_noop("Shows the size of a disk block."),
1866                         NULL,
1867                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1868                 },
1869                 &block_size,
1870                 BLCKSZ, BLCKSZ, BLCKSZ, NULL, NULL
1871         },
1872
1873         {
1874                 {"segment_size", PGC_INTERNAL, PRESET_OPTIONS,
1875                         gettext_noop("Shows the number of pages per disk file."),
1876                         NULL,
1877                         GUC_UNIT_BLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1878                 },
1879                 &segment_size,
1880                 RELSEG_SIZE, RELSEG_SIZE, RELSEG_SIZE, NULL, NULL
1881         },
1882
1883         {
1884                 {"wal_block_size", PGC_INTERNAL, PRESET_OPTIONS,
1885                         gettext_noop("Shows the block size in the write ahead log."),
1886                         NULL,
1887                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1888                 },
1889                 &wal_block_size,
1890                 XLOG_BLCKSZ, XLOG_BLCKSZ, XLOG_BLCKSZ, NULL, NULL
1891         },
1892
1893         {
1894                 {"wal_segment_size", PGC_INTERNAL, PRESET_OPTIONS,
1895                         gettext_noop("Shows the number of pages per write ahead log segment."),
1896                         NULL,
1897                         GUC_UNIT_XBLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1898                 },
1899                 &wal_segment_size,
1900                 (XLOG_SEG_SIZE / XLOG_BLCKSZ),
1901                 (XLOG_SEG_SIZE / XLOG_BLCKSZ),
1902                 (XLOG_SEG_SIZE / XLOG_BLCKSZ),
1903                 NULL, NULL
1904         },
1905
1906         {
1907                 {"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
1908                         gettext_noop("Time to sleep between autovacuum runs."),
1909                         NULL,
1910                         GUC_UNIT_S
1911                 },
1912                 &autovacuum_naptime,
1913                 60, 1, INT_MAX / 1000, NULL, NULL
1914         },
1915         {
1916                 {"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
1917                         gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
1918                         NULL
1919                 },
1920                 &autovacuum_vac_thresh,
1921                 50, 0, INT_MAX, NULL, NULL
1922         },
1923         {
1924                 {"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
1925                         gettext_noop("Minimum number of tuple inserts, updates or deletes prior to analyze."),
1926                         NULL
1927                 },
1928                 &autovacuum_anl_thresh,
1929                 50, 0, INT_MAX, NULL, NULL
1930         },
1931         {
1932                 /* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
1933                 {"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
1934                         gettext_noop("Age at which to autovacuum a table to prevent transaction ID wraparound."),
1935                         NULL
1936                 },
1937                 &autovacuum_freeze_max_age,
1938                 /* see pg_resetxlog if you change the upper-limit value */
1939                 200000000, 100000000, 2000000000, NULL, NULL
1940         },
1941         {
1942                 /* see max_connections */
1943                 {"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
1944                         gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
1945                         NULL
1946                 },
1947                 &autovacuum_max_workers,
1948                 3, 1, INT_MAX / 4, assign_autovacuum_max_workers, NULL
1949         },
1950
1951         {
1952                 {"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER,
1953                         gettext_noop("Time between issuing TCP keepalives."),
1954                         gettext_noop("A value of 0 uses the system default."),
1955                         GUC_UNIT_S
1956                 },
1957                 &tcp_keepalives_idle,
1958                 0, 0, INT_MAX, assign_tcp_keepalives_idle, show_tcp_keepalives_idle
1959         },
1960
1961         {
1962                 {"tcp_keepalives_interval", PGC_USERSET, CLIENT_CONN_OTHER,
1963                         gettext_noop("Time between TCP keepalive retransmits."),
1964                         gettext_noop("A value of 0 uses the system default."),
1965                         GUC_UNIT_S
1966                 },
1967                 &tcp_keepalives_interval,
1968                 0, 0, INT_MAX, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
1969         },
1970
1971         {
1972                 {"tcp_keepalives_count", PGC_USERSET, CLIENT_CONN_OTHER,
1973                         gettext_noop("Maximum number of TCP keepalive retransmits."),
1974                         gettext_noop("This controls the number of consecutive keepalive retransmits that can be "
1975                                                  "lost before a connection is considered dead. A value of 0 uses the "
1976                                                  "system default."),
1977                 },
1978                 &tcp_keepalives_count,
1979                 0, 0, INT_MAX, assign_tcp_keepalives_count, show_tcp_keepalives_count
1980         },
1981
1982         {
1983                 {"gin_fuzzy_search_limit", PGC_USERSET, CLIENT_CONN_OTHER,
1984                         gettext_noop("Sets the maximum allowed result for exact search by GIN."),
1985                         NULL,
1986                         0
1987                 },
1988                 &GinFuzzySearchLimit,
1989                 0, 0, INT_MAX, NULL, NULL
1990         },
1991
1992         {
1993                 {"effective_cache_size", PGC_USERSET, QUERY_TUNING_COST,
1994                         gettext_noop("Sets the planner's assumption about the size of the disk cache."),
1995                         gettext_noop("That is, the portion of the kernel's disk cache that "
1996                                                  "will be used for PostgreSQL data files. This is measured in disk "
1997                                                  "pages, which are normally 8 kB each."),
1998                         GUC_UNIT_BLOCKS,
1999                 },
2000                 &effective_cache_size,
2001                 DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX, NULL, NULL
2002         },
2003
2004         {
2005                 /* Can't be set in postgresql.conf */
2006                 {"server_version_num", PGC_INTERNAL, PRESET_OPTIONS,
2007                         gettext_noop("Shows the server version as an integer."),
2008                         NULL,
2009                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2010                 },
2011                 &server_version_num,
2012                 PG_VERSION_NUM, PG_VERSION_NUM, PG_VERSION_NUM, NULL, NULL
2013         },
2014
2015         {
2016                 {"log_temp_files", PGC_SUSET, LOGGING_WHAT,
2017                         gettext_noop("Log the use of temporary files larger than this number of kilobytes."),
2018                         gettext_noop("Zero logs all files. The default is -1 (turning this feature off)."),
2019                         GUC_UNIT_KB
2020                 },
2021                 &log_temp_files,
2022                 -1, -1, INT_MAX, NULL, NULL
2023         },
2024
2025         {
2026                 {"track_activity_query_size", PGC_POSTMASTER, RESOURCES_MEM,
2027                         gettext_noop("Sets the size reserved for pg_stat_activity.current_query, in bytes."),
2028                         NULL,
2029                 },
2030                 &pgstat_track_activity_query_size,
2031                 1024, 100, 102400, NULL, NULL
2032         },
2033
2034         /* End-of-list marker */
2035         {
2036                 {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
2037         }
2038 };
2039
2040
2041 static struct config_real ConfigureNamesReal[] =
2042 {
2043         {
2044                 {"seq_page_cost", PGC_USERSET, QUERY_TUNING_COST,
2045                         gettext_noop("Sets the planner's estimate of the cost of a "
2046                                                  "sequentially fetched disk page."),
2047                         NULL
2048                 },
2049                 &seq_page_cost,
2050                 DEFAULT_SEQ_PAGE_COST, 0, DBL_MAX, NULL, NULL
2051         },
2052         {
2053                 {"random_page_cost", PGC_USERSET, QUERY_TUNING_COST,
2054                         gettext_noop("Sets the planner's estimate of the cost of a "
2055                                                  "nonsequentially fetched disk page."),
2056                         NULL
2057                 },
2058                 &random_page_cost,
2059                 DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX, NULL, NULL
2060         },
2061         {
2062                 {"cpu_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
2063                         gettext_noop("Sets the planner's estimate of the cost of "
2064                                                  "processing each tuple (row)."),
2065                         NULL
2066                 },
2067                 &cpu_tuple_cost,
2068                 DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX, NULL, NULL
2069         },
2070         {
2071                 {"cpu_index_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
2072                         gettext_noop("Sets the planner's estimate of the cost of "
2073                                                  "processing each index entry during an index scan."),
2074                         NULL
2075                 },
2076                 &cpu_index_tuple_cost,
2077                 DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX, NULL, NULL
2078         },
2079         {
2080                 {"cpu_operator_cost", PGC_USERSET, QUERY_TUNING_COST,
2081                         gettext_noop("Sets the planner's estimate of the cost of "
2082                                                  "processing each operator or function call."),
2083                         NULL
2084                 },
2085                 &cpu_operator_cost,
2086                 DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX, NULL, NULL
2087         },
2088
2089         {
2090                 {"cursor_tuple_fraction", PGC_USERSET, QUERY_TUNING_OTHER,
2091                         gettext_noop("Sets the planner's estimate of the fraction of "
2092                                                  "a cursor's rows that will be retrieved."),
2093                         NULL
2094                 },
2095                 &cursor_tuple_fraction,
2096                 DEFAULT_CURSOR_TUPLE_FRACTION, 0.0, 1.0, NULL, NULL
2097         },
2098
2099         {
2100                 {"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO,
2101                         gettext_noop("GEQO: selective pressure within the population."),
2102                         NULL
2103                 },
2104                 &Geqo_selection_bias,
2105                 DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS,
2106                 MAX_GEQO_SELECTION_BIAS, NULL, NULL
2107         },
2108         {
2109                 {"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
2110                         gettext_noop("GEQO: seed for random path selection."),
2111                         NULL
2112                 },
2113                 &Geqo_seed,
2114                 0.0, 0.0, 1.0, NULL, NULL
2115         },
2116
2117         {
2118                 {"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES,
2119                         gettext_noop("Multiple of the average buffer usage to free per round."),
2120                         NULL
2121                 },
2122                 &bgwriter_lru_multiplier,
2123                 2.0, 0.0, 10.0, NULL, NULL
2124         },
2125
2126         {
2127                 {"seed", PGC_USERSET, UNGROUPED,
2128                         gettext_noop("Sets the seed for random-number generation."),
2129                         NULL,
2130                         GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2131                 },
2132                 &phony_random_seed,
2133                 0.0, -1.0, 1.0, assign_random_seed, show_random_seed
2134         },
2135
2136         {
2137                 {"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
2138                         gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
2139                         NULL
2140                 },
2141                 &autovacuum_vac_scale,
2142                 0.2, 0.0, 100.0, NULL, NULL
2143         },
2144         {
2145                 {"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
2146                         gettext_noop("Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples."),
2147                         NULL
2148                 },
2149                 &autovacuum_anl_scale,
2150                 0.1, 0.0, 100.0, NULL, NULL
2151         },
2152
2153         {
2154                 {"checkpoint_completion_target", PGC_SIGHUP, WAL_CHECKPOINTS,
2155                         gettext_noop("Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."),
2156                         NULL
2157                 },
2158                 &CheckPointCompletionTarget,
2159                 0.5, 0.0, 1.0, NULL, NULL
2160         },
2161
2162         /* End-of-list marker */
2163         {
2164                 {NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL
2165         }
2166 };
2167
2168
2169 static struct config_string ConfigureNamesString[] =
2170 {
2171         {
2172                 {"archive_command", PGC_SIGHUP, WAL_SETTINGS,
2173                         gettext_noop("Sets the shell command that will be called to archive a WAL file."),
2174                         NULL
2175                 },
2176                 &XLogArchiveCommand,
2177                 "", NULL, show_archive_command
2178         },
2179
2180         {
2181                 {"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
2182                         gettext_noop("Sets the client's character set encoding."),
2183                         NULL,
2184                         GUC_IS_NAME | GUC_REPORT
2185                 },
2186                 &client_encoding_string,
2187                 "SQL_ASCII", assign_client_encoding, NULL
2188         },
2189
2190         {
2191                 {"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
2192                         gettext_noop("Controls information prefixed to each log line."),
2193                         gettext_noop("If blank, no prefix is used.")
2194                 },
2195                 &Log_line_prefix,
2196                 "", NULL, NULL
2197         },
2198
2199         {
2200                 {"log_timezone", PGC_SIGHUP, LOGGING_WHAT,
2201                         gettext_noop("Sets the time zone to use in log messages."),
2202                         NULL
2203                 },
2204                 &log_timezone_string,
2205                 "UNKNOWN", assign_log_timezone, show_log_timezone
2206         },
2207
2208         {
2209                 {"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
2210                         gettext_noop("Sets the display format for date and time values."),
2211                         gettext_noop("Also controls interpretation of ambiguous "
2212                                                  "date inputs."),
2213                         GUC_LIST_INPUT | GUC_REPORT
2214                 },
2215                 &datestyle_string,
2216                 "ISO, MDY", assign_datestyle, NULL
2217         },
2218
2219         {
2220                 {"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT,
2221                         gettext_noop("Sets the default tablespace to create tables and indexes in."),
2222                         gettext_noop("An empty string selects the database's default tablespace."),
2223                         GUC_IS_NAME
2224                 },
2225                 &default_tablespace,
2226                 "", assign_default_tablespace, NULL
2227         },
2228
2229         {
2230                 {"temp_tablespaces", PGC_USERSET, CLIENT_CONN_STATEMENT,
2231                         gettext_noop("Sets the tablespace(s) to use for temporary tables and sort files."),
2232                         NULL,
2233                         GUC_LIST_INPUT | GUC_LIST_QUOTE
2234                 },
2235                 &temp_tablespaces,
2236                 "", assign_temp_tablespaces, NULL
2237         },
2238
2239         {
2240                 {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
2241                         gettext_noop("Sets the path for dynamically loadable modules."),
2242                         gettext_noop("If a dynamically loadable module needs to be opened and "
2243                                                  "the specified name does not have a directory component (i.e., the "
2244                                                  "name does not contain a slash), the system will search this path for "
2245                                                  "the specified file."),
2246                         GUC_SUPERUSER_ONLY
2247                 },
2248                 &Dynamic_library_path,
2249                 "$libdir", NULL, NULL
2250         },
2251
2252         {
2253                 {"krb_server_keyfile", PGC_SIGHUP, CONN_AUTH_SECURITY,
2254                         gettext_noop("Sets the location of the Kerberos server key file."),
2255                         NULL,
2256                         GUC_SUPERUSER_ONLY
2257                 },
2258                 &pg_krb_server_keyfile,
2259                 PG_KRB_SRVTAB, NULL, NULL
2260         },
2261
2262         {
2263                 {"krb_srvname", PGC_SIGHUP, CONN_AUTH_SECURITY,
2264                         gettext_noop("Sets the name of the Kerberos service."),
2265                         NULL
2266                 },
2267                 &pg_krb_srvnam,
2268                 PG_KRB_SRVNAM, NULL, NULL
2269         },
2270
2271         {
2272                 {"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2273                         gettext_noop("Sets the Bonjour service name."),
2274                         NULL
2275                 },
2276                 &bonjour_name,
2277                 "", NULL, NULL
2278         },
2279
2280         /* See main.c about why defaults for LC_foo are not all alike */
2281
2282         {
2283                 {"lc_collate", PGC_INTERNAL, CLIENT_CONN_LOCALE,
2284                         gettext_noop("Shows the collation order locale."),
2285                         NULL,
2286                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2287                 },
2288                 &locale_collate,
2289                 "C", NULL, NULL
2290         },
2291
2292         {
2293                 {"lc_ctype", PGC_INTERNAL, CLIENT_CONN_LOCALE,
2294                         gettext_noop("Shows the character classification and case conversion locale."),
2295                         NULL,
2296                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2297                 },
2298                 &locale_ctype,
2299                 "C", NULL, NULL
2300         },
2301
2302         {
2303                 {"lc_messages", PGC_SUSET, CLIENT_CONN_LOCALE,
2304                         gettext_noop("Sets the language in which messages are displayed."),
2305                         NULL
2306                 },
2307                 &locale_messages,
2308                 "", locale_messages_assign, NULL
2309         },
2310
2311         {
2312                 {"lc_monetary", PGC_USERSET, CLIENT_CONN_LOCALE,
2313                         gettext_noop("Sets the locale for formatting monetary amounts."),
2314                         NULL
2315                 },
2316                 &locale_monetary,
2317                 "C", locale_monetary_assign, NULL
2318         },
2319
2320         {
2321                 {"lc_numeric", PGC_USERSET, CLIENT_CONN_LOCALE,
2322                         gettext_noop("Sets the locale for formatting numbers."),
2323                         NULL
2324                 },
2325                 &locale_numeric,
2326                 "C", locale_numeric_assign, NULL
2327         },
2328
2329         {
2330                 {"lc_time", PGC_USERSET, CLIENT_CONN_LOCALE,
2331                         gettext_noop("Sets the locale for formatting date and time values."),
2332                         NULL
2333                 },
2334                 &locale_time,
2335                 "C", locale_time_assign, NULL
2336         },
2337
2338         {
2339                 {"shared_preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
2340                         gettext_noop("Lists shared libraries to preload into server."),
2341                         NULL,
2342                         GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
2343                 },
2344                 &shared_preload_libraries_string,
2345                 "", NULL, NULL
2346         },
2347
2348         {
2349                 {"local_preload_libraries", PGC_BACKEND, CLIENT_CONN_OTHER,
2350                         gettext_noop("Lists shared libraries to preload into each backend."),
2351                         NULL,
2352                         GUC_LIST_INPUT | GUC_LIST_QUOTE
2353                 },
2354                 &local_preload_libraries_string,
2355                 "", NULL, NULL
2356         },
2357
2358         {
2359                 {"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT,
2360                         gettext_noop("Sets the schema search order for names that are not schema-qualified."),
2361                         NULL,
2362                         GUC_LIST_INPUT | GUC_LIST_QUOTE
2363                 },
2364                 &namespace_search_path,
2365                 "\"$user\",public", assign_search_path, NULL
2366         },
2367
2368         {
2369                 /* Can't be set in postgresql.conf */
2370                 {"server_encoding", PGC_INTERNAL, CLIENT_CONN_LOCALE,
2371                         gettext_noop("Sets the server (database) character set encoding."),
2372                         NULL,
2373                         GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2374                 },
2375                 &server_encoding_string,
2376                 "SQL_ASCII", NULL, NULL
2377         },
2378
2379         {
2380                 /* Can't be set in postgresql.conf */
2381                 {"server_version", PGC_INTERNAL, PRESET_OPTIONS,
2382                         gettext_noop("Shows the server version."),
2383                         NULL,
2384                         GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2385                 },
2386                 &server_version_string,
2387                 PG_VERSION, NULL, NULL
2388         },
2389
2390         {
2391                 /* Not for general use --- used by SET ROLE */
2392                 {"role", PGC_USERSET, UNGROUPED,
2393                         gettext_noop("Sets the current role."),
2394                         NULL,
2395                         GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
2396                 },
2397                 &role_string,
2398                 "none", assign_role, show_role
2399         },
2400
2401         {
2402                 /* Not for general use --- used by SET SESSION AUTHORIZATION */
2403                 {"session_authorization", PGC_USERSET, UNGROUPED,
2404                         gettext_noop("Sets the session user name."),
2405                         NULL,
2406                         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
2407                 },
2408                 &session_authorization_string,
2409                 NULL, assign_session_authorization, show_session_authorization
2410         },
2411
2412         {
2413                 {"log_destination", PGC_SIGHUP, LOGGING_WHERE,
2414                         gettext_noop("Sets the destination for server log output."),
2415                         gettext_noop("Valid values are combinations of \"stderr\", "
2416                                                  "\"syslog\", \"csvlog\", and \"eventlog\", "
2417                                                  "depending on the platform."),
2418                         GUC_LIST_INPUT
2419                 },
2420                 &log_destination_string,
2421                 "stderr", assign_log_destination, NULL
2422         },
2423         {
2424                 {"log_directory", PGC_SIGHUP, LOGGING_WHERE,
2425                         gettext_noop("Sets the destination directory for log files."),
2426                         gettext_noop("Can be specified as relative to the data directory "
2427                                                  "or as absolute path."),
2428                         GUC_SUPERUSER_ONLY
2429                 },
2430                 &Log_directory,
2431                 "pg_log", assign_canonical_path, NULL
2432         },
2433         {
2434                 {"log_filename", PGC_SIGHUP, LOGGING_WHERE,
2435                         gettext_noop("Sets the file name pattern for log files."),
2436                         NULL,
2437                         GUC_SUPERUSER_ONLY
2438                 },
2439                 &Log_filename,
2440                 "postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL
2441         },
2442
2443 #ifdef HAVE_SYSLOG
2444         {
2445                 {"syslog_ident", PGC_SIGHUP, LOGGING_WHERE,
2446                         gettext_noop("Sets the program name used to identify PostgreSQL "
2447                                                  "messages in syslog."),
2448                         NULL
2449                 },
2450                 &syslog_ident_str,
2451                 "postgres", assign_syslog_ident, NULL
2452         },
2453 #endif
2454
2455         {
2456                 {"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
2457                         gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
2458                         NULL,
2459                         GUC_REPORT
2460                 },
2461                 &timezone_string,
2462                 "UNKNOWN", assign_timezone, show_timezone
2463         },
2464         {
2465                 {"timezone_abbreviations", PGC_USERSET, CLIENT_CONN_LOCALE,
2466                         gettext_noop("Selects a file of time zone abbreviations."),
2467                         NULL
2468                 },
2469                 &timezone_abbreviations_string,
2470                 "UNKNOWN", assign_timezone_abbreviations, NULL
2471         },
2472
2473         {
2474                 {"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
2475                         gettext_noop("Sets the current transaction's isolation level."),
2476                         NULL,
2477                         GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2478                 },
2479                 &XactIsoLevel_string,
2480                 NULL, assign_XactIsoLevel, show_XactIsoLevel
2481         },
2482
2483         {
2484                 {"unix_socket_group", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2485                         gettext_noop("Sets the owning group of the Unix-domain socket."),
2486                         gettext_noop("The owning user of the socket is always the user "
2487                                                  "that starts the server.")
2488                 },
2489                 &Unix_socket_group,
2490                 "", NULL, NULL
2491         },
2492
2493         {
2494                 {"unix_socket_directory", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2495                         gettext_noop("Sets the directory where the Unix-domain socket will be created."),
2496                         NULL,
2497                         GUC_SUPERUSER_ONLY
2498                 },
2499                 &UnixSocketDir,
2500                 "", assign_canonical_path, NULL
2501         },
2502
2503         {
2504                 {"listen_addresses", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2505                         gettext_noop("Sets the host name or IP address(es) to listen to."),
2506                         NULL,
2507                         GUC_LIST_INPUT
2508                 },
2509                 &ListenAddresses,
2510                 "localhost", NULL, NULL
2511         },
2512
2513         {
2514                 {"custom_variable_classes", PGC_SIGHUP, CUSTOM_OPTIONS,
2515                         gettext_noop("Sets the list of known custom variable classes."),
2516                         NULL,
2517                         GUC_LIST_INPUT | GUC_LIST_QUOTE
2518                 },
2519                 &custom_variable_classes,
2520                 NULL, assign_custom_variable_classes, NULL
2521         },
2522
2523         {
2524                 {"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
2525                         gettext_noop("Sets the server's data directory."),
2526                         NULL,
2527                         GUC_SUPERUSER_ONLY
2528                 },
2529                 &data_directory,
2530                 NULL, NULL, NULL
2531         },
2532
2533         {
2534                 {"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
2535                         gettext_noop("Sets the server's main configuration file."),
2536                         NULL,
2537                         GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
2538                 },
2539                 &ConfigFileName,
2540                 NULL, NULL, NULL
2541         },
2542
2543         {
2544                 {"hba_file", PGC_POSTMASTER, FILE_LOCATIONS,
2545                         gettext_noop("Sets the server's \"hba\" configuration file."),
2546                         NULL,
2547                         GUC_SUPERUSER_ONLY
2548                 },
2549                 &HbaFileName,
2550                 NULL, NULL, NULL
2551         },
2552
2553         {
2554                 {"ident_file", PGC_POSTMASTER, FILE_LOCATIONS,
2555                         gettext_noop("Sets the server's \"ident\" configuration file."),
2556                         NULL,
2557                         GUC_SUPERUSER_ONLY
2558                 },
2559                 &IdentFileName,
2560                 NULL, NULL, NULL
2561         },
2562
2563         {
2564                 {"external_pid_file", PGC_POSTMASTER, FILE_LOCATIONS,
2565                         gettext_noop("Writes the postmaster PID to the specified file."),
2566                         NULL,
2567                         GUC_SUPERUSER_ONLY
2568                 },
2569                 &external_pid_file,
2570                 NULL, assign_canonical_path, NULL
2571         },
2572
2573         {
2574                 {"stats_temp_directory", PGC_SIGHUP, STATS_COLLECTOR,
2575                         gettext_noop("Writes temporary statistics files to the specified directory."),
2576                         NULL,
2577                         GUC_SUPERUSER_ONLY
2578                 },
2579                 &pgstat_temp_directory,
2580                 "pg_stat_tmp", assign_pgstat_temp_directory, NULL
2581         },
2582
2583         {
2584                 {"default_text_search_config", PGC_USERSET, CLIENT_CONN_LOCALE,
2585                         gettext_noop("Sets default text search configuration."),
2586                         NULL
2587                 },
2588                 &TSCurrentConfig,
2589                 "pg_catalog.simple", assignTSCurrentConfig, NULL
2590         },
2591
2592 #ifdef USE_SSL
2593         {
2594                 {"ssl_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY,
2595                         gettext_noop("Sets the list of allowed SSL ciphers."),
2596                         NULL,
2597                         GUC_SUPERUSER_ONLY
2598                 },
2599                 &SSLCipherSuites,
2600                 "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH", NULL, NULL
2601         },
2602 #endif   /* USE_SSL */
2603
2604         {
2605                 {"application_name", PGC_USERSET, LOGGING,
2606                  gettext_noop("Sets the application name to be reported in statistics and logs."),
2607                  NULL,
2608                  GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE
2609                 },
2610                 &application_name,
2611                 "", assign_application_name, NULL
2612         },
2613
2614         /* End-of-list marker */
2615         {
2616                 {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
2617         }
2618 };
2619
2620
2621 static struct config_enum ConfigureNamesEnum[] =
2622 {
2623         {
2624                 {"backslash_quote", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
2625                         gettext_noop("Sets whether \"\\'\" is allowed in string literals."),
2626                         NULL
2627                 },
2628                 &backslash_quote,
2629                 BACKSLASH_QUOTE_SAFE_ENCODING, backslash_quote_options, NULL, NULL
2630         },
2631
2632         {
2633                 {"bytea_output", PGC_USERSET, CLIENT_CONN_STATEMENT,
2634                         gettext_noop("Sets the output format for bytea."),
2635                         NULL
2636                 },
2637                 &bytea_output,
2638                 BYTEA_OUTPUT_HEX, bytea_output_options, NULL, NULL
2639         },
2640
2641         {
2642                 {"client_min_messages", PGC_USERSET, LOGGING_WHEN,
2643                         gettext_noop("Sets the message levels that are sent to the client."),
2644                         gettext_noop("Each level includes all the levels that follow it. The later"
2645                                                  " the level, the fewer messages are sent.")
2646                 },
2647                 &client_min_messages,
2648                 NOTICE, client_message_level_options, NULL, NULL
2649         },
2650
2651         {
2652                 {"constraint_exclusion", PGC_USERSET, QUERY_TUNING_OTHER,
2653                         gettext_noop("Enables the planner to use constraints to optimize queries."),
2654                         gettext_noop("Table scans will be skipped if their constraints"
2655                                                  " guarantee that no rows match the query.")
2656                 },
2657                 &constraint_exclusion,
2658                 CONSTRAINT_EXCLUSION_PARTITION, constraint_exclusion_options,
2659                 NULL, NULL
2660         },
2661
2662         {
2663                 {"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
2664                         gettext_noop("Sets the transaction isolation level of each new transaction."),
2665                         NULL
2666                 },
2667                 &DefaultXactIsoLevel,
2668                 XACT_READ_COMMITTED, isolation_level_options, NULL, NULL
2669         },
2670
2671         {
2672                 {"IntervalStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
2673                         gettext_noop("Sets the display format for interval values."),
2674                         NULL,
2675                         GUC_REPORT
2676                 },
2677                 &IntervalStyle,
2678                 INTSTYLE_POSTGRES, intervalstyle_options, NULL, NULL
2679         },
2680
2681         {
2682                 {"log_error_verbosity", PGC_SUSET, LOGGING_WHAT,
2683                         gettext_noop("Sets the verbosity of logged messages."),
2684                         NULL
2685                 },
2686                 &Log_error_verbosity,
2687                 PGERROR_DEFAULT, log_error_verbosity_options, NULL, NULL
2688         },
2689
2690         {
2691                 {"log_min_messages", PGC_SUSET, LOGGING_WHEN,
2692                         gettext_noop("Sets the message levels that are logged."),
2693                         gettext_noop("Each level includes all the levels that follow it. The later"
2694                                                  " the level, the fewer messages are sent.")
2695                 },
2696                 &log_min_messages,
2697                 WARNING, server_message_level_options, NULL, NULL
2698         },
2699
2700         {
2701                 {"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
2702                         gettext_noop("Causes all statements generating error at or above this level to be logged."),
2703                         gettext_noop("Each level includes all the levels that follow it. The later"
2704                                                  " the level, the fewer messages are sent.")
2705                 },
2706                 &log_min_error_statement,
2707                 ERROR, server_message_level_options, NULL, NULL
2708         },
2709
2710         {
2711                 {"log_statement", PGC_SUSET, LOGGING_WHAT,
2712                         gettext_noop("Sets the type of statements logged."),
2713                         NULL
2714                 },
2715                 &log_statement,
2716                 LOGSTMT_NONE, log_statement_options, NULL, NULL
2717         },
2718
2719 #ifdef HAVE_SYSLOG
2720         {
2721                 {"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
2722                         gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
2723                         NULL
2724                 },
2725                 &syslog_facility,
2726                 LOG_LOCAL0, syslog_facility_options, assign_syslog_facility, NULL
2727         },
2728 #endif
2729
2730         {
2731                 {"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
2732                         gettext_noop("Sets the session's behavior for triggers and rewrite rules."),
2733                         NULL
2734                 },
2735                 &SessionReplicationRole,
2736                 SESSION_REPLICATION_ROLE_ORIGIN, session_replication_role_options,
2737                 assign_session_replication_role, NULL
2738         },
2739
2740         {
2741                 {"trace_recovery_messages", PGC_SUSET, LOGGING_WHEN,
2742                         gettext_noop("Sets the message levels that are logged during recovery."),
2743                         gettext_noop("Each level includes all the levels that follow it. The later"
2744                                                  " the level, the fewer messages are sent.")
2745                 },
2746                 &trace_recovery_messages,
2747                 DEBUG1, server_message_level_options, NULL, NULL
2748         },
2749
2750         {
2751                 {"track_functions", PGC_SUSET, STATS_COLLECTOR,
2752                         gettext_noop("Collects function-level statistics on database activity."),
2753                         NULL
2754                 },
2755                 &pgstat_track_functions,
2756                 TRACK_FUNC_OFF, track_function_options, NULL, NULL
2757         },
2758
2759         {
2760                 {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
2761                         gettext_noop("Selects the method used for forcing WAL updates to disk."),
2762                         NULL
2763                 },
2764                 &sync_method,
2765                 DEFAULT_SYNC_METHOD, sync_method_options,
2766                 assign_xlog_sync_method, NULL
2767         },
2768
2769         {
2770                 {"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
2771                         gettext_noop("Sets how binary values are to be encoded in XML."),
2772                         NULL
2773                 },
2774                 &xmlbinary,
2775                 XMLBINARY_BASE64, xmlbinary_options, NULL, NULL
2776         },
2777
2778         {
2779                 {"xmloption", PGC_USERSET, CLIENT_CONN_STATEMENT,
2780                         gettext_noop("Sets whether XML data in implicit parsing and serialization "
2781                                                  "operations is to be considered as documents or content fragments."),
2782                         NULL
2783                 },
2784                 &xmloption,
2785                 XMLOPTION_CONTENT, xmloption_options, NULL, NULL
2786         },
2787
2788
2789         /* End-of-list marker */
2790         {
2791                 {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL
2792         }
2793 };
2794
2795 /******** end of options list ********/
2796
2797
2798 /*
2799  * To allow continued support of obsolete names for GUC variables, we apply
2800  * the following mappings to any unrecognized name.  Note that an old name
2801  * should be mapped to a new one only if the new variable has very similar
2802  * semantics to the old.
2803  */
2804 static const char *const map_old_guc_names[] = {
2805         "sort_mem", "work_mem",
2806         "vacuum_mem", "maintenance_work_mem",
2807         NULL
2808 };
2809
2810
2811 /*
2812  * Actual lookup of variables is done through this single, sorted array.
2813  */
2814 static struct config_generic **guc_variables;
2815
2816 /* Current number of variables contained in the vector */
2817 static int      num_guc_variables;
2818
2819 /* Vector capacity */
2820 static int      size_guc_variables;
2821
2822
2823 static bool guc_dirty;                  /* TRUE if need to do commit/abort work */
2824
2825 static bool reporting_enabled;  /* TRUE to enable GUC_REPORT */
2826
2827 static int      GUCNestLevel = 0;       /* 1 when in main transaction */
2828
2829
2830 static int      guc_var_compare(const void *a, const void *b);
2831 static int      guc_name_compare(const char *namea, const char *nameb);
2832 static void InitializeOneGUCOption(struct config_generic * gconf);
2833 static void push_old_value(struct config_generic * gconf, GucAction action);
2834 static void ReportGUCOption(struct config_generic * record);
2835 static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
2836 static void ShowAllGUCConfig(DestReceiver *dest);
2837 static char *_ShowOption(struct config_generic * record, bool use_units);
2838 static bool is_newvalue_equal(struct config_generic * record, const char *newvalue);
2839
2840
2841 /*
2842  * Some infrastructure for checking malloc/strdup/realloc calls
2843  */
2844 static void *
2845 guc_malloc(int elevel, size_t size)
2846 {
2847         void       *data;
2848
2849         data = malloc(size);
2850         if (data == NULL)
2851                 ereport(elevel,
2852                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2853                                  errmsg("out of memory")));
2854         return data;
2855 }
2856
2857 static void *
2858 guc_realloc(int elevel, void *old, size_t size)
2859 {
2860         void       *data;
2861
2862         data = realloc(old, size);
2863         if (data == NULL)
2864                 ereport(elevel,
2865                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2866                                  errmsg("out of memory")));
2867         return data;
2868 }
2869
2870 static char *
2871 guc_strdup(int elevel, const char *src)
2872 {
2873         char       *data;
2874
2875         data = strdup(src);
2876         if (data == NULL)
2877                 ereport(elevel,
2878                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2879                                  errmsg("out of memory")));
2880         return data;
2881 }
2882
2883
2884 /*
2885  * Support for assigning to a field of a string GUC item.  Free the prior
2886  * value if it's not referenced anywhere else in the item (including stacked
2887  * states).
2888  */
2889 static void
2890 set_string_field(struct config_string * conf, char **field, char *newval)
2891 {
2892         char       *oldval = *field;
2893         GucStack   *stack;
2894
2895         /* Do the assignment */
2896         *field = newval;
2897
2898         /* Exit if any duplicate references, or if old value was NULL anyway */
2899         if (oldval == NULL ||
2900                 oldval == *(conf->variable) ||
2901                 oldval == conf->reset_val ||
2902                 oldval == conf->boot_val)
2903                 return;
2904         for (stack = conf->gen.stack; stack; stack = stack->prev)
2905         {
2906                 if (oldval == stack->prior.stringval ||
2907                         oldval == stack->masked.stringval)
2908                         return;
2909         }
2910
2911         /* Not used anymore, so free it */
2912         free(oldval);
2913 }
2914
2915 /*
2916  * Detect whether strval is referenced anywhere in a GUC string item
2917  */
2918 static bool
2919 string_field_used(struct config_string * conf, char *strval)
2920 {
2921         GucStack   *stack;
2922
2923         if (strval == *(conf->variable) ||
2924                 strval == conf->reset_val ||
2925                 strval == conf->boot_val)
2926                 return true;
2927         for (stack = conf->gen.stack; stack; stack = stack->prev)
2928         {
2929                 if (strval == stack->prior.stringval ||
2930                         strval == stack->masked.stringval)
2931                         return true;
2932         }
2933         return false;
2934 }
2935
2936 /*
2937  * Support for copying a variable's active value into a stack entry
2938  */
2939 static void
2940 set_stack_value(struct config_generic * gconf, union config_var_value * val)
2941 {
2942         switch (gconf->vartype)
2943         {
2944                 case PGC_BOOL:
2945                         val->boolval =
2946                                 *((struct config_bool *) gconf)->variable;
2947                         break;
2948                 case PGC_INT:
2949                         val->intval =
2950                                 *((struct config_int *) gconf)->variable;
2951                         break;
2952                 case PGC_REAL:
2953                         val->realval =
2954                                 *((struct config_real *) gconf)->variable;
2955                         break;
2956                 case PGC_STRING:
2957                         /* we assume stringval is NULL if not valid */
2958                         set_string_field((struct config_string *) gconf,
2959                                                          &(val->stringval),
2960                                                          *((struct config_string *) gconf)->variable);
2961                         break;
2962                 case PGC_ENUM:
2963                         val->enumval =
2964                                 *((struct config_enum *) gconf)->variable;
2965                         break;
2966         }
2967 }
2968
2969 /*
2970  * Support for discarding a no-longer-needed value in a stack entry
2971  */
2972 static void
2973 discard_stack_value(struct config_generic * gconf, union config_var_value * val)
2974 {
2975         switch (gconf->vartype)
2976         {
2977                 case PGC_BOOL:
2978                 case PGC_INT:
2979                 case PGC_REAL:
2980                 case PGC_ENUM:
2981                         /* no need to do anything */
2982                         break;
2983                 case PGC_STRING:
2984                         set_string_field((struct config_string *) gconf,
2985                                                          &(val->stringval),
2986                                                          NULL);
2987                         break;
2988         }
2989 }
2990
2991
2992 /*
2993  * Fetch the sorted array pointer (exported for help_config.c's use ONLY)
2994  */
2995 struct config_generic **
2996 get_guc_variables(void)
2997 {
2998         return guc_variables;
2999 }
3000
3001
3002 /*
3003  * Build the sorted array.      This is split out so that it could be
3004  * re-executed after startup (eg, we could allow loadable modules to
3005  * add vars, and then we'd need to re-sort).
3006  */
3007 void
3008 build_guc_variables(void)
3009 {
3010         int                     size_vars;
3011         int                     num_vars = 0;
3012         struct config_generic **guc_vars;
3013         int                     i;
3014
3015         for (i = 0; ConfigureNamesBool[i].gen.name; i++)
3016         {
3017                 struct config_bool *conf = &ConfigureNamesBool[i];
3018
3019                 /* Rather than requiring vartype to be filled in by hand, do this: */
3020                 conf->gen.vartype = PGC_BOOL;
3021                 num_vars++;
3022         }
3023
3024         for (i = 0; ConfigureNamesInt[i].gen.name; i++)
3025         {
3026                 struct config_int *conf = &ConfigureNamesInt[i];
3027
3028                 conf->gen.vartype = PGC_INT;
3029                 num_vars++;
3030         }
3031
3032         for (i = 0; ConfigureNamesReal[i].gen.name; i++)
3033         {
3034                 struct config_real *conf = &ConfigureNamesReal[i];
3035
3036                 conf->gen.vartype = PGC_REAL;
3037                 num_vars++;
3038         }
3039
3040         for (i = 0; ConfigureNamesString[i].gen.name; i++)
3041         {
3042                 struct config_string *conf = &ConfigureNamesString[i];
3043
3044                 conf->gen.vartype = PGC_STRING;
3045                 num_vars++;
3046         }
3047
3048         for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
3049         {
3050                 struct config_enum *conf = &ConfigureNamesEnum[i];
3051
3052                 conf->gen.vartype = PGC_ENUM;
3053                 num_vars++;
3054         }
3055
3056         /*
3057          * Create table with 20% slack
3058          */
3059         size_vars = num_vars + num_vars / 4;
3060
3061         guc_vars = (struct config_generic **)
3062                 guc_malloc(FATAL, size_vars * sizeof(struct config_generic *));
3063
3064         num_vars = 0;
3065
3066         for (i = 0; ConfigureNamesBool[i].gen.name; i++)
3067                 guc_vars[num_vars++] = &ConfigureNamesBool[i].gen;
3068
3069         for (i = 0; ConfigureNamesInt[i].gen.name; i++)
3070                 guc_vars[num_vars++] = &ConfigureNamesInt[i].gen;
3071
3072         for (i = 0; ConfigureNamesReal[i].gen.name; i++)
3073                 guc_vars[num_vars++] = &ConfigureNamesReal[i].gen;
3074
3075         for (i = 0; ConfigureNamesString[i].gen.name; i++)
3076                 guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
3077
3078         for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
3079                 guc_vars[num_vars++] = &ConfigureNamesEnum[i].gen;
3080
3081         if (guc_variables)
3082                 free(guc_variables);
3083         guc_variables = guc_vars;
3084         num_guc_variables = num_vars;
3085         size_guc_variables = size_vars;
3086         qsort((void *) guc_variables, num_guc_variables,
3087                   sizeof(struct config_generic *), guc_var_compare);
3088 }
3089
3090 /*
3091  * Add a new GUC variable to the list of known variables. The
3092  * list is expanded if needed.
3093  */
3094 static bool
3095 add_guc_variable(struct config_generic * var, int elevel)
3096 {
3097         if (num_guc_variables + 1 >= size_guc_variables)
3098         {
3099                 /*
3100                  * Increase the vector by 25%
3101                  */
3102                 int                     size_vars = size_guc_variables + size_guc_variables / 4;
3103                 struct config_generic **guc_vars;
3104
3105                 if (size_vars == 0)
3106                 {
3107                         size_vars = 100;
3108                         guc_vars = (struct config_generic **)
3109                                 guc_malloc(elevel, size_vars * sizeof(struct config_generic *));
3110                 }
3111                 else
3112                 {
3113                         guc_vars = (struct config_generic **)
3114                                 guc_realloc(elevel, guc_variables, size_vars * sizeof(struct config_generic *));
3115                 }
3116
3117                 if (guc_vars == NULL)
3118                         return false;           /* out of memory */
3119
3120                 guc_variables = guc_vars;
3121                 size_guc_variables = size_vars;
3122         }
3123         guc_variables[num_guc_variables++] = var;
3124         qsort((void *) guc_variables, num_guc_variables,
3125                   sizeof(struct config_generic *), guc_var_compare);
3126         return true;
3127 }
3128
3129 /*
3130  * Create and add a placeholder variable. It's presumed to belong
3131  * to a valid custom variable class at this point.
3132  */
3133 static struct config_generic *
3134 add_placeholder_variable(const char *name, int elevel)
3135 {
3136         size_t          sz = sizeof(struct config_string) + sizeof(char *);
3137         struct config_string *var;
3138         struct config_generic *gen;
3139
3140         var = (struct config_string *) guc_malloc(elevel, sz);
3141         if (var == NULL)
3142                 return NULL;
3143         memset(var, 0, sz);
3144         gen = &var->gen;
3145
3146         gen->name = guc_strdup(elevel, name);
3147         if (gen->name == NULL)
3148         {
3149                 free(var);
3150                 return NULL;
3151         }
3152
3153         gen->context = PGC_USERSET;
3154         gen->group = CUSTOM_OPTIONS;
3155         gen->short_desc = "GUC placeholder variable";
3156         gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER;
3157         gen->vartype = PGC_STRING;
3158
3159         /*
3160          * The char* is allocated at the end of the struct since we have no
3161          * 'static' place to point to.  Note that the current value, as well as
3162          * the boot and reset values, start out NULL.
3163          */
3164         var->variable = (char **) (var + 1);
3165
3166         if (!add_guc_variable((struct config_generic *) var, elevel))
3167         {
3168                 free((void *) gen->name);
3169                 free(var);
3170                 return NULL;
3171         }
3172
3173         return gen;
3174 }
3175
3176 /*
3177  * Detect whether the portion of "name" before dotPos matches any custom
3178  * variable class name listed in custom_var_classes.  The latter must be
3179  * formatted the way that assign_custom_variable_classes does it, ie,
3180  * no whitespace.  NULL is valid for custom_var_classes.
3181  */
3182 static bool
3183 is_custom_class(const char *name, int dotPos, const char *custom_var_classes)
3184 {
3185         bool            result = false;
3186         const char *ccs = custom_var_classes;
3187
3188         if (ccs != NULL)
3189         {
3190                 const char *start = ccs;
3191
3192                 for (;; ++ccs)
3193                 {
3194                         char            c = *ccs;
3195
3196                         if (c == '\0' || c == ',')
3197                         {
3198                                 if (dotPos == ccs - start && strncmp(start, name, dotPos) == 0)
3199                                 {
3200                                         result = true;
3201                                         break;
3202                                 }
3203                                 if (c == '\0')
3204                                         break;
3205                                 start = ccs + 1;
3206                         }
3207                 }
3208         }
3209         return result;
3210 }
3211
3212 /*
3213  * Look up option NAME.  If it exists, return a pointer to its record,
3214  * else return NULL.  If create_placeholders is TRUE, we'll create a
3215  * placeholder record for a valid-looking custom variable name.
3216  */
3217 static struct config_generic *
3218 find_option(const char *name, bool create_placeholders, int elevel)
3219 {
3220         const char **key = &name;
3221         struct config_generic **res;
3222         int                     i;
3223
3224         Assert(name);
3225
3226         /*
3227          * By equating const char ** with struct config_generic *, we are assuming
3228          * the name field is first in config_generic.
3229          */
3230         res = (struct config_generic **) bsearch((void *) &key,
3231                                                                                          (void *) guc_variables,
3232                                                                                          num_guc_variables,
3233                                                                                          sizeof(struct config_generic *),
3234                                                                                          guc_var_compare);
3235         if (res)
3236                 return *res;
3237
3238         /*
3239          * See if the name is an obsolete name for a variable.  We assume that the
3240          * set of supported old names is short enough that a brute-force search is
3241          * the best way.
3242          */
3243         for (i = 0; map_old_guc_names[i] != NULL; i += 2)
3244         {
3245                 if (guc_name_compare(name, map_old_guc_names[i]) == 0)
3246                         return find_option(map_old_guc_names[i + 1], false, elevel);
3247         }
3248
3249         if (create_placeholders)
3250         {
3251                 /*
3252                  * Check if the name is qualified, and if so, check if the qualifier
3253                  * matches any custom variable class.  If so, add a placeholder.
3254                  */
3255                 const char *dot = strchr(name, GUC_QUALIFIER_SEPARATOR);
3256
3257                 if (dot != NULL &&
3258                         is_custom_class(name, dot - name, custom_variable_classes))
3259                         return add_placeholder_variable(name, elevel);
3260         }
3261
3262         /* Unknown name */
3263         return NULL;
3264 }
3265
3266
3267 /*
3268  * comparator for qsorting and bsearching guc_variables array
3269  */
3270 static int
3271 guc_var_compare(const void *a, const void *b)
3272 {
3273         struct config_generic *confa = *(struct config_generic **) a;
3274         struct config_generic *confb = *(struct config_generic **) b;
3275
3276         return guc_name_compare(confa->name, confb->name);
3277 }
3278
3279 /*
3280  * the bare comparison function for GUC names
3281  */
3282 static int
3283 guc_name_compare(const char *namea, const char *nameb)
3284 {
3285         /*
3286          * The temptation to use strcasecmp() here must be resisted, because the
3287          * array ordering has to remain stable across setlocale() calls. So, build
3288          * our own with a simple ASCII-only downcasing.
3289          */
3290         while (*namea && *nameb)
3291         {
3292                 char            cha = *namea++;
3293                 char            chb = *nameb++;
3294
3295                 if (cha >= 'A' && cha <= 'Z')
3296                         cha += 'a' - 'A';
3297                 if (chb >= 'A' && chb <= 'Z')
3298                         chb += 'a' - 'A';
3299                 if (cha != chb)
3300                         return cha - chb;
3301         }
3302         if (*namea)
3303                 return 1;                               /* a is longer */
3304         if (*nameb)
3305                 return -1;                              /* b is longer */
3306         return 0;
3307 }
3308
3309
3310 /*
3311  * Initialize GUC options during program startup.
3312  *
3313  * Note that we cannot read the config file yet, since we have not yet
3314  * processed command-line switches.
3315  */
3316 void
3317 InitializeGUCOptions(void)
3318 {
3319         int                     i;
3320         char       *env;
3321         long            stack_rlimit;
3322
3323         /*
3324          * Before log_line_prefix could possibly receive a nonempty setting, make
3325          * sure that timezone processing is minimally alive (see elog.c).
3326          */
3327         pg_timezone_pre_initialize();
3328
3329         /*
3330          * Build sorted array of all GUC variables.
3331          */
3332         build_guc_variables();
3333
3334         /*
3335          * Load all variables with their compiled-in defaults, and initialize
3336          * status fields as needed.
3337          */
3338         for (i = 0; i < num_guc_variables; i++)
3339         {
3340                 InitializeOneGUCOption(guc_variables[i]);
3341         }
3342
3343         guc_dirty = false;
3344
3345         reporting_enabled = false;
3346
3347         /*
3348          * Prevent any attempt to override the transaction modes from
3349          * non-interactive sources.
3350          */
3351         SetConfigOption("transaction_isolation", "default",
3352                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
3353         SetConfigOption("transaction_read_only", "no",
3354                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
3355
3356         /*
3357          * For historical reasons, some GUC parameters can receive defaults from
3358          * environment variables.  Process those settings.      NB: if you add or
3359          * remove anything here, see also ProcessConfigFile().
3360          */
3361
3362         env = getenv("PGPORT");
3363         if (env != NULL)
3364                 SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
3365
3366         env = getenv("PGDATESTYLE");
3367         if (env != NULL)
3368                 SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
3369
3370         env = getenv("PGCLIENTENCODING");
3371         if (env != NULL)
3372                 SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
3373
3374         /*
3375          * rlimit isn't exactly an "environment variable", but it behaves about
3376          * the same.  If we can identify the platform stack depth rlimit, increase
3377          * default stack depth setting up to whatever is safe (but at most 2MB).
3378          */
3379         stack_rlimit = get_stack_depth_rlimit();
3380         if (stack_rlimit > 0)
3381         {
3382                 int                     new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;
3383
3384                 if (new_limit > 100)
3385                 {
3386                         char            limbuf[16];
3387
3388                         new_limit = Min(new_limit, 2048);
3389                         sprintf(limbuf, "%d", new_limit);
3390                         SetConfigOption("max_stack_depth", limbuf,
3391                                                         PGC_POSTMASTER, PGC_S_ENV_VAR);
3392                 }
3393         }
3394 }
3395
3396 /*
3397  * Initialize one GUC option variable to its compiled-in default.
3398  */
3399 static void
3400 InitializeOneGUCOption(struct config_generic * gconf)
3401 {
3402         gconf->status = 0;
3403         gconf->reset_source = PGC_S_DEFAULT;
3404         gconf->source = PGC_S_DEFAULT;
3405         gconf->stack = NULL;
3406         gconf->sourcefile = NULL;
3407         gconf->sourceline = 0;
3408
3409         switch (gconf->vartype)
3410         {
3411                 case PGC_BOOL:
3412                         {
3413                                 struct config_bool *conf = (struct config_bool *) gconf;
3414
3415                                 if (conf->assign_hook)
3416                                         if (!(*conf->assign_hook) (conf->boot_val, true,
3417                                                                                            PGC_S_DEFAULT))
3418                                                 elog(FATAL, "failed to initialize %s to %d",
3419                                                          conf->gen.name, (int) conf->boot_val);
3420                                 *conf->variable = conf->reset_val = conf->boot_val;
3421                                 break;
3422                         }
3423                 case PGC_INT:
3424                         {
3425                                 struct config_int *conf = (struct config_int *) gconf;
3426
3427                                 Assert(conf->boot_val >= conf->min);
3428                                 Assert(conf->boot_val <= conf->max);
3429                                 if (conf->assign_hook)
3430                                         if (!(*conf->assign_hook) (conf->boot_val, true,
3431                                                                                            PGC_S_DEFAULT))
3432                                                 elog(FATAL, "failed to initialize %s to %d",
3433                                                          conf->gen.name, conf->boot_val);
3434                                 *conf->variable = conf->reset_val = conf->boot_val;
3435                                 break;
3436                         }
3437                 case PGC_REAL:
3438                         {
3439                                 struct config_real *conf = (struct config_real *) gconf;
3440
3441                                 Assert(conf->boot_val >= conf->min);
3442                                 Assert(conf->boot_val <= conf->max);
3443                                 if (conf->assign_hook)
3444                                         if (!(*conf->assign_hook) (conf->boot_val, true,
3445                                                                                            PGC_S_DEFAULT))
3446                                                 elog(FATAL, "failed to initialize %s to %g",
3447                                                          conf->gen.name, conf->boot_val);
3448                                 *conf->variable = conf->reset_val = conf->boot_val;
3449                                 break;
3450                         }
3451                 case PGC_STRING:
3452                         {
3453                                 struct config_string *conf = (struct config_string *) gconf;
3454                                 char       *str;
3455
3456                                 *conf->variable = NULL;
3457                                 conf->reset_val = NULL;
3458
3459                                 if (conf->boot_val == NULL)
3460                                 {
3461                                         /* leave the value NULL, do not call assign hook */
3462                                         break;
3463                                 }
3464
3465                                 str = guc_strdup(FATAL, conf->boot_val);
3466                                 conf->reset_val = str;
3467
3468                                 if (conf->assign_hook)
3469                                 {
3470                                         const char *newstr;
3471
3472                                         newstr = (*conf->assign_hook) (str, true,
3473                                                                                                    PGC_S_DEFAULT);
3474                                         if (newstr == NULL)
3475                                         {
3476                                                 elog(FATAL, "failed to initialize %s to \"%s\"",
3477                                                          conf->gen.name, str);
3478                                         }
3479                                         else if (newstr != str)
3480                                         {
3481                                                 free(str);
3482
3483                                                 /*
3484                                                  * See notes in set_config_option about casting
3485                                                  */
3486                                                 str = (char *) newstr;
3487                                                 conf->reset_val = str;
3488                                         }
3489                                 }
3490                                 *conf->variable = str;
3491                                 break;
3492                         }
3493                 case PGC_ENUM:
3494                         {
3495                                 struct config_enum *conf = (struct config_enum *) gconf;
3496
3497                                 if (conf->assign_hook)
3498                                         if (!(*conf->assign_hook) (conf->boot_val, true,
3499                                                                                            PGC_S_DEFAULT))
3500                                                 elog(FATAL, "failed to initialize %s to %s",
3501                                                          conf->gen.name,
3502                                                   config_enum_lookup_by_value(conf, conf->boot_val));
3503                                 *conf->variable = conf->reset_val = conf->boot_val;
3504                                 break;
3505                         }
3506         }
3507 }
3508
3509
3510 /*
3511  * Select the configuration files and data directory to be used, and
3512  * do the initial read of postgresql.conf.
3513  *
3514  * This is called after processing command-line switches.
3515  *              userDoption is the -D switch value if any (NULL if unspecified).
3516  *              progname is just for use in error messages.
3517  *
3518  * Returns true on success; on failure, prints a suitable error message
3519  * to stderr and returns false.
3520  */
3521 bool
3522 SelectConfigFiles(const char *userDoption, const char *progname)
3523 {
3524         char       *configdir;
3525         char       *fname;
3526         struct stat stat_buf;
3527
3528         /* configdir is -D option, or $PGDATA if no -D */
3529         if (userDoption)
3530                 configdir = make_absolute_path(userDoption);
3531         else
3532                 configdir = make_absolute_path(getenv("PGDATA"));
3533
3534         /*
3535          * Find the configuration file: if config_file was specified on the
3536          * command line, use it, else use configdir/postgresql.conf.  In any case
3537          * ensure the result is an absolute path, so that it will be interpreted
3538          * the same way by future backends.
3539          */
3540         if (ConfigFileName)
3541                 fname = make_absolute_path(ConfigFileName);
3542         else if (configdir)
3543         {
3544                 fname = guc_malloc(FATAL,
3545                                                    strlen(configdir) + strlen(CONFIG_FILENAME) + 2);
3546                 sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);
3547         }
3548         else
3549         {
3550                 write_stderr("%s does not know where to find the server configuration file.\n"
3551                                          "You must specify the --config-file or -D invocation "
3552                                          "option or set the PGDATA environment variable.\n",
3553                                          progname);
3554                 return false;
3555         }
3556
3557         /*
3558          * Set the ConfigFileName GUC variable to its final value, ensuring that
3559          * it can't be overridden later.
3560          */
3561         SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
3562         free(fname);
3563
3564         /*
3565          * Now read the config file for the first time.
3566          */
3567         if (stat(ConfigFileName, &stat_buf) != 0)
3568         {
3569                 write_stderr("%s cannot access the server configuration file \"%s\": %s\n",
3570                                          progname, ConfigFileName, strerror(errno));
3571                 return false;
3572         }
3573
3574         ProcessConfigFile(PGC_POSTMASTER);
3575
3576         /*
3577          * If the data_directory GUC variable has been set, use that as DataDir;
3578          * otherwise use configdir if set; else punt.
3579          *
3580          * Note: SetDataDir will copy and absolute-ize its argument, so we don't
3581          * have to.
3582          */
3583         if (data_directory)
3584                 SetDataDir(data_directory);
3585         else if (configdir)
3586                 SetDataDir(configdir);
3587         else
3588         {
3589                 write_stderr("%s does not know where to find the database system data.\n"
3590                                          "This can be specified as \"data_directory\" in \"%s\", "
3591                                          "or by the -D invocation option, or by the "
3592                                          "PGDATA environment variable.\n",
3593                                          progname, ConfigFileName);
3594                 return false;
3595         }
3596
3597         /*
3598          * Reflect the final DataDir value back into the data_directory GUC var.
3599          * (If you are wondering why we don't just make them a single variable,
3600          * it's because the EXEC_BACKEND case needs DataDir to be transmitted to
3601          * child backends specially.  XXX is that still true?  Given that we now
3602          * chdir to DataDir, EXEC_BACKEND can read the config file without knowing
3603          * DataDir in advance.)
3604          */
3605         SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
3606
3607         /*
3608          * Figure out where pg_hba.conf is, and make sure the path is absolute.
3609          */
3610         if (HbaFileName)
3611                 fname = make_absolute_path(HbaFileName);
3612         else if (configdir)
3613         {
3614                 fname = guc_malloc(FATAL,
3615                                                    strlen(configdir) + strlen(HBA_FILENAME) + 2);
3616                 sprintf(fname, "%s/%s", configdir, HBA_FILENAME);
3617         }
3618         else
3619         {
3620                 write_stderr("%s does not know where to find the \"hba\" configuration file.\n"
3621                                          "This can be specified as \"hba_file\" in \"%s\", "
3622                                          "or by the -D invocation option, or by the "
3623                                          "PGDATA environment variable.\n",
3624                                          progname, ConfigFileName);
3625                 return false;
3626         }
3627         SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
3628         free(fname);
3629
3630         /*
3631          * Likewise for pg_ident.conf.
3632          */
3633         if (IdentFileName)
3634                 fname = make_absolute_path(IdentFileName);
3635         else if (configdir)
3636         {
3637                 fname = guc_malloc(FATAL,
3638                                                    strlen(configdir) + strlen(IDENT_FILENAME) + 2);
3639                 sprintf(fname, "%s/%s", configdir, IDENT_FILENAME);
3640         }
3641         else
3642         {
3643                 write_stderr("%s does not know where to find the \"ident\" configuration file.\n"
3644                                          "This can be specified as \"ident_file\" in \"%s\", "
3645                                          "or by the -D invocation option, or by the "
3646                                          "PGDATA environment variable.\n",
3647                                          progname, ConfigFileName);
3648                 return false;
3649         }
3650         SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
3651         free(fname);
3652
3653         free(configdir);
3654
3655         return true;
3656 }
3657
3658
3659 /*
3660  * Reset all options to their saved default values (implements RESET ALL)
3661  */
3662 void
3663 ResetAllOptions(void)
3664 {
3665         int                     i;
3666
3667         for (i = 0; i < num_guc_variables; i++)
3668         {
3669                 struct config_generic *gconf = guc_variables[i];
3670
3671                 /* Don't reset non-SET-able values */
3672                 if (gconf->context != PGC_SUSET &&
3673                         gconf->context != PGC_USERSET)
3674                         continue;
3675                 /* Don't reset if special exclusion from RESET ALL */
3676                 if (gconf->flags & GUC_NO_RESET_ALL)
3677                         continue;
3678                 /* No need to reset if wasn't SET */
3679                 if (gconf->source <= PGC_S_OVERRIDE)
3680                         continue;
3681
3682                 /* Save old value to support transaction abort */
3683                 push_old_value(gconf, GUC_ACTION_SET);
3684
3685                 switch (gconf->vartype)
3686                 {
3687                         case PGC_BOOL:
3688                                 {
3689                                         struct config_bool *conf = (struct config_bool *) gconf;
3690
3691                                         if (conf->assign_hook)
3692                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
3693                                                                                                    PGC_S_SESSION))
3694                                                         elog(ERROR, "failed to reset %s to %d",
3695                                                                  conf->gen.name, (int) conf->reset_val);
3696                                         *conf->variable = conf->reset_val;
3697                                         break;
3698                                 }
3699                         case PGC_INT:
3700                                 {
3701                                         struct config_int *conf = (struct config_int *) gconf;
3702
3703                                         if (conf->assign_hook)
3704                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
3705                                                                                                    PGC_S_SESSION))
3706                                                         elog(ERROR, "failed to reset %s to %d",
3707                                                                  conf->gen.name, conf->reset_val);
3708                                         *conf->variable = conf->reset_val;
3709                                         break;
3710                                 }
3711                         case PGC_REAL:
3712                                 {
3713                                         struct config_real *conf = (struct config_real *) gconf;
3714
3715                                         if (conf->assign_hook)
3716                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
3717                                                                                                    PGC_S_SESSION))
3718                                                         elog(ERROR, "failed to reset %s to %g",
3719                                                                  conf->gen.name, conf->reset_val);
3720                                         *conf->variable = conf->reset_val;
3721                                         break;
3722                                 }
3723                         case PGC_STRING:
3724                                 {
3725                                         struct config_string *conf = (struct config_string *) gconf;
3726                                         char       *str;
3727
3728                                         /* We need not strdup here */
3729                                         str = conf->reset_val;
3730
3731                                         if (conf->assign_hook && str)
3732                                         {
3733                                                 const char *newstr;
3734
3735                                                 newstr = (*conf->assign_hook) (str, true,
3736                                                                                                            PGC_S_SESSION);
3737                                                 if (newstr == NULL)
3738                                                         elog(ERROR, "failed to reset %s to \"%s\"",
3739                                                                  conf->gen.name, str);
3740                                                 else if (newstr != str)
3741                                                 {
3742                                                         /*
3743                                                          * See notes in set_config_option about casting
3744                                                          */
3745                                                         str = (char *) newstr;
3746                                                 }
3747                                         }
3748
3749                                         set_string_field(conf, conf->variable, str);
3750                                         break;
3751                                 }
3752                         case PGC_ENUM:
3753                                 {
3754                                         struct config_enum *conf = (struct config_enum *) gconf;
3755
3756                                         if (conf->assign_hook)
3757                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
3758                                                                                                    PGC_S_SESSION))
3759                                                         elog(ERROR, "failed to reset %s to %s",
3760                                                                  conf->gen.name,
3761                                                                  config_enum_lookup_by_value(conf, conf->reset_val));
3762                                         *conf->variable = conf->reset_val;
3763                                         break;
3764                                 }
3765                 }
3766
3767                 gconf->source = gconf->reset_source;
3768
3769                 if (gconf->flags & GUC_REPORT)
3770                         ReportGUCOption(gconf);
3771         }
3772 }
3773
3774
3775 /*
3776  * push_old_value
3777  *              Push previous state during transactional assignment to a GUC variable.
3778  */
3779 static void
3780 push_old_value(struct config_generic * gconf, GucAction action)
3781 {
3782         GucStack   *stack;
3783
3784         /* If we're not inside a nest level, do nothing */
3785         if (GUCNestLevel == 0)
3786                 return;
3787
3788         /* Do we already have a stack entry of the current nest level? */
3789         stack = gconf->stack;
3790         if (stack && stack->nest_level >= GUCNestLevel)
3791         {
3792                 /* Yes, so adjust its state if necessary */
3793                 Assert(stack->nest_level == GUCNestLevel);
3794                 switch (action)
3795                 {
3796                         case GUC_ACTION_SET:
3797                                 /* SET overrides any prior action at same nest level */
3798                                 if (stack->state == GUC_SET_LOCAL)
3799                                 {
3800                                         /* must discard old masked value */
3801                                         discard_stack_value(gconf, &stack->masked);
3802                                 }
3803                                 stack->state = GUC_SET;
3804                                 break;
3805                         case GUC_ACTION_LOCAL:
3806                                 if (stack->state == GUC_SET)
3807                                 {
3808                                         /* SET followed by SET LOCAL, remember SET's value */
3809                                         set_stack_value(gconf, &stack->masked);
3810                                         stack->state = GUC_SET_LOCAL;
3811                                 }
3812                                 /* in all other cases, no change to stack entry */
3813                                 break;
3814                         case GUC_ACTION_SAVE:
3815                                 /* Could only have a prior SAVE of same variable */
3816                                 Assert(stack->state == GUC_SAVE);
3817                                 break;
3818                 }
3819                 Assert(guc_dirty);              /* must be set already */
3820                 return;
3821         }
3822
3823         /*
3824          * Push a new stack entry
3825          *
3826          * We keep all the stack entries in TopTransactionContext for simplicity.
3827          */
3828         stack = (GucStack *) MemoryContextAllocZero(TopTransactionContext,
3829                                                                                                 sizeof(GucStack));
3830
3831         stack->prev = gconf->stack;
3832         stack->nest_level = GUCNestLevel;
3833         switch (action)
3834         {
3835                 case GUC_ACTION_SET:
3836                         stack->state = GUC_SET;
3837                         break;
3838                 case GUC_ACTION_LOCAL:
3839                         stack->state = GUC_LOCAL;
3840                         break;
3841                 case GUC_ACTION_SAVE:
3842                         stack->state = GUC_SAVE;
3843                         break;
3844         }
3845         stack->source = gconf->source;
3846         set_stack_value(gconf, &stack->prior);
3847
3848         gconf->stack = stack;
3849
3850         /* Ensure we remember to pop at end of xact */
3851         guc_dirty = true;
3852 }
3853
3854
3855 /*
3856  * Do GUC processing at main transaction start.
3857  */
3858 void
3859 AtStart_GUC(void)
3860 {
3861         /*
3862          * The nest level should be 0 between transactions; if it isn't, somebody
3863          * didn't call AtEOXact_GUC, or called it with the wrong nestLevel.  We
3864          * throw a warning but make no other effort to clean up.
3865          */
3866         if (GUCNestLevel != 0)
3867                 elog(WARNING, "GUC nest level = %d at transaction start",
3868                          GUCNestLevel);
3869         GUCNestLevel = 1;
3870 }
3871
3872 /*
3873  * Enter a new nesting level for GUC values.  This is called at subtransaction
3874  * start and when entering a function that has proconfig settings.      NOTE that
3875  * we must not risk error here, else subtransaction start will be unhappy.
3876  */
3877 int
3878 NewGUCNestLevel(void)
3879 {
3880         return ++GUCNestLevel;
3881 }
3882
3883 /*
3884  * Do GUC processing at transaction or subtransaction commit or abort, or
3885  * when exiting a function that has proconfig settings.  (The name is thus
3886  * a bit of a misnomer; perhaps it should be ExitGUCNestLevel or some such.)
3887  * During abort, we discard all GUC settings that were applied at nesting
3888  * levels >= nestLevel.  nestLevel == 1 corresponds to the main transaction.
3889  */
3890 void
3891 AtEOXact_GUC(bool isCommit, int nestLevel)
3892 {
3893         bool            still_dirty;
3894         int                     i;
3895
3896         /*
3897          * Note: it's possible to get here with GUCNestLevel == nestLevel-1 during
3898          * abort, if there is a failure during transaction start before
3899          * AtStart_GUC is called.
3900          */
3901         Assert(nestLevel > 0 &&
3902                    (nestLevel <= GUCNestLevel ||
3903                         (nestLevel == GUCNestLevel + 1 && !isCommit)));
3904
3905         /* Quick exit if nothing's changed in this transaction */
3906         if (!guc_dirty)
3907         {
3908                 GUCNestLevel = nestLevel - 1;
3909                 return;
3910         }
3911
3912         still_dirty = false;
3913         for (i = 0; i < num_guc_variables; i++)
3914         {
3915                 struct config_generic *gconf = guc_variables[i];
3916                 GucStack   *stack;
3917
3918                 /*
3919                  * Process and pop each stack entry within the nest level.      To
3920                  * simplify fmgr_security_definer(), we allow failure exit from a
3921                  * function-with-SET-options to be recovered at the surrounding
3922                  * transaction or subtransaction abort; so there could be more than
3923                  * one stack entry to pop.
3924                  */
3925                 while ((stack = gconf->stack) != NULL &&
3926                            stack->nest_level >= nestLevel)
3927                 {
3928                         GucStack   *prev = stack->prev;
3929                         bool            restorePrior = false;
3930                         bool            restoreMasked = false;
3931                         bool            changed;
3932
3933                         /*
3934                          * In this next bit, if we don't set either restorePrior or
3935                          * restoreMasked, we must "discard" any unwanted fields of the
3936                          * stack entries to avoid leaking memory.  If we do set one of
3937                          * those flags, unused fields will be cleaned up after restoring.
3938                          */
3939                         if (!isCommit)          /* if abort, always restore prior value */
3940                                 restorePrior = true;
3941                         else if (stack->state == GUC_SAVE)
3942                                 restorePrior = true;
3943                         else if (stack->nest_level == 1)
3944                         {
3945                                 /* transaction commit */
3946                                 if (stack->state == GUC_SET_LOCAL)
3947                                         restoreMasked = true;
3948                                 else if (stack->state == GUC_SET)
3949                                 {
3950                                         /* we keep the current active value */
3951                                         discard_stack_value(gconf, &stack->prior);
3952                                 }
3953                                 else    /* must be GUC_LOCAL */
3954                                         restorePrior = true;
3955                         }
3956                         else if (prev == NULL ||
3957                                          prev->nest_level < stack->nest_level - 1)
3958                         {
3959                                 /* decrement entry's level and do not pop it */
3960                                 stack->nest_level--;
3961                                 continue;
3962                         }
3963                         else
3964                         {
3965                                 /*
3966                                  * We have to merge this stack entry into prev. See README for
3967                                  * discussion of this bit.
3968                                  */
3969                                 switch (stack->state)
3970                                 {
3971                                         case GUC_SAVE:
3972                                                 Assert(false);  /* can't get here */
3973
3974                                         case GUC_SET:
3975                                                 /* next level always becomes SET */
3976                                                 discard_stack_value(gconf, &stack->prior);
3977                                                 if (prev->state == GUC_SET_LOCAL)
3978                                                         discard_stack_value(gconf, &prev->masked);
3979                                                 prev->state = GUC_SET;
3980                                                 break;
3981
3982                                         case GUC_LOCAL:
3983                                                 if (prev->state == GUC_SET)
3984                                                 {
3985                                                         /* LOCAL migrates down */
3986                                                         prev->masked = stack->prior;
3987                                                         prev->state = GUC_SET_LOCAL;
3988                                                 }
3989                                                 else
3990                                                 {
3991                                                         /* else just forget this stack level */
3992                                                         discard_stack_value(gconf, &stack->prior);
3993                                                 }
3994                                                 break;
3995
3996                                         case GUC_SET_LOCAL:
3997                                                 /* prior state at this level no longer wanted */
3998                                                 discard_stack_value(gconf, &stack->prior);
3999                                                 /* copy down the masked state */
4000                                                 if (prev->state == GUC_SET_LOCAL)
4001                                                         discard_stack_value(gconf, &prev->masked);
4002                                                 prev->masked = stack->masked;
4003                                                 prev->state = GUC_SET_LOCAL;
4004                                                 break;
4005                                 }
4006                         }
4007
4008                         changed = false;
4009
4010                         if (restorePrior || restoreMasked)
4011                         {
4012                                 /* Perform appropriate restoration of the stacked value */
4013                                 union config_var_value newvalue;
4014                                 GucSource       newsource;
4015
4016                                 if (restoreMasked)
4017                                 {
4018                                         newvalue = stack->masked;
4019                                         newsource = PGC_S_SESSION;
4020                                 }
4021                                 else
4022                                 {
4023                                         newvalue = stack->prior;
4024                                         newsource = stack->source;
4025                                 }
4026
4027                                 switch (gconf->vartype)
4028                                 {
4029                                         case PGC_BOOL:
4030                                                 {
4031                                                         struct config_bool *conf = (struct config_bool *) gconf;
4032                                                         bool            newval = newvalue.boolval;
4033
4034                                                         if (*conf->variable != newval)
4035                                                         {
4036                                                                 if (conf->assign_hook)
4037                                                                         if (!(*conf->assign_hook) (newval,
4038                                                                                                            true, PGC_S_OVERRIDE))
4039                                                                                 elog(LOG, "failed to commit %s as %d",
4040                                                                                          conf->gen.name, (int) newval);
4041                                                                 *conf->variable = newval;
4042                                                                 changed = true;
4043                                                         }
4044                                                         break;
4045                                                 }
4046                                         case PGC_INT:
4047                                                 {
4048                                                         struct config_int *conf = (struct config_int *) gconf;
4049                                                         int                     newval = newvalue.intval;
4050
4051                                                         if (*conf->variable != newval)
4052                                                         {
4053                                                                 if (conf->assign_hook)
4054                                                                         if (!(*conf->assign_hook) (newval,
4055                                                                                                            true, PGC_S_OVERRIDE))
4056                                                                                 elog(LOG, "failed to commit %s as %d",
4057                                                                                          conf->gen.name, newval);
4058                                                                 *conf->variable = newval;
4059                                                                 changed = true;
4060                                                         }
4061                                                         break;
4062                                                 }
4063                                         case PGC_REAL:
4064                                                 {
4065                                                         struct config_real *conf = (struct config_real *) gconf;
4066                                                         double          newval = newvalue.realval;
4067
4068                                                         if (*conf->variable != newval)
4069                                                         {
4070                                                                 if (conf->assign_hook)
4071                                                                         if (!(*conf->assign_hook) (newval,
4072                                                                                                            true, PGC_S_OVERRIDE))
4073                                                                                 elog(LOG, "failed to commit %s as %g",
4074                                                                                          conf->gen.name, newval);
4075                                                                 *conf->variable = newval;
4076                                                                 changed = true;
4077                                                         }
4078                                                         break;
4079                                                 }
4080                                         case PGC_STRING:
4081                                                 {
4082                                                         struct config_string *conf = (struct config_string *) gconf;
4083                                                         char       *newval = newvalue.stringval;
4084
4085                                                         if (*conf->variable != newval)
4086                                                         {
4087                                                                 if (conf->assign_hook && newval)
4088                                                                 {
4089                                                                         const char *newstr;
4090
4091                                                                         newstr = (*conf->assign_hook) (newval, true,
4092                                                                                                                          PGC_S_OVERRIDE);
4093                                                                         if (newstr == NULL)
4094                                                                                 elog(LOG, "failed to commit %s as \"%s\"",
4095                                                                                          conf->gen.name, newval);
4096                                                                         else if (newstr != newval)
4097                                                                         {
4098                                                                                 /*
4099                                                                                  * If newval should now be freed,
4100                                                                                  * it'll be taken care of below.
4101                                                                                  *
4102                                                                                  * See notes in set_config_option
4103                                                                                  * about casting
4104                                                                                  */
4105                                                                                 newval = (char *) newstr;
4106                                                                         }
4107                                                                 }
4108
4109                                                                 set_string_field(conf, conf->variable, newval);
4110                                                                 changed = true;
4111                                                         }
4112
4113                                                         /*
4114                                                          * Release stacked values if not used anymore. We
4115                                                          * could use discard_stack_value() here, but since
4116                                                          * we have type-specific code anyway, might as
4117                                                          * well inline it.
4118                                                          */
4119                                                         set_string_field(conf, &stack->prior.stringval, NULL);
4120                                                         set_string_field(conf, &stack->masked.stringval, NULL);
4121                                                         break;
4122                                                 }
4123                                         case PGC_ENUM:
4124                                                 {
4125                                                         struct config_enum *conf = (struct config_enum *) gconf;
4126                                                         int                     newval = newvalue.enumval;
4127
4128                                                         if (*conf->variable != newval)
4129                                                         {
4130                                                                 if (conf->assign_hook)
4131                                                                         if (!(*conf->assign_hook) (newval,
4132                                                                                                            true, PGC_S_OVERRIDE))
4133                                                                                 elog(LOG, "failed to commit %s as %s",
4134                                                                                          conf->gen.name,
4135                                                                                          config_enum_lookup_by_value(conf, newval));
4136                                                                 *conf->variable = newval;
4137                                                                 changed = true;
4138                                                         }
4139                                                         break;
4140                                                 }
4141                                 }
4142
4143                                 gconf->source = newsource;
4144                         }
4145
4146                         /* Finish popping the state stack */
4147                         gconf->stack = prev;
4148                         pfree(stack);
4149
4150                         /* Report new value if we changed it */
4151                         if (changed && (gconf->flags & GUC_REPORT))
4152                                 ReportGUCOption(gconf);
4153                 }                                               /* end of stack-popping loop */
4154
4155                 if (stack != NULL)
4156                         still_dirty = true;
4157         }
4158
4159         /* If there are no remaining stack entries, we can reset guc_dirty */
4160         guc_dirty = still_dirty;
4161
4162         /* Update nesting level */
4163         GUCNestLevel = nestLevel - 1;
4164 }
4165
4166
4167 /*
4168  * Start up automatic reporting of changes to variables marked GUC_REPORT.
4169  * This is executed at completion of backend startup.
4170  */
4171 void
4172 BeginReportingGUCOptions(void)
4173 {
4174         int                     i;
4175
4176         /*
4177          * Don't do anything unless talking to an interactive frontend of protocol
4178          * 3.0 or later.
4179          */
4180         if (whereToSendOutput != DestRemote ||
4181                 PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
4182                 return;
4183
4184         reporting_enabled = true;
4185
4186         /* Transmit initial values of interesting variables */
4187         for (i = 0; i < num_guc_variables; i++)
4188         {
4189                 struct config_generic *conf = guc_variables[i];
4190
4191                 if (conf->flags & GUC_REPORT)
4192                         ReportGUCOption(conf);
4193         }
4194 }
4195
4196 /*
4197  * ReportGUCOption: if appropriate, transmit option value to frontend
4198  */
4199 static void
4200 ReportGUCOption(struct config_generic * record)
4201 {
4202         if (reporting_enabled && (record->flags & GUC_REPORT))
4203         {
4204                 char       *val = _ShowOption(record, false);
4205                 StringInfoData msgbuf;
4206
4207                 pq_beginmessage(&msgbuf, 'S');
4208                 pq_sendstring(&msgbuf, record->name);
4209                 pq_sendstring(&msgbuf, val);
4210                 pq_endmessage(&msgbuf);
4211
4212                 pfree(val);
4213         }
4214 }
4215
4216 /*
4217  * Try to parse value as an integer.  The accepted formats are the
4218  * usual decimal, octal, or hexadecimal formats, optionally followed by
4219  * a unit name if "flags" indicates a unit is allowed.
4220  *
4221  * If the string parses okay, return true, else false.
4222  * If okay and result is not NULL, return the value in *result.
4223  * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
4224  *      HINT message, or NULL if no hint provided.
4225  */
4226 bool
4227 parse_int(const char *value, int *result, int flags, const char **hintmsg)
4228 {
4229         int64           val;
4230         char       *endptr;
4231
4232         /* To suppress compiler warnings, always set output params */
4233         if (result)
4234                 *result = 0;
4235         if (hintmsg)
4236                 *hintmsg = NULL;
4237
4238         /* We assume here that int64 is at least as wide as long */
4239         errno = 0;
4240         val = strtol(value, &endptr, 0);
4241
4242         if (endptr == value)
4243                 return false;                   /* no HINT for integer syntax error */
4244
4245         if (errno == ERANGE || val != (int64) ((int32) val))
4246         {
4247                 if (hintmsg)
4248                         *hintmsg = gettext_noop("Value exceeds integer range.");
4249                 return false;
4250         }
4251
4252         /* allow whitespace between integer and unit */
4253         while (isspace((unsigned char) *endptr))
4254                 endptr++;
4255
4256         /* Handle possible unit */
4257         if (*endptr != '\0')
4258         {
4259                 /*
4260                  * Note: the multiple-switch coding technique here is a bit tedious,
4261                  * but seems necessary to avoid intermediate-value overflows.
4262                  */
4263                 if (flags & GUC_UNIT_MEMORY)
4264                 {
4265                         /* Set hint for use if no match or trailing garbage */
4266                         if (hintmsg)
4267                                 *hintmsg = gettext_noop("Valid units for this parameter are \"kB\", \"MB\", and \"GB\".");
4268
4269 #if BLCKSZ < 1024 || BLCKSZ > (1024*1024)
4270 #error BLCKSZ must be between 1KB and 1MB
4271 #endif
4272 #if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024*1024)
4273 #error XLOG_BLCKSZ must be between 1KB and 1MB
4274 #endif
4275
4276                         if (strncmp(endptr, "kB", 2) == 0)
4277                         {
4278                                 endptr += 2;
4279                                 switch (flags & GUC_UNIT_MEMORY)
4280                                 {
4281                                         case GUC_UNIT_BLOCKS:
4282                                                 val /= (BLCKSZ / 1024);
4283                                                 break;
4284                                         case GUC_UNIT_XBLOCKS:
4285                                                 val /= (XLOG_BLCKSZ / 1024);
4286                                                 break;
4287                                 }
4288                         }
4289                         else if (strncmp(endptr, "MB", 2) == 0)
4290                         {
4291                                 endptr += 2;
4292                                 switch (flags & GUC_UNIT_MEMORY)
4293                                 {
4294                                         case GUC_UNIT_KB:
4295                                                 val *= KB_PER_MB;
4296                                                 break;
4297                                         case GUC_UNIT_BLOCKS:
4298                                                 val *= KB_PER_MB / (BLCKSZ / 1024);
4299                                                 break;
4300                                         case GUC_UNIT_XBLOCKS:
4301                                                 val *= KB_PER_MB / (XLOG_BLCKSZ / 1024);
4302                                                 break;
4303                                 }
4304                         }
4305                         else if (strncmp(endptr, "GB", 2) == 0)
4306                         {
4307                                 endptr += 2;
4308                                 switch (flags & GUC_UNIT_MEMORY)
4309                                 {
4310                                         case GUC_UNIT_KB:
4311                                                 val *= KB_PER_GB;
4312                                                 break;
4313                                         case GUC_UNIT_BLOCKS:
4314                                                 val *= KB_PER_GB / (BLCKSZ / 1024);
4315                                                 break;
4316                                         case GUC_UNIT_XBLOCKS:
4317                                                 val *= KB_PER_GB / (XLOG_BLCKSZ / 1024);
4318                                                 break;
4319                                 }
4320                         }
4321                 }
4322                 else if (flags & GUC_UNIT_TIME)
4323                 {
4324                         /* Set hint for use if no match or trailing garbage */
4325                         if (hintmsg)
4326                                 *hintmsg = gettext_noop("Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\".");
4327
4328                         if (strncmp(endptr, "ms", 2) == 0)
4329                         {
4330                                 endptr += 2;
4331                                 switch (flags & GUC_UNIT_TIME)
4332                                 {
4333                                         case GUC_UNIT_S:
4334                                                 val /= MS_PER_S;
4335                                                 break;
4336                                         case GUC_UNIT_MIN:
4337                                                 val /= MS_PER_MIN;
4338                                                 break;
4339                                 }
4340                         }
4341                         else if (strncmp(endptr, "s", 1) == 0)
4342                         {
4343                                 endptr += 1;
4344                                 switch (flags & GUC_UNIT_TIME)
4345                                 {
4346                                         case GUC_UNIT_MS:
4347                                                 val *= MS_PER_S;
4348                                                 break;
4349                                         case GUC_UNIT_MIN:
4350                                                 val /= S_PER_MIN;
4351                                                 break;
4352                                 }
4353                         }
4354                         else if (strncmp(endptr, "min", 3) == 0)
4355                         {
4356                                 endptr += 3;
4357                                 switch (flags & GUC_UNIT_TIME)
4358                                 {
4359                                         case GUC_UNIT_MS:
4360                                                 val *= MS_PER_MIN;
4361                                                 break;
4362                                         case GUC_UNIT_S:
4363                                                 val *= S_PER_MIN;
4364                                                 break;
4365                                 }
4366                         }
4367                         else if (strncmp(endptr, "h", 1) == 0)
4368                         {
4369                                 endptr += 1;
4370                                 switch (flags & GUC_UNIT_TIME)
4371                                 {
4372                                         case GUC_UNIT_MS:
4373                                                 val *= MS_PER_H;
4374                                                 break;
4375                                         case GUC_UNIT_S:
4376                                                 val *= S_PER_H;
4377                                                 break;
4378                                         case GUC_UNIT_MIN:
4379                                                 val *= MIN_PER_H;
4380                                                 break;
4381                                 }
4382                         }
4383                         else if (strncmp(endptr, "d", 1) == 0)
4384                         {
4385                                 endptr += 1;
4386                                 switch (flags & GUC_UNIT_TIME)
4387                                 {
4388                                         case GUC_UNIT_MS:
4389                                                 val *= MS_PER_D;
4390                                                 break;
4391                                         case GUC_UNIT_S:
4392                                                 val *= S_PER_D;
4393                                                 break;
4394                                         case GUC_UNIT_MIN:
4395                                                 val *= MIN_PER_D;
4396                                                 break;
4397                                 }
4398                         }
4399                 }
4400
4401                 /* allow whitespace after unit */
4402                 while (isspace((unsigned char) *endptr))
4403                         endptr++;
4404
4405                 if (*endptr != '\0')
4406                         return false;           /* appropriate hint, if any, already set */
4407
4408                 /* Check for overflow due to units conversion */
4409                 if (val != (int64) ((int32) val))
4410                 {
4411                         if (hintmsg)
4412                                 *hintmsg = gettext_noop("Value exceeds integer range.");
4413                         return false;
4414                 }
4415         }
4416
4417         if (result)
4418                 *result = (int) val;
4419         return true;
4420 }
4421
4422
4423
4424 /*
4425  * Try to parse value as a floating point number in the usual format.
4426  * If the string parses okay, return true, else false.
4427  * If okay and result is not NULL, return the value in *result.
4428  */
4429 bool
4430 parse_real(const char *value, double *result)
4431 {
4432         double          val;
4433         char       *endptr;
4434
4435         if (result)
4436                 *result = 0;                    /* suppress compiler warning */
4437
4438         errno = 0;
4439         val = strtod(value, &endptr);
4440         if (endptr == value || errno == ERANGE)
4441                 return false;
4442
4443         /* allow whitespace after number */
4444         while (isspace((unsigned char) *endptr))
4445                 endptr++;
4446         if (*endptr != '\0')
4447                 return false;
4448
4449         if (result)
4450                 *result = val;
4451         return true;
4452 }
4453
4454
4455 /*
4456  * Lookup the name for an enum option with the selected value.
4457  * Should only ever be called with known-valid values, so throws
4458  * an elog(ERROR) if the enum option is not found.
4459  *
4460  * The returned string is a pointer to static data and not
4461  * allocated for modification.
4462  */
4463 const char *
4464 config_enum_lookup_by_value(struct config_enum * record, int val)
4465 {
4466         const struct config_enum_entry *entry;
4467
4468         for (entry = record->options; entry && entry->name; entry++)
4469         {
4470                 if (entry->val == val)
4471                         return entry->name;
4472         }
4473
4474         elog(ERROR, "could not find enum option %d for %s",
4475                  val, record->gen.name);
4476         return NULL;                            /* silence compiler */
4477 }
4478
4479
4480 /*
4481  * Lookup the value for an enum option with the selected name
4482  * (case-insensitive).
4483  * If the enum option is found, sets the retval value and returns
4484  * true. If it's not found, return FALSE and retval is set to 0.
4485  */
4486 bool
4487 config_enum_lookup_by_name(struct config_enum * record, const char *value,
4488                                                    int *retval)
4489 {
4490         const struct config_enum_entry *entry;
4491
4492         for (entry = record->options; entry && entry->name; entry++)
4493         {
4494                 if (pg_strcasecmp(value, entry->name) == 0)
4495                 {
4496                         *retval = entry->val;
4497                         return TRUE;
4498                 }
4499         }
4500
4501         *retval = 0;
4502         return FALSE;
4503 }
4504
4505
4506 /*
4507  * Return a list of all available options for an enum, excluding
4508  * hidden ones, separated by the given separator.
4509  * If prefix is non-NULL, it is added before the first enum value.
4510  * If suffix is non-NULL, it is added to the end of the string.
4511  */
4512 static char *
4513 config_enum_get_options(struct config_enum * record, const char *prefix,
4514                                                 const char *suffix, const char *separator)
4515 {
4516         const struct config_enum_entry *entry;
4517         StringInfoData retstr;
4518         int                     seplen;
4519
4520         initStringInfo(&retstr);
4521         appendStringInfoString(&retstr, prefix);
4522
4523         seplen = strlen(separator);
4524         for (entry = record->options; entry && entry->name; entry++)
4525         {
4526                 if (!entry->hidden)
4527                 {
4528                         appendStringInfoString(&retstr, entry->name);
4529                         appendBinaryStringInfo(&retstr, separator, seplen);
4530                 }
4531         }
4532
4533         /*
4534          * All the entries may have been hidden, leaving the string empty if no
4535          * prefix was given. This indicates a broken GUC setup, since there is no
4536          * use for an enum without any values, so we just check to make sure we
4537          * don't write to invalid memory instead of actually trying to do
4538          * something smart with it.
4539          */
4540         if (retstr.len >= seplen)
4541         {
4542                 /* Replace final separator */
4543                 retstr.data[retstr.len - seplen] = '\0';
4544                 retstr.len -= seplen;
4545         }
4546
4547         appendStringInfoString(&retstr, suffix);
4548
4549         return retstr.data;
4550 }
4551
4552 /*
4553  * Call a GucStringAssignHook function, being careful to free the
4554  * "newval" string if the hook ereports.
4555  *
4556  * This is split out of set_config_option just to avoid the "volatile"
4557  * qualifiers that would otherwise have to be plastered all over.
4558  */
4559 static const char *
4560 call_string_assign_hook(GucStringAssignHook assign_hook,
4561                                                 char *newval, bool doit, GucSource source)
4562 {
4563         const char *result;
4564
4565         PG_TRY();
4566         {
4567                 result = (*assign_hook) (newval, doit, source);
4568         }
4569         PG_CATCH();
4570         {
4571                 free(newval);
4572                 PG_RE_THROW();
4573         }
4574         PG_END_TRY();
4575
4576         return result;
4577 }
4578
4579
4580 /*
4581  * Sets option `name' to given value. The value should be a string
4582  * which is going to be parsed and converted to the appropriate data
4583  * type.  The context and source parameters indicate in which context this
4584  * function is being called so it can apply the access restrictions
4585  * properly.
4586  *
4587  * If value is NULL, set the option to its default value (normally the
4588  * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
4589  *
4590  * action indicates whether to set the value globally in the session, locally
4591  * to the current top transaction, or just for the duration of a function call.
4592  *
4593  * If changeVal is false then don't really set the option but do all
4594  * the checks to see if it would work.
4595  *
4596  * If there is an error (non-existing option, invalid value) then an
4597  * ereport(ERROR) is thrown *unless* this is called in a context where we
4598  * don't want to ereport (currently, startup or SIGHUP config file reread).
4599  * In that case we write a suitable error message via ereport(LOG) and
4600  * return false. This is working around the deficiencies in the ereport
4601  * mechanism, so don't blame me.  In all other cases, the function
4602  * returns true, including cases where the input is valid but we chose
4603  * not to apply it because of context or source-priority considerations.
4604  *
4605  * See also SetConfigOption for an external interface.
4606  */
4607 bool
4608 set_config_option(const char *name, const char *value,
4609                                   GucContext context, GucSource source,
4610                                   GucAction action, bool changeVal)
4611 {
4612         struct config_generic *record;
4613         int                     elevel;
4614         bool            makeDefault;
4615
4616         if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
4617         {
4618                 /*
4619                  * To avoid cluttering the log, only the postmaster bleats loudly
4620                  * about problems with the config file.
4621                  */
4622                 elevel = IsUnderPostmaster ? DEBUG3 : LOG;
4623         }
4624         else if (source == PGC_S_DATABASE || source == PGC_S_USER ||
4625                          source == PGC_S_DATABASE_USER)
4626                 elevel = WARNING;
4627         else
4628                 elevel = ERROR;
4629
4630         record = find_option(name, true, elevel);
4631         if (record == NULL)
4632         {
4633                 ereport(elevel,
4634                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
4635                            errmsg("unrecognized configuration parameter \"%s\"", name)));
4636                 return false;
4637         }
4638
4639         /*
4640          * If source is postgresql.conf, mark the found record with
4641          * GUC_IS_IN_FILE. This is for the convenience of ProcessConfigFile.  Note
4642          * that we do it even if changeVal is false, since ProcessConfigFile wants
4643          * the marking to occur during its testing pass.
4644          */
4645         if (source == PGC_S_FILE)
4646                 record->status |= GUC_IS_IN_FILE;
4647
4648         /*
4649          * Check if the option can be set at this time. See guc.h for the precise
4650          * rules. Note that we don't want to throw errors if we're in the SIGHUP
4651          * context. In that case we just ignore the attempt and return true.
4652          */
4653         switch (record->context)
4654         {
4655                 case PGC_INTERNAL:
4656                         if (context == PGC_SIGHUP)
4657                                 return true;
4658                         if (context != PGC_INTERNAL)
4659                         {
4660                                 ereport(elevel,
4661                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4662                                                  errmsg("parameter \"%s\" cannot be changed",
4663                                                                 name)));
4664                                 return false;
4665                         }
4666                         break;
4667                 case PGC_POSTMASTER:
4668                         if (context == PGC_SIGHUP)
4669                         {
4670                                 /*
4671                                  * We are reading a PGC_POSTMASTER var from postgresql.conf.
4672                                  * We can't change the setting, so give a warning if the DBA
4673                                  * tries to change it.  (Throwing an error would be more
4674                                  * consistent, but seems overly rigid.)
4675                                  */
4676                                 if (changeVal && !is_newvalue_equal(record, value))
4677                                         ereport(elevel,
4678                                                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4679                                            errmsg("parameter \"%s\" cannot be changed without restarting the server",
4680                                                           name)));
4681                                 return true;
4682                         }
4683                         if (context != PGC_POSTMASTER)
4684                         {
4685                                 ereport(elevel,
4686                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4687                                            errmsg("parameter \"%s\" cannot be changed without restarting the server",
4688                                                           name)));
4689                                 return false;
4690                         }
4691                         break;
4692                 case PGC_SIGHUP:
4693                         if (context != PGC_SIGHUP && context != PGC_POSTMASTER)
4694                         {
4695                                 ereport(elevel,
4696                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4697                                                  errmsg("parameter \"%s\" cannot be changed now",
4698                                                                 name)));
4699                                 return false;
4700                         }
4701
4702                         /*
4703                          * Hmm, the idea of the SIGHUP context is "ought to be global, but
4704                          * can be changed after postmaster start". But there's nothing
4705                          * that prevents a crafty administrator from sending SIGHUP
4706                          * signals to individual backends only.
4707                          */
4708                         break;
4709                 case PGC_BACKEND:
4710                         if (context == PGC_SIGHUP)
4711                         {
4712                                 /*
4713                                  * If a PGC_BACKEND parameter is changed in the config file,
4714                                  * we want to accept the new value in the postmaster (whence
4715                                  * it will propagate to subsequently-started backends), but
4716                                  * ignore it in existing backends.      This is a tad klugy, but
4717                                  * necessary because we don't re-read the config file during
4718                                  * backend start.
4719                                  */
4720                                 if (IsUnderPostmaster)
4721                                         return true;
4722                         }
4723                         else if (context != PGC_POSTMASTER && context != PGC_BACKEND &&
4724                                          source != PGC_S_CLIENT)
4725                         {
4726                                 ereport(elevel,
4727                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4728                                                  errmsg("parameter \"%s\" cannot be set after connection start",
4729                                                                 name)));
4730                                 return false;
4731                         }
4732                         break;
4733                 case PGC_SUSET:
4734                         if (context == PGC_USERSET || context == PGC_BACKEND)
4735                         {
4736                                 ereport(elevel,
4737                                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4738                                                  errmsg("permission denied to set parameter \"%s\"",
4739                                                                 name)));
4740                                 return false;
4741                         }
4742                         break;
4743                 case PGC_USERSET:
4744                         /* always okay */
4745                         break;
4746         }
4747
4748         /*
4749          * Disallow changing GUC_NOT_WHILE_SEC_REST values if we are inside a
4750          * security restriction context.  We can reject this regardless of
4751          * the GUC context or source, mainly because sources that it might be
4752          * reasonable to override for won't be seen while inside a function.
4753          *
4754          * Note: variables marked GUC_NOT_WHILE_SEC_REST should usually be marked
4755          * GUC_NO_RESET_ALL as well, because ResetAllOptions() doesn't check this.
4756          * An exception might be made if the reset value is assumed to be "safe".
4757          *
4758          * Note: this flag is currently used for "session_authorization" and
4759          * "role".  We need to prohibit changing these inside a local userid
4760          * context because when we exit it, GUC won't be notified, leaving things
4761          * out of sync.  (This could be fixed by forcing a new GUC nesting level,
4762          * but that would change behavior in possibly-undesirable ways.)  Also,
4763          * we prohibit changing these in a security-restricted operation because
4764          * otherwise RESET could be used to regain the session user's privileges.
4765          */
4766         if (record->flags & GUC_NOT_WHILE_SEC_REST)
4767         {
4768                 if (InLocalUserIdChange())
4769                 {
4770                         /*
4771                          * Phrasing of this error message is historical, but it's the
4772                          * most common case.
4773                          */
4774                         ereport(elevel,
4775                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4776                                          errmsg("cannot set parameter \"%s\" within security-definer function",
4777                                                         name)));
4778                         return false;
4779                 }
4780                 if (InSecurityRestrictedOperation())
4781                 {
4782                         ereport(elevel,
4783                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4784                                          errmsg("cannot set parameter \"%s\" within security-restricted operation",
4785                                                         name)));
4786                         return false;
4787                 }
4788         }
4789
4790         /*
4791          * Should we set reset/stacked values?  (If so, the behavior is not
4792          * transactional.)      This is done either when we get a default value from
4793          * the database's/user's/client's default settings or when we reset a
4794          * value to its default.
4795          */
4796         makeDefault = changeVal && (source <= PGC_S_OVERRIDE) &&
4797                 ((value != NULL) || source == PGC_S_DEFAULT);
4798
4799         /*
4800          * Ignore attempted set if overridden by previously processed setting.
4801          * However, if changeVal is false then plow ahead anyway since we are
4802          * trying to find out if the value is potentially good, not actually use
4803          * it. Also keep going if makeDefault is true, since we may want to set
4804          * the reset/stacked values even if we can't set the variable itself.
4805          */
4806         if (record->source > source)
4807         {
4808                 if (changeVal && !makeDefault)
4809                 {
4810                         elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
4811                                  name);
4812                         return true;
4813                 }
4814                 changeVal = false;
4815         }
4816
4817         /*
4818          * Evaluate value and set variable.
4819          */
4820         switch (record->vartype)
4821         {
4822                 case PGC_BOOL:
4823                         {
4824                                 struct config_bool *conf = (struct config_bool *) record;
4825                                 bool            newval;
4826
4827                                 if (value)
4828                                 {
4829                                         if (!parse_bool(value, &newval))
4830                                         {
4831                                                 ereport(elevel,
4832                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4833                                                   errmsg("parameter \"%s\" requires a Boolean value",
4834                                                                  name)));
4835                                                 return false;
4836                                         }
4837                                 }
4838                                 else if (source == PGC_S_DEFAULT)
4839                                         newval = conf->boot_val;
4840                                 else
4841                                 {
4842                                         newval = conf->reset_val;
4843                                         source = conf->gen.reset_source;
4844                                 }
4845
4846                                 /* Save old value to support transaction abort */
4847                                 if (changeVal && !makeDefault)
4848                                         push_old_value(&conf->gen, action);
4849
4850                                 if (conf->assign_hook)
4851                                         if (!(*conf->assign_hook) (newval, changeVal, source))
4852                                         {
4853                                                 ereport(elevel,
4854                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4855                                                          errmsg("invalid value for parameter \"%s\": %d",
4856                                                                         name, (int) newval)));
4857                                                 return false;
4858                                         }
4859
4860                                 if (changeVal)
4861                                 {
4862                                         *conf->variable = newval;
4863                                         conf->gen.source = source;
4864                                 }
4865                                 if (makeDefault)
4866                                 {
4867                                         GucStack   *stack;
4868
4869                                         if (conf->gen.reset_source <= source)
4870                                         {
4871                                                 conf->reset_val = newval;
4872                                                 conf->gen.reset_source = source;
4873                                         }
4874                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
4875                                         {
4876                                                 if (stack->source <= source)
4877                                                 {
4878                                                         stack->prior.boolval = newval;
4879                                                         stack->source = source;
4880                                                 }
4881                                         }
4882                                 }
4883                                 break;
4884                         }
4885
4886                 case PGC_INT:
4887                         {
4888                                 struct config_int *conf = (struct config_int *) record;
4889                                 int                     newval;
4890
4891                                 if (value)
4892                                 {
4893                                         const char *hintmsg;
4894
4895                                         if (!parse_int(value, &newval, conf->gen.flags, &hintmsg))
4896                                         {
4897                                                 ereport(elevel,
4898                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4899                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
4900                                                                 name, value),
4901                                                                  hintmsg ? errhint("%s", _(hintmsg)) : 0));
4902                                                 return false;
4903                                         }
4904                                         if (newval < conf->min || newval > conf->max)
4905                                         {
4906                                                 ereport(elevel,
4907                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4908                                                                  errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
4909                                                                                 newval, name, conf->min, conf->max)));
4910                                                 return false;
4911                                         }
4912                                 }
4913                                 else if (source == PGC_S_DEFAULT)
4914                                         newval = conf->boot_val;
4915                                 else
4916                                 {
4917                                         newval = conf->reset_val;
4918                                         source = conf->gen.reset_source;
4919                                 }
4920
4921                                 /* Save old value to support transaction abort */
4922                                 if (changeVal && !makeDefault)
4923                                         push_old_value(&conf->gen, action);
4924
4925                                 if (conf->assign_hook)
4926                                         if (!(*conf->assign_hook) (newval, changeVal, source))
4927                                         {
4928                                                 ereport(elevel,
4929                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4930                                                          errmsg("invalid value for parameter \"%s\": %d",
4931                                                                         name, newval)));
4932                                                 return false;
4933                                         }
4934
4935                                 if (changeVal)
4936                                 {
4937                                         *conf->variable = newval;
4938                                         conf->gen.source = source;
4939                                 }
4940                                 if (makeDefault)
4941                                 {
4942                                         GucStack   *stack;
4943
4944                                         if (conf->gen.reset_source <= source)
4945                                         {
4946                                                 conf->reset_val = newval;
4947                                                 conf->gen.reset_source = source;
4948                                         }
4949                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
4950                                         {
4951                                                 if (stack->source <= source)
4952                                                 {
4953                                                         stack->prior.intval = newval;
4954                                                         stack->source = source;
4955                                                 }
4956                                         }
4957                                 }
4958                                 break;
4959                         }
4960
4961                 case PGC_REAL:
4962                         {
4963                                 struct config_real *conf = (struct config_real *) record;
4964                                 double          newval;
4965
4966                                 if (value)
4967                                 {
4968                                         if (!parse_real(value, &newval))
4969                                         {
4970                                                 ereport(elevel,
4971                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4972                                                   errmsg("parameter \"%s\" requires a numeric value",
4973                                                                  name)));
4974                                                 return false;
4975                                         }
4976                                         if (newval < conf->min || newval > conf->max)
4977                                         {
4978                                                 ereport(elevel,
4979                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4980                                                                  errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
4981                                                                                 newval, name, conf->min, conf->max)));
4982                                                 return false;
4983                                         }
4984                                 }
4985                                 else if (source == PGC_S_DEFAULT)
4986                                         newval = conf->boot_val;
4987                                 else
4988                                 {
4989                                         newval = conf->reset_val;
4990                                         source = conf->gen.reset_source;
4991                                 }
4992
4993                                 /* Save old value to support transaction abort */
4994                                 if (changeVal && !makeDefault)
4995                                         push_old_value(&conf->gen, action);
4996
4997                                 if (conf->assign_hook)
4998                                         if (!(*conf->assign_hook) (newval, changeVal, source))
4999                                         {
5000                                                 ereport(elevel,
5001                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5002                                                          errmsg("invalid value for parameter \"%s\": %g",
5003                                                                         name, newval)));
5004                                                 return false;
5005                                         }
5006
5007                                 if (changeVal)
5008                                 {
5009                                         *conf->variable = newval;
5010                                         conf->gen.source = source;
5011                                 }
5012                                 if (makeDefault)
5013                                 {
5014                                         GucStack   *stack;
5015
5016                                         if (conf->gen.reset_source <= source)
5017                                         {
5018                                                 conf->reset_val = newval;
5019                                                 conf->gen.reset_source = source;
5020                                         }
5021                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
5022                                         {
5023                                                 if (stack->source <= source)
5024                                                 {
5025                                                         stack->prior.realval = newval;
5026                                                         stack->source = source;
5027                                                 }
5028                                         }
5029                                 }
5030                                 break;
5031                         }
5032
5033                 case PGC_STRING:
5034                         {
5035                                 struct config_string *conf = (struct config_string *) record;
5036                                 char       *newval;
5037
5038                                 if (value)
5039                                 {
5040                                         newval = guc_strdup(elevel, value);
5041                                         if (newval == NULL)
5042                                                 return false;
5043
5044                                         /*
5045                                          * The only sort of "parsing" check we need to do is apply
5046                                          * truncation if GUC_IS_NAME.
5047                                          */
5048                                         if (conf->gen.flags & GUC_IS_NAME)
5049                                                 truncate_identifier(newval, strlen(newval), true);
5050                                 }
5051                                 else if (source == PGC_S_DEFAULT)
5052                                 {
5053                                         if (conf->boot_val == NULL)
5054                                                 newval = NULL;
5055                                         else
5056                                         {
5057                                                 newval = guc_strdup(elevel, conf->boot_val);
5058                                                 if (newval == NULL)
5059                                                         return false;
5060                                         }
5061                                 }
5062                                 else
5063                                 {
5064                                         /*
5065                                          * We could possibly avoid strdup here, but easier to make
5066                                          * this case work the same as the normal assignment case;
5067                                          * note the possible free of newval below.
5068                                          */
5069                                         if (conf->reset_val == NULL)
5070                                                 newval = NULL;
5071                                         else
5072                                         {
5073                                                 newval = guc_strdup(elevel, conf->reset_val);
5074                                                 if (newval == NULL)
5075                                                         return false;
5076                                         }
5077                                         source = conf->gen.reset_source;
5078                                 }
5079
5080                                 /* Save old value to support transaction abort */
5081                                 if (changeVal && !makeDefault)
5082                                         push_old_value(&conf->gen, action);
5083
5084                                 if (conf->assign_hook && newval)
5085                                 {
5086                                         const char *hookresult;
5087
5088                                         /*
5089                                          * If the hook ereports, we have to make sure we free
5090                                          * newval, else it will be a permanent memory leak.
5091                                          */
5092                                         hookresult = call_string_assign_hook(conf->assign_hook,
5093                                                                                                                  newval,
5094                                                                                                                  changeVal,
5095                                                                                                                  source);
5096                                         if (hookresult == NULL)
5097                                         {
5098                                                 free(newval);
5099                                                 ereport(elevel,
5100                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5101                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
5102                                                                 name, value ? value : "")));
5103                                                 return false;
5104                                         }
5105                                         else if (hookresult != newval)
5106                                         {
5107                                                 free(newval);
5108
5109                                                 /*
5110                                                  * Having to cast away const here is annoying, but the
5111                                                  * alternative is to declare assign_hooks as returning
5112                                                  * char*, which would mean they'd have to cast away
5113                                                  * const, or as both taking and returning char*, which
5114                                                  * doesn't seem attractive either --- we don't want
5115                                                  * them to scribble on the passed str.
5116                                                  */
5117                                                 newval = (char *) hookresult;
5118                                         }
5119                                 }
5120
5121                                 if (changeVal)
5122                                 {
5123                                         set_string_field(conf, conf->variable, newval);
5124                                         conf->gen.source = source;
5125                                 }
5126                                 if (makeDefault)
5127                                 {
5128                                         GucStack   *stack;
5129
5130                                         if (conf->gen.reset_source <= source)
5131                                         {
5132                                                 set_string_field(conf, &conf->reset_val, newval);
5133                                                 conf->gen.reset_source = source;
5134                                         }
5135                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
5136                                         {
5137                                                 if (stack->source <= source)
5138                                                 {
5139                                                         set_string_field(conf, &stack->prior.stringval,
5140                                                                                          newval);
5141                                                         stack->source = source;
5142                                                 }
5143                                         }
5144                                 }
5145                                 /* Perhaps we didn't install newval anywhere */
5146                                 if (newval && !string_field_used(conf, newval))
5147                                         free(newval);
5148                                 break;
5149                         }
5150                 case PGC_ENUM:
5151                         {
5152                                 struct config_enum *conf = (struct config_enum *) record;
5153                                 int                     newval;
5154
5155                                 if (value)
5156                                 {
5157                                         if (!config_enum_lookup_by_name(conf, value, &newval))
5158                                         {
5159                                                 char       *hintmsg;
5160
5161                                                 hintmsg = config_enum_get_options(conf,
5162                                                                                                                 "Available values: ",
5163                                                                                                                   ".", ", ");
5164
5165                                                 ereport(elevel,
5166                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5167                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
5168                                                                 name, value),
5169                                                                  hintmsg ? errhint("%s", _(hintmsg)) : 0));
5170
5171                                                 if (hintmsg)
5172                                                         pfree(hintmsg);
5173                                                 return false;
5174                                         }
5175                                 }
5176                                 else if (source == PGC_S_DEFAULT)
5177                                         newval = conf->boot_val;
5178                                 else
5179                                 {
5180                                         newval = conf->reset_val;
5181                                         source = conf->gen.reset_source;
5182                                 }
5183
5184                                 /* Save old value to support transaction abort */
5185                                 if (changeVal && !makeDefault)
5186                                         push_old_value(&conf->gen, action);
5187
5188                                 if (conf->assign_hook)
5189                                         if (!(*conf->assign_hook) (newval, changeVal, source))
5190                                         {
5191                                                 ereport(elevel,
5192                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5193                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
5194                                                                 name,
5195                                                                 config_enum_lookup_by_value(conf, newval))));
5196                                                 return false;
5197                                         }
5198
5199                                 if (changeVal)
5200                                 {
5201                                         *conf->variable = newval;
5202                                         conf->gen.source = source;
5203                                 }
5204                                 if (makeDefault)
5205                                 {
5206                                         GucStack   *stack;
5207
5208                                         if (conf->gen.reset_source <= source)
5209                                         {
5210                                                 conf->reset_val = newval;
5211                                                 conf->gen.reset_source = source;
5212                                         }
5213                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
5214                                         {
5215                                                 if (stack->source <= source)
5216                                                 {
5217                                                         stack->prior.enumval = newval;
5218                                                         stack->source = source;
5219                                                 }
5220                                         }
5221                                 }
5222                                 break;
5223                         }
5224         }
5225
5226         if (changeVal && (record->flags & GUC_REPORT))
5227                 ReportGUCOption(record);
5228
5229         return true;
5230 }
5231
5232
5233 /*
5234  * Set the fields for source file and line number the setting came from.
5235  */
5236 static void
5237 set_config_sourcefile(const char *name, char *sourcefile, int sourceline)
5238 {
5239         struct config_generic *record;
5240         int                     elevel;
5241
5242         /*
5243          * To avoid cluttering the log, only the postmaster bleats loudly about
5244          * problems with the config file.
5245          */
5246         elevel = IsUnderPostmaster ? DEBUG3 : LOG;
5247
5248         record = find_option(name, true, elevel);
5249         /* should not happen */
5250         if (record == NULL)
5251                 elog(ERROR, "unrecognized configuration parameter \"%s\"", name);
5252
5253         sourcefile = guc_strdup(elevel, sourcefile);
5254         if (record->sourcefile)
5255                 free(record->sourcefile);
5256         record->sourcefile = sourcefile;
5257         record->sourceline = sourceline;
5258 }
5259
5260 /*
5261  * Set a config option to the given value. See also set_config_option,
5262  * this is just the wrapper to be called from outside GUC.      NB: this
5263  * is used only for non-transactional operations.
5264  *
5265  * Note: there is no support here for setting source file/line, as it
5266  * is currently not needed.
5267  */
5268 void
5269 SetConfigOption(const char *name, const char *value,
5270                                 GucContext context, GucSource source)
5271 {
5272         (void) set_config_option(name, value, context, source,
5273                                                          GUC_ACTION_SET, true);
5274 }
5275
5276
5277
5278 /*
5279  * Fetch the current value of the option `name'. If the option doesn't exist,
5280  * throw an ereport and don't return.
5281  *
5282  * If restrict_superuser is true, we also enforce that only superusers can
5283  * see GUC_SUPERUSER_ONLY variables.  This should only be passed as true
5284  * in user-driven calls.
5285  *
5286  * The string is *not* allocated for modification and is really only
5287  * valid until the next call to configuration related functions.
5288  */
5289 const char *
5290 GetConfigOption(const char *name, bool restrict_superuser)
5291 {
5292         struct config_generic *record;
5293         static char buffer[256];
5294
5295         record = find_option(name, false, ERROR);
5296         if (record == NULL)
5297                 ereport(ERROR,
5298                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
5299                            errmsg("unrecognized configuration parameter \"%s\"", name)));
5300         if (restrict_superuser &&
5301                 (record->flags & GUC_SUPERUSER_ONLY) &&
5302                 !superuser())
5303                 ereport(ERROR,
5304                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5305                                  errmsg("must be superuser to examine \"%s\"", name)));
5306
5307         switch (record->vartype)
5308         {
5309                 case PGC_BOOL:
5310                         return *((struct config_bool *) record)->variable ? "on" : "off";
5311
5312                 case PGC_INT:
5313                         snprintf(buffer, sizeof(buffer), "%d",
5314                                          *((struct config_int *) record)->variable);
5315                         return buffer;
5316
5317                 case PGC_REAL:
5318                         snprintf(buffer, sizeof(buffer), "%g",
5319                                          *((struct config_real *) record)->variable);
5320                         return buffer;
5321
5322                 case PGC_STRING:
5323                         return *((struct config_string *) record)->variable;
5324
5325                 case PGC_ENUM:
5326                         return config_enum_lookup_by_value((struct config_enum *) record,
5327                                                                  *((struct config_enum *) record)->variable);
5328         }
5329         return NULL;
5330 }
5331
5332 /*
5333  * Get the RESET value associated with the given option.
5334  *
5335  * Note: this is not re-entrant, due to use of static result buffer;
5336  * not to mention that a string variable could have its reset_val changed.
5337  * Beware of assuming the result value is good for very long.
5338  */
5339 const char *
5340 GetConfigOptionResetString(const char *name)
5341 {
5342         struct config_generic *record;
5343         static char buffer[256];
5344
5345         record = find_option(name, false, ERROR);
5346         if (record == NULL)
5347                 ereport(ERROR,
5348                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
5349                            errmsg("unrecognized configuration parameter \"%s\"", name)));
5350         if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
5351                 ereport(ERROR,
5352                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5353                                  errmsg("must be superuser to examine \"%s\"", name)));
5354
5355         switch (record->vartype)
5356         {
5357                 case PGC_BOOL:
5358                         return ((struct config_bool *) record)->reset_val ? "on" : "off";
5359
5360                 case PGC_INT:
5361                         snprintf(buffer, sizeof(buffer), "%d",
5362                                          ((struct config_int *) record)->reset_val);
5363                         return buffer;
5364
5365                 case PGC_REAL:
5366                         snprintf(buffer, sizeof(buffer), "%g",
5367                                          ((struct config_real *) record)->reset_val);
5368                         return buffer;
5369
5370                 case PGC_STRING:
5371                         return ((struct config_string *) record)->reset_val;
5372
5373                 case PGC_ENUM:
5374                         return config_enum_lookup_by_value((struct config_enum *) record,
5375                                                                  ((struct config_enum *) record)->reset_val);
5376         }
5377         return NULL;
5378 }
5379
5380
5381 /*
5382  * GUC_complaint_elevel
5383  *              Get the ereport error level to use in an assign_hook's error report.
5384  *
5385  * This should be used by assign hooks that want to emit a custom error
5386  * report (in addition to the generic "invalid value for option FOO" that
5387  * guc.c will provide).  Note that the result might be ERROR or a lower
5388  * level, so the caller must be prepared for control to return from ereport,
5389  * or not.      If control does return, return false/NULL from the hook function.
5390  *
5391  * At some point it'd be nice to replace this with a mechanism that allows
5392  * the custom message to become the DETAIL line of guc.c's generic message.
5393  */
5394 int
5395 GUC_complaint_elevel(GucSource source)
5396 {
5397         int                     elevel;
5398
5399         if (source == PGC_S_FILE)
5400         {
5401                 /*
5402                  * To avoid cluttering the log, only the postmaster bleats loudly
5403                  * about problems with the config file.
5404                  */
5405                 elevel = IsUnderPostmaster ? DEBUG3 : LOG;
5406         }
5407         else if (source == PGC_S_OVERRIDE)
5408         {
5409                 /*
5410                  * If we're a postmaster child, this is probably "undo" during
5411                  * transaction abort, so we don't want to clutter the log.  There's a
5412                  * small chance of a real problem with an OVERRIDE setting, though, so
5413                  * suppressing the message entirely wouldn't be desirable.
5414                  */
5415                 elevel = IsUnderPostmaster ? DEBUG5 : LOG;
5416         }
5417         else if (source < PGC_S_INTERACTIVE)
5418                 elevel = LOG;
5419         else
5420                 elevel = ERROR;
5421
5422         return elevel;
5423 }
5424
5425
5426 /*
5427  * flatten_set_variable_args
5428  *              Given a parsenode List as emitted by the grammar for SET,
5429  *              convert to the flat string representation used by GUC.
5430  *
5431  * We need to be told the name of the variable the args are for, because
5432  * the flattening rules vary (ugh).
5433  *
5434  * The result is NULL if args is NIL (ie, SET ... TO DEFAULT), otherwise
5435  * a palloc'd string.
5436  */
5437 static char *
5438 flatten_set_variable_args(const char *name, List *args)
5439 {
5440         struct config_generic *record;
5441         int                     flags;
5442         StringInfoData buf;
5443         ListCell   *l;
5444
5445         /* Fast path if just DEFAULT */
5446         if (args == NIL)
5447                 return NULL;
5448
5449         /* Else get flags for the variable */
5450         record = find_option(name, true, ERROR);
5451         if (record == NULL)
5452                 ereport(ERROR,
5453                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
5454                            errmsg("unrecognized configuration parameter \"%s\"", name)));
5455
5456         flags = record->flags;
5457
5458         /* Complain if list input and non-list variable */
5459         if ((flags & GUC_LIST_INPUT) == 0 &&
5460                 list_length(args) != 1)
5461                 ereport(ERROR,
5462                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5463                                  errmsg("SET %s takes only one argument", name)));
5464
5465         initStringInfo(&buf);
5466
5467         /*
5468          * Each list member may be a plain A_Const node, or an A_Const within a
5469          * TypeCast; the latter case is supported only for ConstInterval arguments
5470          * (for SET TIME ZONE).
5471          */
5472         foreach(l, args)
5473         {
5474                 Node       *arg = (Node *) lfirst(l);
5475                 char       *val;
5476                 TypeName   *typeName = NULL;
5477                 A_Const    *con;
5478
5479                 if (l != list_head(args))
5480                         appendStringInfo(&buf, ", ");
5481
5482                 if (IsA(arg, TypeCast))
5483                 {
5484                         TypeCast   *tc = (TypeCast *) arg;
5485
5486                         arg = tc->arg;
5487                         typeName = tc->typeName;
5488                 }
5489
5490                 if (!IsA(arg, A_Const))
5491                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
5492                 con = (A_Const *) arg;
5493
5494                 switch (nodeTag(&con->val))
5495                 {
5496                         case T_Integer:
5497                                 appendStringInfo(&buf, "%ld", intVal(&con->val));
5498                                 break;
5499                         case T_Float:
5500                                 /* represented as a string, so just copy it */
5501                                 appendStringInfoString(&buf, strVal(&con->val));
5502                                 break;
5503                         case T_String:
5504                                 val = strVal(&con->val);
5505                                 if (typeName != NULL)
5506                                 {
5507                                         /*
5508                                          * Must be a ConstInterval argument for TIME ZONE. Coerce
5509                                          * to interval and back to normalize the value and account
5510                                          * for any typmod.
5511                                          */
5512                                         Oid                     typoid;
5513                                         int32           typmod;
5514                                         Datum           interval;
5515                                         char       *intervalout;
5516
5517                                         typoid = typenameTypeId(NULL, typeName, &typmod);
5518                                         Assert(typoid == INTERVALOID);
5519
5520                                         interval =
5521                                                 DirectFunctionCall3(interval_in,
5522                                                                                         CStringGetDatum(val),
5523                                                                                         ObjectIdGetDatum(InvalidOid),
5524                                                                                         Int32GetDatum(typmod));
5525
5526                                         intervalout =
5527                                                 DatumGetCString(DirectFunctionCall1(interval_out,
5528                                                                                                                         interval));
5529                                         appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
5530                                 }
5531                                 else
5532                                 {
5533                                         /*
5534                                          * Plain string literal or identifier.  For quote mode,
5535                                          * quote it if it's not a vanilla identifier.
5536                                          */
5537                                         if (flags & GUC_LIST_QUOTE)
5538                                                 appendStringInfoString(&buf, quote_identifier(val));
5539                                         else
5540                                                 appendStringInfoString(&buf, val);
5541                                 }
5542                                 break;
5543                         default:
5544                                 elog(ERROR, "unrecognized node type: %d",
5545                                          (int) nodeTag(&con->val));
5546                                 break;
5547                 }
5548         }
5549
5550         return buf.data;
5551 }
5552
5553
5554 /*
5555  * SET command
5556  */
5557 void
5558 ExecSetVariableStmt(VariableSetStmt *stmt)
5559 {
5560         GucAction       action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
5561
5562         switch (stmt->kind)
5563         {
5564                 case VAR_SET_VALUE:
5565                 case VAR_SET_CURRENT:
5566                         set_config_option(stmt->name,
5567                                                           ExtractSetVariableArgs(stmt),
5568                                                           (superuser() ? PGC_SUSET : PGC_USERSET),
5569                                                           PGC_S_SESSION,
5570                                                           action,
5571                                                           true);
5572                         break;
5573                 case VAR_SET_MULTI:
5574
5575                         /*
5576                          * Special case for special SQL syntax that effectively sets more
5577                          * than one variable per statement.
5578                          */
5579                         if (strcmp(stmt->name, "TRANSACTION") == 0)
5580                         {
5581                                 ListCell   *head;
5582
5583                                 foreach(head, stmt->args)
5584                                 {
5585                                         DefElem    *item = (DefElem *) lfirst(head);
5586
5587                                         if (strcmp(item->defname, "transaction_isolation") == 0)
5588                                                 SetPGVariable("transaction_isolation",
5589                                                                           list_make1(item->arg), stmt->is_local);
5590                                         else if (strcmp(item->defname, "transaction_read_only") == 0)
5591                                                 SetPGVariable("transaction_read_only",
5592                                                                           list_make1(item->arg), stmt->is_local);
5593                                         else
5594                                                 elog(ERROR, "unexpected SET TRANSACTION element: %s",
5595                                                          item->defname);
5596                                 }
5597                         }
5598                         else if (strcmp(stmt->name, "SESSION CHARACTERISTICS") == 0)
5599                         {
5600                                 ListCell   *head;
5601
5602                                 foreach(head, stmt->args)
5603                                 {
5604                                         DefElem    *item = (DefElem *) lfirst(head);
5605
5606                                         if (strcmp(item->defname, "transaction_isolation") == 0)
5607                                                 SetPGVariable("default_transaction_isolation",
5608                                                                           list_make1(item->arg), stmt->is_local);
5609                                         else if (strcmp(item->defname, "transaction_read_only") == 0)
5610                                                 SetPGVariable("default_transaction_read_only",
5611                                                                           list_make1(item->arg), stmt->is_local);
5612                                         else
5613                                                 elog(ERROR, "unexpected SET SESSION element: %s",
5614                                                          item->defname);
5615                                 }
5616                         }
5617                         else
5618                                 elog(ERROR, "unexpected SET MULTI element: %s",
5619                                          stmt->name);
5620                         break;
5621                 case VAR_SET_DEFAULT:
5622                 case VAR_RESET:
5623                         set_config_option(stmt->name,
5624                                                           NULL,
5625                                                           (superuser() ? PGC_SUSET : PGC_USERSET),
5626                                                           PGC_S_SESSION,
5627                                                           action,
5628                                                           true);
5629                         break;
5630                 case VAR_RESET_ALL:
5631                         ResetAllOptions();
5632                         break;
5633         }
5634 }
5635
5636 /*
5637  * Get the value to assign for a VariableSetStmt, or NULL if it's RESET.
5638  * The result is palloc'd.
5639  *
5640  * This is exported for use by actions such as ALTER ROLE SET.
5641  */
5642 char *
5643 ExtractSetVariableArgs(VariableSetStmt *stmt)
5644 {
5645         switch (stmt->kind)
5646         {
5647                 case VAR_SET_VALUE:
5648                         return flatten_set_variable_args(stmt->name, stmt->args);
5649                 case VAR_SET_CURRENT:
5650                         return GetConfigOptionByName(stmt->name, NULL);
5651                 default:
5652                         return NULL;
5653         }
5654 }
5655
5656 /*
5657  * SetPGVariable - SET command exported as an easily-C-callable function.
5658  *
5659  * This provides access to SET TO value, as well as SET TO DEFAULT (expressed
5660  * by passing args == NIL), but not SET FROM CURRENT functionality.
5661  */
5662 void
5663 SetPGVariable(const char *name, List *args, bool is_local)
5664 {
5665         char       *argstring = flatten_set_variable_args(name, args);
5666
5667         /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
5668         set_config_option(name,
5669                                           argstring,
5670                                           (superuser() ? PGC_SUSET : PGC_USERSET),
5671                                           PGC_S_SESSION,
5672                                           is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
5673                                           true);
5674 }
5675
5676 /*
5677  * SET command wrapped as a SQL callable function.
5678  */
5679 Datum
5680 set_config_by_name(PG_FUNCTION_ARGS)
5681 {
5682         char       *name;
5683         char       *value;
5684         char       *new_value;
5685         bool            is_local;
5686
5687         if (PG_ARGISNULL(0))
5688                 ereport(ERROR,
5689                                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5690                                  errmsg("SET requires parameter name")));
5691
5692         /* Get the GUC variable name */
5693         name = TextDatumGetCString(PG_GETARG_DATUM(0));
5694
5695         /* Get the desired value or set to NULL for a reset request */
5696         if (PG_ARGISNULL(1))
5697                 value = NULL;
5698         else
5699                 value = TextDatumGetCString(PG_GETARG_DATUM(1));
5700
5701         /*
5702          * Get the desired state of is_local. Default to false if provided value
5703          * is NULL
5704          */
5705         if (PG_ARGISNULL(2))
5706                 is_local = false;
5707         else
5708                 is_local = PG_GETARG_BOOL(2);
5709
5710         /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
5711         set_config_option(name,
5712                                           value,
5713                                           (superuser() ? PGC_SUSET : PGC_USERSET),
5714                                           PGC_S_SESSION,
5715                                           is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
5716                                           true);
5717
5718         /* get the new current value */
5719         new_value = GetConfigOptionByName(name, NULL);
5720
5721         /* Convert return string to text */
5722         PG_RETURN_TEXT_P(cstring_to_text(new_value));
5723 }
5724
5725
5726 /*
5727  * Common code for DefineCustomXXXVariable subroutines: allocate the
5728  * new variable's config struct and fill in generic fields.
5729  */
5730 static struct config_generic *
5731 init_custom_variable(const char *name,
5732                                          const char *short_desc,
5733                                          const char *long_desc,
5734                                          GucContext context,
5735                                          int flags,
5736                                          enum config_type type,
5737                                          size_t sz)
5738 {
5739         struct config_generic *gen;
5740
5741         /*
5742          * Only allow custom PGC_POSTMASTER variables to be created during shared
5743          * library preload; any later than that, we can't ensure that the value
5744          * doesn't change after startup.  This is a fatal elog if it happens; just
5745          * erroring out isn't safe because we don't know what the calling loadable
5746          * module might already have hooked into.
5747          */
5748         if (context == PGC_POSTMASTER &&
5749                 !process_shared_preload_libraries_in_progress)
5750                 elog(FATAL, "cannot create PGC_POSTMASTER variables after startup");
5751
5752         gen = (struct config_generic *) guc_malloc(ERROR, sz);
5753         memset(gen, 0, sz);
5754
5755         gen->name = guc_strdup(ERROR, name);
5756         gen->context = context;
5757         gen->group = CUSTOM_OPTIONS;
5758         gen->short_desc = short_desc;
5759         gen->long_desc = long_desc;
5760         gen->flags = flags;
5761         gen->vartype = type;
5762
5763         return gen;
5764 }
5765
5766 /*
5767  * Common code for DefineCustomXXXVariable subroutines: insert the new
5768  * variable into the GUC variable array, replacing any placeholder.
5769  */
5770 static void
5771 define_custom_variable(struct config_generic * variable)
5772 {
5773         const char *name = variable->name;
5774         const char **nameAddr = &name;
5775         const char *value;
5776         struct config_string *pHolder;
5777         GucContext      phcontext;
5778         struct config_generic **res;
5779
5780         /*
5781          * See if there's a placeholder by the same name.
5782          */
5783         res = (struct config_generic **) bsearch((void *) &nameAddr,
5784                                                                                          (void *) guc_variables,
5785                                                                                          num_guc_variables,
5786                                                                                          sizeof(struct config_generic *),
5787                                                                                          guc_var_compare);
5788         if (res == NULL)
5789         {
5790                 /*
5791                  * No placeholder to replace, so we can just add it ... but first,
5792                  * make sure it's initialized to its default value.
5793                  */
5794                 InitializeOneGUCOption(variable);
5795                 add_guc_variable(variable, ERROR);
5796                 return;
5797         }
5798
5799         /*
5800          * This better be a placeholder
5801          */
5802         if (((*res)->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
5803                 ereport(ERROR,
5804                                 (errcode(ERRCODE_INTERNAL_ERROR),
5805                                  errmsg("attempt to redefine parameter \"%s\"", name)));
5806
5807         Assert((*res)->vartype == PGC_STRING);
5808         pHolder = (struct config_string *) (*res);
5809
5810         /*
5811          * First, set the variable to its default value.  We must do this even
5812          * though we intend to immediately apply a new value, since it's possible
5813          * that the new value is invalid.
5814          */
5815         InitializeOneGUCOption(variable);
5816
5817         /*
5818          * Replace the placeholder. We aren't changing the name, so no re-sorting
5819          * is necessary
5820          */
5821         *res = variable;
5822
5823         /*
5824          * Infer context for assignment based on source of existing value. We
5825          * can't tell this with exact accuracy, but we can at least do something
5826          * reasonable in typical cases.
5827          */
5828         switch (pHolder->gen.source)
5829         {
5830                 case PGC_S_DEFAULT:
5831                 case PGC_S_ENV_VAR:
5832                 case PGC_S_FILE:
5833                 case PGC_S_ARGV:
5834
5835                         /*
5836                          * If we got past the check in init_custom_variable, we can safely
5837                          * assume that any existing value for a PGC_POSTMASTER variable
5838                          * was set in postmaster context.
5839                          */
5840                         if (variable->context == PGC_POSTMASTER)
5841                                 phcontext = PGC_POSTMASTER;
5842                         else
5843                                 phcontext = PGC_SIGHUP;
5844                         break;
5845                 case PGC_S_DATABASE:
5846                 case PGC_S_USER:
5847                 case PGC_S_DATABASE_USER:
5848                 case PGC_S_CLIENT:
5849                 case PGC_S_SESSION:
5850                 default:
5851                         phcontext = PGC_USERSET;
5852                         break;
5853         }
5854
5855         /*
5856          * Assign the string value stored in the placeholder to the real variable.
5857          *
5858          * XXX this is not really good enough --- it should be a nontransactional
5859          * assignment, since we don't want it to roll back if the current xact
5860          * fails later.  (Or do we?)
5861          */
5862         value = *pHolder->variable;
5863
5864         if (value)
5865         {
5866                 if (set_config_option(name, value,
5867                                                           phcontext, pHolder->gen.source,
5868                                                           GUC_ACTION_SET, true))
5869                 {
5870                         /* Also copy over any saved source-location information */
5871                         if (pHolder->gen.sourcefile)
5872                                 set_config_sourcefile(name, pHolder->gen.sourcefile,
5873                                                                           pHolder->gen.sourceline);
5874                 }
5875         }
5876
5877         /*
5878          * Free up as much as we conveniently can of the placeholder structure
5879          * (this neglects any stack items...)
5880          */
5881         set_string_field(pHolder, pHolder->variable, NULL);
5882         set_string_field(pHolder, &pHolder->reset_val, NULL);
5883
5884         free(pHolder);
5885 }
5886
5887 void
5888 DefineCustomBoolVariable(const char *name,
5889                                                  const char *short_desc,
5890                                                  const char *long_desc,
5891                                                  bool *valueAddr,
5892                                                  bool bootValue,
5893                                                  GucContext context,
5894                                                  int flags,
5895                                                  GucBoolAssignHook assign_hook,
5896                                                  GucShowHook show_hook)
5897 {
5898         struct config_bool *var;
5899
5900         var = (struct config_bool *)
5901                 init_custom_variable(name, short_desc, long_desc, context, flags,
5902                                                          PGC_BOOL, sizeof(struct config_bool));
5903         var->variable = valueAddr;
5904         var->boot_val = bootValue;
5905         var->reset_val = bootValue;
5906         var->assign_hook = assign_hook;
5907         var->show_hook = show_hook;
5908         define_custom_variable(&var->gen);
5909 }
5910
5911 void
5912 DefineCustomIntVariable(const char *name,
5913                                                 const char *short_desc,
5914                                                 const char *long_desc,
5915                                                 int *valueAddr,
5916                                                 int bootValue,
5917                                                 int minValue,
5918                                                 int maxValue,
5919                                                 GucContext context,
5920                                                 int flags,
5921                                                 GucIntAssignHook assign_hook,
5922                                                 GucShowHook show_hook)
5923 {
5924         struct config_int *var;
5925
5926         var = (struct config_int *)
5927                 init_custom_variable(name, short_desc, long_desc, context, flags,
5928                                                          PGC_INT, sizeof(struct config_int));
5929         var->variable = valueAddr;
5930         var->boot_val = bootValue;
5931         var->reset_val = bootValue;
5932         var->min = minValue;
5933         var->max = maxValue;
5934         var->assign_hook = assign_hook;
5935         var->show_hook = show_hook;
5936         define_custom_variable(&var->gen);
5937 }
5938
5939 void
5940 DefineCustomRealVariable(const char *name,
5941                                                  const char *short_desc,
5942                                                  const char *long_desc,
5943                                                  double *valueAddr,
5944                                                  double bootValue,
5945                                                  double minValue,
5946                                                  double maxValue,
5947                                                  GucContext context,
5948                                                  int flags,
5949                                                  GucRealAssignHook assign_hook,
5950                                                  GucShowHook show_hook)
5951 {
5952         struct config_real *var;
5953
5954         var = (struct config_real *)
5955                 init_custom_variable(name, short_desc, long_desc, context, flags,
5956                                                          PGC_REAL, sizeof(struct config_real));
5957         var->variable = valueAddr;
5958         var->boot_val = bootValue;
5959         var->reset_val = bootValue;
5960         var->min = minValue;
5961         var->max = maxValue;
5962         var->assign_hook = assign_hook;
5963         var->show_hook = show_hook;
5964         define_custom_variable(&var->gen);
5965 }
5966
5967 void
5968 DefineCustomStringVariable(const char *name,
5969                                                    const char *short_desc,
5970                                                    const char *long_desc,
5971                                                    char **valueAddr,
5972                                                    const char *bootValue,
5973                                                    GucContext context,
5974                                                    int flags,
5975                                                    GucStringAssignHook assign_hook,
5976                                                    GucShowHook show_hook)
5977 {
5978         struct config_string *var;
5979
5980         var = (struct config_string *)
5981                 init_custom_variable(name, short_desc, long_desc, context, flags,
5982                                                          PGC_STRING, sizeof(struct config_string));
5983         var->variable = valueAddr;
5984         var->boot_val = bootValue;
5985         /* we could probably do without strdup, but keep it like normal case */
5986         if (var->boot_val)
5987                 var->reset_val = guc_strdup(ERROR, var->boot_val);
5988         var->assign_hook = assign_hook;
5989         var->show_hook = show_hook;
5990         define_custom_variable(&var->gen);
5991 }
5992
5993 void
5994 DefineCustomEnumVariable(const char *name,
5995                                                  const char *short_desc,
5996                                                  const char *long_desc,
5997                                                  int *valueAddr,
5998                                                  int bootValue,
5999                                                  const struct config_enum_entry * options,
6000                                                  GucContext context,
6001                                                  int flags,
6002                                                  GucEnumAssignHook assign_hook,
6003                                                  GucShowHook show_hook)
6004 {
6005         struct config_enum *var;
6006
6007         var = (struct config_enum *)
6008                 init_custom_variable(name, short_desc, long_desc, context, flags,
6009                                                          PGC_ENUM, sizeof(struct config_enum));
6010         var->variable = valueAddr;
6011         var->boot_val = bootValue;
6012         var->reset_val = bootValue;
6013         var->options = options;
6014         var->assign_hook = assign_hook;
6015         var->show_hook = show_hook;
6016         define_custom_variable(&var->gen);
6017 }
6018
6019 void
6020 EmitWarningsOnPlaceholders(const char *className)
6021 {
6022         int                     classLen = strlen(className);
6023         int                     i;
6024
6025         for (i = 0; i < num_guc_variables; i++)
6026         {
6027                 struct config_generic *var = guc_variables[i];
6028
6029                 if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
6030                         strncmp(className, var->name, classLen) == 0 &&
6031                         var->name[classLen] == GUC_QUALIFIER_SEPARATOR)
6032                 {
6033                         ereport(WARNING,
6034                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
6035                                          errmsg("unrecognized configuration parameter \"%s\"",
6036                                                         var->name)));
6037                 }
6038         }
6039 }
6040
6041
6042 /*
6043  * SHOW command
6044  */
6045 void
6046 GetPGVariable(const char *name, DestReceiver *dest)
6047 {
6048         if (guc_name_compare(name, "all") == 0)
6049                 ShowAllGUCConfig(dest);
6050         else
6051                 ShowGUCConfigOption(name, dest);
6052 }
6053
6054 TupleDesc
6055 GetPGVariableResultDesc(const char *name)
6056 {
6057         TupleDesc       tupdesc;
6058
6059         if (guc_name_compare(name, "all") == 0)
6060         {
6061                 /* need a tuple descriptor representing three TEXT columns */
6062                 tupdesc = CreateTemplateTupleDesc(3, false);
6063                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
6064                                                    TEXTOID, -1, 0);
6065                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
6066                                                    TEXTOID, -1, 0);
6067                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
6068                                                    TEXTOID, -1, 0);
6069         }
6070         else
6071         {
6072                 const char *varname;
6073
6074                 /* Get the canonical spelling of name */
6075                 (void) GetConfigOptionByName(name, &varname);
6076
6077                 /* need a tuple descriptor representing a single TEXT column */
6078                 tupdesc = CreateTemplateTupleDesc(1, false);
6079                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
6080                                                    TEXTOID, -1, 0);
6081         }
6082         return tupdesc;
6083 }
6084
6085
6086 /*
6087  * SHOW command
6088  */
6089 static void
6090 ShowGUCConfigOption(const char *name, DestReceiver *dest)
6091 {
6092         TupOutputState *tstate;
6093         TupleDesc       tupdesc;
6094         const char *varname;
6095         char       *value;
6096
6097         /* Get the value and canonical spelling of name */
6098         value = GetConfigOptionByName(name, &varname);
6099
6100         /* need a tuple descriptor representing a single TEXT column */
6101         tupdesc = CreateTemplateTupleDesc(1, false);
6102         TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
6103                                            TEXTOID, -1, 0);
6104
6105         /* prepare for projection of tuples */
6106         tstate = begin_tup_output_tupdesc(dest, tupdesc);
6107
6108         /* Send it */
6109         do_text_output_oneline(tstate, value);
6110
6111         end_tup_output(tstate);
6112 }
6113
6114 /*
6115  * SHOW ALL command
6116  */
6117 static void
6118 ShowAllGUCConfig(DestReceiver *dest)
6119 {
6120         bool            am_superuser = superuser();
6121         int                     i;
6122         TupOutputState *tstate;
6123         TupleDesc       tupdesc;
6124         Datum       values[3];
6125         bool            isnull[3] = { false, false, false };
6126
6127         /* need a tuple descriptor representing three TEXT columns */
6128         tupdesc = CreateTemplateTupleDesc(3, false);
6129         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
6130                                            TEXTOID, -1, 0);
6131         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
6132                                            TEXTOID, -1, 0);
6133         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
6134                                            TEXTOID, -1, 0);
6135
6136         /* prepare for projection of tuples */
6137         tstate = begin_tup_output_tupdesc(dest, tupdesc);
6138
6139         for (i = 0; i < num_guc_variables; i++)
6140         {
6141                 struct config_generic *conf = guc_variables[i];
6142                 char   *setting;
6143
6144                 if ((conf->flags & GUC_NO_SHOW_ALL) ||
6145                         ((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser))
6146                         continue;
6147
6148                 /* assign to the values array */
6149                 values[0] = PointerGetDatum(cstring_to_text(conf->name));
6150
6151                 setting = _ShowOption(conf, true);
6152                 if (setting)
6153                 {
6154                         values[1] = PointerGetDatum(cstring_to_text(setting));
6155                         isnull[1] = false;
6156                 }
6157                 else
6158                 {
6159                         values[1] = PointerGetDatum(NULL);
6160                         isnull[1] = true;
6161                 }
6162
6163                 values[2] = PointerGetDatum(cstring_to_text(conf->short_desc));
6164
6165                 /* send it to dest */
6166                 do_tup_output(tstate, values, isnull);
6167
6168                 /* clean up */
6169                 pfree(DatumGetPointer(values[0]));
6170                 if (setting)
6171                 {
6172                         pfree(setting);
6173                         pfree(DatumGetPointer(values[1]));
6174                 }
6175                 pfree(DatumGetPointer(values[2]));
6176         }
6177
6178         end_tup_output(tstate);
6179 }
6180
6181 /*
6182  * Return GUC variable value by name; optionally return canonical
6183  * form of name.  Return value is palloc'd.
6184  */
6185 char *
6186 GetConfigOptionByName(const char *name, const char **varname)
6187 {
6188         struct config_generic *record;
6189
6190         record = find_option(name, false, ERROR);
6191         if (record == NULL)
6192                 ereport(ERROR,
6193                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
6194                            errmsg("unrecognized configuration parameter \"%s\"", name)));
6195         if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
6196                 ereport(ERROR,
6197                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
6198                                  errmsg("must be superuser to examine \"%s\"", name)));
6199
6200         if (varname)
6201                 *varname = record->name;
6202
6203         return _ShowOption(record, true);
6204 }
6205
6206 /*
6207  * Return GUC variable value by variable number; optionally return canonical
6208  * form of name.  Return value is palloc'd.
6209  */
6210 void
6211 GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
6212 {
6213         char            buffer[256];
6214         struct config_generic *conf;
6215
6216         /* check requested variable number valid */
6217         Assert((varnum >= 0) && (varnum < num_guc_variables));
6218
6219         conf = guc_variables[varnum];
6220
6221         if (noshow)
6222         {
6223                 if ((conf->flags & GUC_NO_SHOW_ALL) ||
6224                         ((conf->flags & GUC_SUPERUSER_ONLY) && !superuser()))
6225                         *noshow = true;
6226                 else
6227                         *noshow = false;
6228         }
6229
6230         /* first get the generic attributes */
6231
6232         /* name */
6233         values[0] = conf->name;
6234
6235         /* setting : use _ShowOption in order to avoid duplicating the logic */
6236         values[1] = _ShowOption(conf, false);
6237
6238         /* unit */
6239         if (conf->vartype == PGC_INT)
6240         {
6241                 static char buf[8];
6242
6243                 switch (conf->flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME))
6244                 {
6245                         case GUC_UNIT_KB:
6246                                 values[2] = "kB";
6247                                 break;
6248                         case GUC_UNIT_BLOCKS:
6249                                 snprintf(buf, sizeof(buf), "%dkB", BLCKSZ / 1024);
6250                                 values[2] = buf;
6251                                 break;
6252                         case GUC_UNIT_XBLOCKS:
6253                                 snprintf(buf, sizeof(buf), "%dkB", XLOG_BLCKSZ / 1024);
6254                                 values[2] = buf;
6255                                 break;
6256                         case GUC_UNIT_MS:
6257                                 values[2] = "ms";
6258                                 break;
6259                         case GUC_UNIT_S:
6260                                 values[2] = "s";
6261                                 break;
6262                         case GUC_UNIT_MIN:
6263                                 values[2] = "min";
6264                                 break;
6265                         default:
6266                                 values[2] = "";
6267                                 break;
6268                 }
6269         }
6270         else
6271                 values[2] = NULL;
6272
6273         /* group */
6274         values[3] = config_group_names[conf->group];
6275
6276         /* short_desc */
6277         values[4] = conf->short_desc;
6278
6279         /* extra_desc */
6280         values[5] = conf->long_desc;
6281
6282         /* context */
6283         values[6] = GucContext_Names[conf->context];
6284
6285         /* vartype */
6286         values[7] = config_type_names[conf->vartype];
6287
6288         /* source */
6289         values[8] = GucSource_Names[conf->source];
6290
6291         /* now get the type specifc attributes */
6292         switch (conf->vartype)
6293         {
6294                 case PGC_BOOL:
6295                         {
6296                                 struct config_bool *lconf = (struct config_bool *) conf;
6297
6298                                 /* min_val */
6299                                 values[9] = NULL;
6300
6301                                 /* max_val */
6302                                 values[10] = NULL;
6303
6304                                 /* enumvals */
6305                                 values[11] = NULL;
6306
6307                                 /* boot_val */
6308                                 values[12] = pstrdup(lconf->boot_val ? "on" : "off");
6309
6310                                 /* reset_val */
6311                                 values[13] = pstrdup(lconf->reset_val ? "on" : "off");
6312                         }
6313                         break;
6314
6315                 case PGC_INT:
6316                         {
6317                                 struct config_int *lconf = (struct config_int *) conf;
6318
6319                                 /* min_val */
6320                                 snprintf(buffer, sizeof(buffer), "%d", lconf->min);
6321                                 values[9] = pstrdup(buffer);
6322
6323                                 /* max_val */
6324                                 snprintf(buffer, sizeof(buffer), "%d", lconf->max);
6325                                 values[10] = pstrdup(buffer);
6326
6327                                 /* enumvals */
6328                                 values[11] = NULL;
6329
6330                                 /* boot_val */
6331                                 snprintf(buffer, sizeof(buffer), "%d", lconf->boot_val);
6332                                 values[12] = pstrdup(buffer);
6333
6334                                 /* reset_val */
6335                                 snprintf(buffer, sizeof(buffer), "%d", lconf->reset_val);
6336                                 values[13] = pstrdup(buffer);
6337                         }
6338                         break;
6339
6340                 case PGC_REAL:
6341                         {
6342                                 struct config_real *lconf = (struct config_real *) conf;
6343
6344                                 /* min_val */
6345                                 snprintf(buffer, sizeof(buffer), "%g", lconf->min);
6346                                 values[9] = pstrdup(buffer);
6347
6348                                 /* max_val */
6349                                 snprintf(buffer, sizeof(buffer), "%g", lconf->max);
6350                                 values[10] = pstrdup(buffer);
6351
6352                                 /* enumvals */
6353                                 values[11] = NULL;
6354
6355                                 /* boot_val */
6356                                 snprintf(buffer, sizeof(buffer), "%g", lconf->boot_val);
6357                                 values[12] = pstrdup(buffer);
6358
6359                                 /* reset_val */
6360                                 snprintf(buffer, sizeof(buffer), "%g", lconf->reset_val);
6361                                 values[13] = pstrdup(buffer);
6362                         }
6363                         break;
6364
6365                 case PGC_STRING:
6366                         {
6367                                 struct config_string *lconf = (struct config_string *) conf;
6368
6369                                 /* min_val */
6370                                 values[9] = NULL;
6371
6372                                 /* max_val */
6373                                 values[10] = NULL;
6374
6375                                 /* enumvals */
6376                                 values[11] = NULL;
6377
6378                                 /* boot_val */
6379                                 if (lconf->boot_val == NULL)
6380                                         values[12] = NULL;
6381                                 else
6382                                         values[12] = pstrdup(lconf->boot_val);
6383
6384                                 /* reset_val */
6385                                 if (lconf->reset_val == NULL)
6386                                         values[13] = NULL;
6387                                 else
6388                                         values[13] = pstrdup(lconf->reset_val);
6389                         }
6390                         break;
6391
6392                 case PGC_ENUM:
6393                         {
6394                                 struct config_enum *lconf = (struct config_enum *) conf;
6395
6396                                 /* min_val */
6397                                 values[9] = NULL;
6398
6399                                 /* max_val */
6400                                 values[10] = NULL;
6401
6402                                 /* enumvals */
6403
6404                                 /*
6405                                  * NOTE! enumvals with double quotes in them are not
6406                                  * supported!
6407                                  */
6408                                 values[11] = config_enum_get_options((struct config_enum *) conf,
6409                                                                                                          "{\"", "\"}", "\",\"");
6410
6411                                 /* boot_val */
6412                                 values[12] = pstrdup(config_enum_lookup_by_value(lconf,
6413                                                                                                                    lconf->boot_val));
6414
6415                                 /* reset_val */
6416                                 values[13] = pstrdup(config_enum_lookup_by_value(lconf,
6417                                                                                                                   lconf->reset_val));
6418                         }
6419                         break;
6420
6421                 default:
6422                         {
6423                                 /*
6424                                  * should never get here, but in case we do, set 'em to NULL
6425                                  */
6426
6427                                 /* min_val */
6428                                 values[9] = NULL;
6429
6430                                 /* max_val */
6431                                 values[10] = NULL;
6432
6433                                 /* enumvals */
6434                                 values[11] = NULL;
6435
6436                                 /* boot_val */
6437                                 values[12] = NULL;
6438
6439                                 /* reset_val */
6440                                 values[13] = NULL;
6441                         }
6442                         break;
6443         }
6444
6445         /*
6446          * If the setting came from a config file, set the source location. For
6447          * security reasons, we don't show source file/line number for
6448          * non-superusers.
6449          */
6450         if (conf->source == PGC_S_FILE && superuser())
6451         {
6452                 values[14] = conf->sourcefile;
6453                 snprintf(buffer, sizeof(buffer), "%d", conf->sourceline);
6454                 values[15] = pstrdup(buffer);
6455         }
6456         else
6457         {
6458                 values[14] = NULL;
6459                 values[15] = NULL;
6460         }
6461 }
6462
6463 /*
6464  * Return the total number of GUC variables
6465  */
6466 int
6467 GetNumConfigOptions(void)
6468 {
6469         return num_guc_variables;
6470 }
6471
6472 /*
6473  * show_config_by_name - equiv to SHOW X command but implemented as
6474  * a function.
6475  */
6476 Datum
6477 show_config_by_name(PG_FUNCTION_ARGS)
6478 {
6479         char       *varname;
6480         char       *varval;
6481
6482         /* Get the GUC variable name */
6483         varname = TextDatumGetCString(PG_GETARG_DATUM(0));
6484
6485         /* Get the value */
6486         varval = GetConfigOptionByName(varname, NULL);
6487
6488         /* Convert to text */
6489         PG_RETURN_TEXT_P(cstring_to_text(varval));
6490 }
6491
6492 /*
6493  * show_all_settings - equiv to SHOW ALL command but implemented as
6494  * a Table Function.
6495  */
6496 #define NUM_PG_SETTINGS_ATTS    16
6497
6498 Datum
6499 show_all_settings(PG_FUNCTION_ARGS)
6500 {
6501         FuncCallContext *funcctx;
6502         TupleDesc       tupdesc;
6503         int                     call_cntr;
6504         int                     max_calls;
6505         AttInMetadata *attinmeta;
6506         MemoryContext oldcontext;
6507
6508         /* stuff done only on the first call of the function */
6509         if (SRF_IS_FIRSTCALL())
6510         {
6511                 /* create a function context for cross-call persistence */
6512                 funcctx = SRF_FIRSTCALL_INIT();
6513
6514                 /*
6515                  * switch to memory context appropriate for multiple function calls
6516                  */
6517                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
6518
6519                 /*
6520                  * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
6521                  * of the appropriate types
6522                  */
6523                 tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS, false);
6524                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
6525                                                    TEXTOID, -1, 0);
6526                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
6527                                                    TEXTOID, -1, 0);
6528                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit",
6529                                                    TEXTOID, -1, 0);
6530                 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category",
6531                                                    TEXTOID, -1, 0);
6532                 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc",
6533                                                    TEXTOID, -1, 0);
6534                 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc",
6535                                                    TEXTOID, -1, 0);
6536                 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context",
6537                                                    TEXTOID, -1, 0);
6538                 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype",
6539                                                    TEXTOID, -1, 0);
6540                 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source",
6541                                                    TEXTOID, -1, 0);
6542                 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val",
6543                                                    TEXTOID, -1, 0);
6544                 TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
6545                                                    TEXTOID, -1, 0);
6546                 TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
6547                                                    TEXTARRAYOID, -1, 0);
6548                 TupleDescInitEntry(tupdesc, (AttrNumber) 13, "boot_val",
6549                                                    TEXTOID, -1, 0);
6550                 TupleDescInitEntry(tupdesc, (AttrNumber) 14, "reset_val",
6551                                                    TEXTOID, -1, 0);
6552                 TupleDescInitEntry(tupdesc, (AttrNumber) 15, "sourcefile",
6553                                                    TEXTOID, -1, 0);
6554                 TupleDescInitEntry(tupdesc, (AttrNumber) 16, "sourceline",
6555                                                    INT4OID, -1, 0);
6556
6557                 /*
6558                  * Generate attribute metadata needed later to produce tuples from raw
6559                  * C strings
6560                  */
6561                 attinmeta = TupleDescGetAttInMetadata(tupdesc);
6562                 funcctx->attinmeta = attinmeta;
6563
6564                 /* total number of tuples to be returned */
6565                 funcctx->max_calls = GetNumConfigOptions();
6566
6567                 MemoryContextSwitchTo(oldcontext);
6568         }
6569
6570         /* stuff done on every call of the function */
6571         funcctx = SRF_PERCALL_SETUP();
6572
6573         call_cntr = funcctx->call_cntr;
6574         max_calls = funcctx->max_calls;
6575         attinmeta = funcctx->attinmeta;
6576
6577         if (call_cntr < max_calls)      /* do when there is more left to send */
6578         {
6579                 char       *values[NUM_PG_SETTINGS_ATTS];
6580                 bool            noshow;
6581                 HeapTuple       tuple;
6582                 Datum           result;
6583
6584                 /*
6585                  * Get the next visible GUC variable name and value
6586                  */
6587                 do
6588                 {
6589                         GetConfigOptionByNum(call_cntr, (const char **) values, &noshow);
6590                         if (noshow)
6591                         {
6592                                 /* bump the counter and get the next config setting */
6593                                 call_cntr = ++funcctx->call_cntr;
6594
6595                                 /* make sure we haven't gone too far now */
6596                                 if (call_cntr >= max_calls)
6597                                         SRF_RETURN_DONE(funcctx);
6598                         }
6599                 } while (noshow);
6600
6601                 /* build a tuple */
6602                 tuple = BuildTupleFromCStrings(attinmeta, values);
6603
6604                 /* make the tuple into a datum */
6605                 result = HeapTupleGetDatum(tuple);
6606
6607                 SRF_RETURN_NEXT(funcctx, result);
6608         }
6609         else
6610         {
6611                 /* do when there is no more left */
6612                 SRF_RETURN_DONE(funcctx);
6613         }
6614 }
6615
6616 static char *
6617 _ShowOption(struct config_generic * record, bool use_units)
6618 {
6619         char            buffer[256];
6620         const char *val;
6621
6622         switch (record->vartype)
6623         {
6624                 case PGC_BOOL:
6625                         {
6626                                 struct config_bool *conf = (struct config_bool *) record;
6627
6628                                 if (conf->show_hook)
6629                                         val = (*conf->show_hook) ();
6630                                 else
6631                                         val = *conf->variable ? "on" : "off";
6632                         }
6633                         break;
6634
6635                 case PGC_INT:
6636                         {
6637                                 struct config_int *conf = (struct config_int *) record;
6638
6639                                 if (conf->show_hook)
6640                                         val = (*conf->show_hook) ();
6641                                 else
6642                                 {
6643                                         /*
6644                                          * Use int64 arithmetic to avoid overflows in units
6645                                          * conversion.
6646                                          */
6647                                         int64           result = *conf->variable;
6648                                         const char *unit;
6649
6650                                         if (use_units && result > 0 &&
6651                                                 (record->flags & GUC_UNIT_MEMORY))
6652                                         {
6653                                                 switch (record->flags & GUC_UNIT_MEMORY)
6654                                                 {
6655                                                         case GUC_UNIT_BLOCKS:
6656                                                                 result *= BLCKSZ / 1024;
6657                                                                 break;
6658                                                         case GUC_UNIT_XBLOCKS:
6659                                                                 result *= XLOG_BLCKSZ / 1024;
6660                                                                 break;
6661                                                 }
6662
6663                                                 if (result % KB_PER_GB == 0)
6664                                                 {
6665                                                         result /= KB_PER_GB;
6666                                                         unit = "GB";
6667                                                 }
6668                                                 else if (result % KB_PER_MB == 0)
6669                                                 {
6670                                                         result /= KB_PER_MB;
6671                                                         unit = "MB";
6672                                                 }
6673                                                 else
6674                                                 {
6675                                                         unit = "kB";
6676                                                 }
6677                                         }
6678                                         else if (use_units && result > 0 &&
6679                                                          (record->flags & GUC_UNIT_TIME))
6680                                         {
6681                                                 switch (record->flags & GUC_UNIT_TIME)
6682                                                 {
6683                                                         case GUC_UNIT_S:
6684                                                                 result *= MS_PER_S;
6685                                                                 break;
6686                                                         case GUC_UNIT_MIN:
6687                                                                 result *= MS_PER_MIN;
6688                                                                 break;
6689                                                 }
6690
6691                                                 if (result % MS_PER_D == 0)
6692                                                 {
6693                                                         result /= MS_PER_D;
6694                                                         unit = "d";
6695                                                 }
6696                                                 else if (result % MS_PER_H == 0)
6697                                                 {
6698                                                         result /= MS_PER_H;
6699                                                         unit = "h";
6700                                                 }
6701                                                 else if (result % MS_PER_MIN == 0)
6702                                                 {
6703                                                         result /= MS_PER_MIN;
6704                                                         unit = "min";
6705                                                 }
6706                                                 else if (result % MS_PER_S == 0)
6707                                                 {
6708                                                         result /= MS_PER_S;
6709                                                         unit = "s";
6710                                                 }
6711                                                 else
6712                                                 {
6713                                                         unit = "ms";
6714                                                 }
6715                                         }
6716                                         else
6717                                                 unit = "";
6718
6719                                         snprintf(buffer, sizeof(buffer), INT64_FORMAT "%s",
6720                                                          result, unit);
6721                                         val = buffer;
6722                                 }
6723                         }
6724                         break;
6725
6726                 case PGC_REAL:
6727                         {
6728                                 struct config_real *conf = (struct config_real *) record;
6729
6730                                 if (conf->show_hook)
6731                                         val = (*conf->show_hook) ();
6732                                 else
6733                                 {
6734                                         snprintf(buffer, sizeof(buffer), "%g",
6735                                                          *conf->variable);
6736                                         val = buffer;
6737                                 }
6738                         }
6739                         break;
6740
6741                 case PGC_STRING:
6742                         {
6743                                 struct config_string *conf = (struct config_string *) record;
6744
6745                                 if (conf->show_hook)
6746                                         val = (*conf->show_hook) ();
6747                                 else if (*conf->variable && **conf->variable)
6748                                         val = *conf->variable;
6749                                 else
6750                                         val = "";
6751                         }
6752                         break;
6753
6754                 case PGC_ENUM:
6755                         {
6756                                 struct config_enum *conf = (struct config_enum *) record;
6757
6758                                 if (conf->show_hook)
6759                                         val = (*conf->show_hook) ();
6760                                 else
6761                                         val = config_enum_lookup_by_value(conf, *conf->variable);
6762                         }
6763                         break;
6764
6765                 default:
6766                         /* just to keep compiler quiet */
6767                         val = "???";
6768                         break;
6769         }
6770
6771         return pstrdup(val);
6772 }
6773
6774
6775 /*
6776  * Attempt (badly) to detect if a proposed new GUC setting is the same
6777  * as the current value.
6778  *
6779  * XXX this does not really work because it doesn't account for the
6780  * effects of canonicalization of string values by assign_hooks.
6781  */
6782 static bool
6783 is_newvalue_equal(struct config_generic * record, const char *newvalue)
6784 {
6785         /* newvalue == NULL isn't supported */
6786         Assert(newvalue != NULL);
6787
6788         switch (record->vartype)
6789         {
6790                 case PGC_BOOL:
6791                         {
6792                                 struct config_bool *conf = (struct config_bool *) record;
6793                                 bool            newval;
6794
6795                                 return parse_bool(newvalue, &newval)
6796                                         && *conf->variable == newval;
6797                         }
6798                 case PGC_INT:
6799                         {
6800                                 struct config_int *conf = (struct config_int *) record;
6801                                 int                     newval;
6802
6803                                 return parse_int(newvalue, &newval, record->flags, NULL)
6804                                         && *conf->variable == newval;
6805                         }
6806                 case PGC_REAL:
6807                         {
6808                                 struct config_real *conf = (struct config_real *) record;
6809                                 double          newval;
6810
6811                                 return parse_real(newvalue, &newval)
6812                                         && *conf->variable == newval;
6813                         }
6814                 case PGC_STRING:
6815                         {
6816                                 struct config_string *conf = (struct config_string *) record;
6817
6818                                 return *conf->variable != NULL &&
6819                                         strcmp(*conf->variable, newvalue) == 0;
6820                         }
6821
6822                 case PGC_ENUM:
6823                         {
6824                                 struct config_enum *conf = (struct config_enum *) record;
6825                                 int                     newval;
6826
6827                                 return config_enum_lookup_by_name(conf, newvalue, &newval) &&
6828                                         *conf->variable == newval;
6829                         }
6830         }
6831
6832         return false;
6833 }
6834
6835
6836 #ifdef EXEC_BACKEND
6837
6838 /*
6839  *      These routines dump out all non-default GUC options into a binary
6840  *      file that is read by all exec'ed backends.  The format is:
6841  *
6842  *              variable name, string, null terminated
6843  *              variable value, string, null terminated
6844  *              variable source, integer
6845  */
6846 static void
6847 write_one_nondefault_variable(FILE *fp, struct config_generic * gconf)
6848 {
6849         if (gconf->source == PGC_S_DEFAULT)
6850                 return;
6851
6852         fprintf(fp, "%s", gconf->name);
6853         fputc(0, fp);
6854
6855         switch (gconf->vartype)
6856         {
6857                 case PGC_BOOL:
6858                         {
6859                                 struct config_bool *conf = (struct config_bool *) gconf;
6860
6861                                 if (*conf->variable)
6862                                         fprintf(fp, "true");
6863                                 else
6864                                         fprintf(fp, "false");
6865                         }
6866                         break;
6867
6868                 case PGC_INT:
6869                         {
6870                                 struct config_int *conf = (struct config_int *) gconf;
6871
6872                                 fprintf(fp, "%d", *conf->variable);
6873                         }
6874                         break;
6875
6876                 case PGC_REAL:
6877                         {
6878                                 struct config_real *conf = (struct config_real *) gconf;
6879
6880                                 /* Could lose precision here? */
6881                                 fprintf(fp, "%f", *conf->variable);
6882                         }
6883                         break;
6884
6885                 case PGC_STRING:
6886                         {
6887                                 struct config_string *conf = (struct config_string *) gconf;
6888
6889                                 fprintf(fp, "%s", *conf->variable);
6890                         }
6891                         break;
6892
6893                 case PGC_ENUM:
6894                         {
6895                                 struct config_enum *conf = (struct config_enum *) gconf;
6896
6897                                 fprintf(fp, "%s",
6898                                                 config_enum_lookup_by_value(conf, *conf->variable));
6899                         }
6900                         break;
6901         }
6902
6903         fputc(0, fp);
6904
6905         fwrite(&gconf->source, sizeof(gconf->source), 1, fp);
6906 }
6907
6908 void
6909 write_nondefault_variables(GucContext context)
6910 {
6911         int                     elevel;
6912         FILE       *fp;
6913         struct config_generic *cvc_conf;
6914         int                     i;
6915
6916         Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
6917
6918         elevel = (context == PGC_SIGHUP) ? LOG : ERROR;
6919
6920         /*
6921          * Open file
6922          */
6923         fp = AllocateFile(CONFIG_EXEC_PARAMS_NEW, "w");
6924         if (!fp)
6925         {
6926                 ereport(elevel,
6927                                 (errcode_for_file_access(),
6928                                  errmsg("could not write to file \"%s\": %m",
6929                                                 CONFIG_EXEC_PARAMS_NEW)));
6930                 return;
6931         }
6932
6933         /*
6934          * custom_variable_classes must be written out first; otherwise we might
6935          * reject custom variable values while reading the file.
6936          */
6937         cvc_conf = find_option("custom_variable_classes", false, ERROR);
6938         if (cvc_conf)
6939                 write_one_nondefault_variable(fp, cvc_conf);
6940
6941         for (i = 0; i < num_guc_variables; i++)
6942         {
6943                 struct config_generic *gconf = guc_variables[i];
6944
6945                 if (gconf != cvc_conf)
6946                         write_one_nondefault_variable(fp, gconf);
6947         }
6948
6949         if (FreeFile(fp))
6950         {
6951                 ereport(elevel,
6952                                 (errcode_for_file_access(),
6953                                  errmsg("could not write to file \"%s\": %m",
6954                                                 CONFIG_EXEC_PARAMS_NEW)));
6955                 return;
6956         }
6957
6958         /*
6959          * Put new file in place.  This could delay on Win32, but we don't hold
6960          * any exclusive locks.
6961          */
6962         rename(CONFIG_EXEC_PARAMS_NEW, CONFIG_EXEC_PARAMS);
6963 }
6964
6965
6966 /*
6967  *      Read string, including null byte from file
6968  *
6969  *      Return NULL on EOF and nothing read
6970  */
6971 static char *
6972 read_string_with_null(FILE *fp)
6973 {
6974         int                     i = 0,
6975                                 ch,
6976                                 maxlen = 256;
6977         char       *str = NULL;
6978
6979         do
6980         {
6981                 if ((ch = fgetc(fp)) == EOF)
6982                 {
6983                         if (i == 0)
6984                                 return NULL;
6985                         else
6986                                 elog(FATAL, "invalid format of exec config params file");
6987                 }
6988                 if (i == 0)
6989                         str = guc_malloc(FATAL, maxlen);
6990                 else if (i == maxlen)
6991                         str = guc_realloc(FATAL, str, maxlen *= 2);
6992                 str[i++] = ch;
6993         } while (ch != 0);
6994
6995         return str;
6996 }
6997
6998
6999 /*
7000  *      This routine loads a previous postmaster dump of its non-default
7001  *      settings.
7002  */
7003 void
7004 read_nondefault_variables(void)
7005 {
7006         FILE       *fp;
7007         char       *varname,
7008                            *varvalue;
7009         int                     varsource;
7010
7011         /*
7012          * Open file
7013          */
7014         fp = AllocateFile(CONFIG_EXEC_PARAMS, "r");
7015         if (!fp)
7016         {
7017                 /* File not found is fine */
7018                 if (errno != ENOENT)
7019                         ereport(FATAL,
7020                                         (errcode_for_file_access(),
7021                                          errmsg("could not read from file \"%s\": %m",
7022                                                         CONFIG_EXEC_PARAMS)));
7023                 return;
7024         }
7025
7026         for (;;)
7027         {
7028                 struct config_generic *record;
7029
7030                 if ((varname = read_string_with_null(fp)) == NULL)
7031                         break;
7032
7033                 if ((record = find_option(varname, true, FATAL)) == NULL)
7034                         elog(FATAL, "failed to locate variable %s in exec config params file", varname);
7035                 if ((varvalue = read_string_with_null(fp)) == NULL)
7036                         elog(FATAL, "invalid format of exec config params file");
7037                 if (fread(&varsource, sizeof(varsource), 1, fp) == 0)
7038                         elog(FATAL, "invalid format of exec config params file");
7039
7040                 (void) set_config_option(varname, varvalue, record->context,
7041                                                                  varsource, GUC_ACTION_SET, true);
7042                 free(varname);
7043                 free(varvalue);
7044         }
7045
7046         FreeFile(fp);
7047 }
7048 #endif   /* EXEC_BACKEND */
7049
7050
7051 /*
7052  * A little "long argument" simulation, although not quite GNU
7053  * compliant. Takes a string of the form "some-option=some value" and
7054  * returns name = "some_option" and value = "some value" in malloc'ed
7055  * storage. Note that '-' is converted to '_' in the option name. If
7056  * there is no '=' in the input string then value will be NULL.
7057  */
7058 void
7059 ParseLongOption(const char *string, char **name, char **value)
7060 {
7061         size_t          equal_pos;
7062         char       *cp;
7063
7064         AssertArg(string);
7065         AssertArg(name);
7066         AssertArg(value);
7067
7068         equal_pos = strcspn(string, "=");
7069
7070         if (string[equal_pos] == '=')
7071         {
7072                 *name = guc_malloc(FATAL, equal_pos + 1);
7073                 strlcpy(*name, string, equal_pos + 1);
7074
7075                 *value = guc_strdup(FATAL, &string[equal_pos + 1]);
7076         }
7077         else
7078         {
7079                 /* no equal sign in string */
7080                 *name = guc_strdup(FATAL, string);
7081                 *value = NULL;
7082         }
7083
7084         for (cp = *name; *cp; cp++)
7085                 if (*cp == '-')
7086                         *cp = '_';
7087 }
7088
7089
7090 /*
7091  * Handle options fetched from pg_database.datconfig, pg_authid.rolconfig,
7092  * pg_proc.proconfig, etc.      Caller must specify proper context/source/action.
7093  *
7094  * The array parameter must be an array of TEXT (it must not be NULL).
7095  */
7096 void
7097 ProcessGUCArray(ArrayType *array,
7098                                 GucContext context, GucSource source, GucAction action)
7099 {
7100         int                     i;
7101
7102         Assert(array != NULL);
7103         Assert(ARR_ELEMTYPE(array) == TEXTOID);
7104         Assert(ARR_NDIM(array) == 1);
7105         Assert(ARR_LBOUND(array)[0] == 1);
7106
7107         for (i = 1; i <= ARR_DIMS(array)[0]; i++)
7108         {
7109                 Datum           d;
7110                 bool            isnull;
7111                 char       *s;
7112                 char       *name;
7113                 char       *value;
7114
7115                 d = array_ref(array, 1, &i,
7116                                           -1 /* varlenarray */ ,
7117                                           -1 /* TEXT's typlen */ ,
7118                                           false /* TEXT's typbyval */ ,
7119                                           'i' /* TEXT's typalign */ ,
7120                                           &isnull);
7121
7122                 if (isnull)
7123                         continue;
7124
7125                 s = TextDatumGetCString(d);
7126
7127                 ParseLongOption(s, &name, &value);
7128                 if (!value)
7129                 {
7130                         ereport(WARNING,
7131                                         (errcode(ERRCODE_SYNTAX_ERROR),
7132                                          errmsg("could not parse setting for parameter \"%s\"",
7133                                                         name)));
7134                         free(name);
7135                         continue;
7136                 }
7137
7138                 (void) set_config_option(name, value, context, source, action, true);
7139
7140                 free(name);
7141                 if (value)
7142                         free(value);
7143         }
7144 }
7145
7146
7147 /*
7148  * Add an entry to an option array.  The array parameter may be NULL
7149  * to indicate the current table entry is NULL.
7150  */
7151 ArrayType *
7152 GUCArrayAdd(ArrayType *array, const char *name, const char *value)
7153 {
7154         const char *varname;
7155         Datum           datum;
7156         char       *newval;
7157         ArrayType  *a;
7158
7159         Assert(name);
7160         Assert(value);
7161
7162         /* test if the option is valid */
7163         set_config_option(name, value,
7164                                           superuser() ? PGC_SUSET : PGC_USERSET,
7165                                           PGC_S_TEST, GUC_ACTION_SET, false);
7166
7167         /* convert name to canonical spelling, so we can use plain strcmp */
7168         (void) GetConfigOptionByName(name, &varname);
7169         name = varname;
7170
7171         newval = palloc(strlen(name) + 1 + strlen(value) + 1);
7172         sprintf(newval, "%s=%s", name, value);
7173         datum = CStringGetTextDatum(newval);
7174
7175         if (array)
7176         {
7177                 int                     index;
7178                 bool            isnull;
7179                 int                     i;
7180
7181                 Assert(ARR_ELEMTYPE(array) == TEXTOID);
7182                 Assert(ARR_NDIM(array) == 1);
7183                 Assert(ARR_LBOUND(array)[0] == 1);
7184
7185                 index = ARR_DIMS(array)[0] + 1; /* add after end */
7186
7187                 for (i = 1; i <= ARR_DIMS(array)[0]; i++)
7188                 {
7189                         Datum           d;
7190                         char       *current;
7191
7192                         d = array_ref(array, 1, &i,
7193                                                   -1 /* varlenarray */ ,
7194                                                   -1 /* TEXT's typlen */ ,
7195                                                   false /* TEXT's typbyval */ ,
7196                                                   'i' /* TEXT's typalign */ ,
7197                                                   &isnull);
7198                         if (isnull)
7199                                 continue;
7200                         current = TextDatumGetCString(d);
7201                         if (strncmp(current, newval, strlen(name) + 1) == 0)
7202                         {
7203                                 index = i;
7204                                 break;
7205                         }
7206                 }
7207
7208                 a = array_set(array, 1, &index,
7209                                           datum,
7210                                           false,
7211                                           -1 /* varlena array */ ,
7212                                           -1 /* TEXT's typlen */ ,
7213                                           false /* TEXT's typbyval */ ,
7214                                           'i' /* TEXT's typalign */ );
7215         }
7216         else
7217                 a = construct_array(&datum, 1,
7218                                                         TEXTOID,
7219                                                         -1, false, 'i');
7220
7221         return a;
7222 }
7223
7224
7225 /*
7226  * Delete an entry from an option array.  The array parameter may be NULL
7227  * to indicate the current table entry is NULL.  Also, if the return value
7228  * is NULL then a null should be stored.
7229  */
7230 ArrayType *
7231 GUCArrayDelete(ArrayType *array, const char *name)
7232 {
7233         const char *varname;
7234         ArrayType  *newarray;
7235         int                     i;
7236         int                     index;
7237
7238         Assert(name);
7239
7240         /* test if the option is valid */
7241         set_config_option(name, NULL,
7242                                           superuser() ? PGC_SUSET : PGC_USERSET,
7243                                           PGC_S_TEST, GUC_ACTION_SET, false);
7244
7245         /* convert name to canonical spelling, so we can use plain strcmp */
7246         (void) GetConfigOptionByName(name, &varname);
7247         name = varname;
7248
7249         /* if array is currently null, then surely nothing to delete */
7250         if (!array)
7251                 return NULL;
7252
7253         newarray = NULL;
7254         index = 1;
7255
7256         for (i = 1; i <= ARR_DIMS(array)[0]; i++)
7257         {
7258                 Datum           d;
7259                 char       *val;
7260                 bool            isnull;
7261
7262                 d = array_ref(array, 1, &i,
7263                                           -1 /* varlenarray */ ,
7264                                           -1 /* TEXT's typlen */ ,
7265                                           false /* TEXT's typbyval */ ,
7266                                           'i' /* TEXT's typalign */ ,
7267                                           &isnull);
7268                 if (isnull)
7269                         continue;
7270                 val = TextDatumGetCString(d);
7271
7272                 /* ignore entry if it's what we want to delete */
7273                 if (strncmp(val, name, strlen(name)) == 0
7274                         && val[strlen(name)] == '=')
7275                         continue;
7276
7277                 /* else add it to the output array */
7278                 if (newarray)
7279                 {
7280                         newarray = array_set(newarray, 1, &index,
7281                                                                  d,
7282                                                                  false,
7283                                                                  -1 /* varlenarray */ ,
7284                                                                  -1 /* TEXT's typlen */ ,
7285                                                                  false /* TEXT's typbyval */ ,
7286                                                                  'i' /* TEXT's typalign */ );
7287                 }
7288                 else
7289                         newarray = construct_array(&d, 1,
7290                                                                            TEXTOID,
7291                                                                            -1, false, 'i');
7292
7293                 index++;
7294         }
7295
7296         return newarray;
7297 }
7298
7299
7300 /*
7301  * assign_hook and show_hook subroutines
7302  */
7303
7304 static const char *
7305 assign_log_destination(const char *value, bool doit, GucSource source)
7306 {
7307         char       *rawstring;
7308         List       *elemlist;
7309         ListCell   *l;
7310         int                     newlogdest = 0;
7311
7312         /* Need a modifiable copy of string */
7313         rawstring = pstrdup(value);
7314
7315         /* Parse string into list of identifiers */
7316         if (!SplitIdentifierString(rawstring, ',', &elemlist))
7317         {
7318                 /* syntax error in list */
7319                 pfree(rawstring);
7320                 list_free(elemlist);
7321                 ereport(GUC_complaint_elevel(source),
7322                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7323                    errmsg("invalid list syntax for parameter \"log_destination\"")));
7324                 return NULL;
7325         }
7326
7327         foreach(l, elemlist)
7328         {
7329                 char       *tok = (char *) lfirst(l);
7330
7331                 if (pg_strcasecmp(tok, "stderr") == 0)
7332                         newlogdest |= LOG_DESTINATION_STDERR;
7333                 else if (pg_strcasecmp(tok, "csvlog") == 0)
7334                         newlogdest |= LOG_DESTINATION_CSVLOG;
7335 #ifdef HAVE_SYSLOG
7336                 else if (pg_strcasecmp(tok, "syslog") == 0)
7337                         newlogdest |= LOG_DESTINATION_SYSLOG;
7338 #endif
7339 #ifdef WIN32
7340                 else if (pg_strcasecmp(tok, "eventlog") == 0)
7341                         newlogdest |= LOG_DESTINATION_EVENTLOG;
7342 #endif
7343                 else
7344                 {
7345                         ereport(GUC_complaint_elevel(source),
7346                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7347                                   errmsg("unrecognized \"log_destination\" key word: \"%s\"",
7348                                                  tok)));
7349                         pfree(rawstring);
7350                         list_free(elemlist);
7351                         return NULL;
7352                 }
7353         }
7354
7355         if (doit)
7356                 Log_destination = newlogdest;
7357
7358         pfree(rawstring);
7359         list_free(elemlist);
7360
7361         return value;
7362 }
7363
7364 #ifdef HAVE_SYSLOG
7365
7366 static bool
7367 assign_syslog_facility(int newval, bool doit, GucSource source)
7368 {
7369         if (doit)
7370                 set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
7371                                                           newval);
7372
7373         return true;
7374 }
7375
7376 static const char *
7377 assign_syslog_ident(const char *ident, bool doit, GucSource source)
7378 {
7379         if (doit)
7380                 set_syslog_parameters(ident, syslog_facility);
7381
7382         return ident;
7383 }
7384 #endif   /* HAVE_SYSLOG */
7385
7386
7387 static bool
7388 assign_session_replication_role(int newval, bool doit, GucSource source)
7389 {
7390         /*
7391          * Must flush the plan cache when changing replication role; but don't
7392          * flush unnecessarily.
7393          */
7394         if (doit && SessionReplicationRole != newval)
7395         {
7396                 ResetPlanCache();
7397         }
7398
7399         return true;
7400 }
7401
7402 static const char *
7403 show_num_temp_buffers(void)
7404 {
7405         /*
7406          * We show the GUC var until local buffers have been initialized, and
7407          * NLocBuffer afterwards.
7408          */
7409         static char nbuf[32];
7410
7411         sprintf(nbuf, "%d", NLocBuffer ? NLocBuffer : num_temp_buffers);
7412         return nbuf;
7413 }
7414
7415 static bool
7416 assign_phony_autocommit(bool newval, bool doit, GucSource source)
7417 {
7418         if (!newval)
7419         {
7420                 ereport(GUC_complaint_elevel(source),
7421                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7422                                  errmsg("SET AUTOCOMMIT TO OFF is no longer supported")));
7423                 return false;
7424         }
7425         return true;
7426 }
7427
7428 static const char *
7429 assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
7430 {
7431         /*
7432          * Check syntax. newval must be a comma separated list of identifiers.
7433          * Whitespace is allowed but removed from the result.
7434          */
7435         bool            hasSpaceAfterToken = false;
7436         const char *cp = newval;
7437         int                     symLen = 0;
7438         char            c;
7439         StringInfoData buf;
7440
7441         initStringInfo(&buf);
7442         while ((c = *cp++) != '\0')
7443         {
7444                 if (isspace((unsigned char) c))
7445                 {
7446                         if (symLen > 0)
7447                                 hasSpaceAfterToken = true;
7448                         continue;
7449                 }
7450
7451                 if (c == ',')
7452                 {
7453                         if (symLen > 0)         /* terminate identifier */
7454                         {
7455                                 appendStringInfoChar(&buf, ',');
7456                                 symLen = 0;
7457                         }
7458                         hasSpaceAfterToken = false;
7459                         continue;
7460                 }
7461
7462                 if (hasSpaceAfterToken || !(isalnum((unsigned char) c) || c == '_'))
7463                 {
7464                         /*
7465                          * Syntax error due to token following space after token or
7466                          * non-identifier character
7467                          */
7468                         pfree(buf.data);
7469                         return NULL;
7470                 }
7471                 appendStringInfoChar(&buf, c);
7472                 symLen++;
7473         }
7474
7475         /* Remove stray ',' at end */
7476         if (symLen == 0 && buf.len > 0)
7477                 buf.data[--buf.len] = '\0';
7478
7479         /* GUC wants the result malloc'd */
7480         newval = guc_strdup(LOG, buf.data);
7481
7482         pfree(buf.data);
7483         return newval;
7484 }
7485
7486 static bool
7487 assign_debug_assertions(bool newval, bool doit, GucSource source)
7488 {
7489 #ifndef USE_ASSERT_CHECKING
7490         if (newval)
7491         {
7492                 ereport(GUC_complaint_elevel(source),
7493                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7494                            errmsg("assertion checking is not supported by this build")));
7495                 return false;
7496         }
7497 #endif
7498         return true;
7499 }
7500
7501 static bool
7502 assign_bonjour(bool newval, bool doit, GucSource source)
7503 {
7504 #ifndef USE_BONJOUR
7505         if (newval)
7506         {
7507                 ereport(GUC_complaint_elevel(source),
7508                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7509                                  errmsg("Bonjour is not supported by this build")));
7510                 return false;
7511         }
7512 #endif
7513         return true;
7514 }
7515
7516 static bool
7517 assign_ssl(bool newval, bool doit, GucSource source)
7518 {
7519 #ifndef USE_SSL
7520         if (newval)
7521         {
7522                 ereport(GUC_complaint_elevel(source),
7523                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7524                                  errmsg("SSL is not supported by this build")));
7525                 return false;
7526         }
7527 #endif
7528         return true;
7529 }
7530
7531 static bool
7532 assign_stage_log_stats(bool newval, bool doit, GucSource source)
7533 {
7534         if (newval && log_statement_stats)
7535         {
7536                 ereport(GUC_complaint_elevel(source),
7537                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7538                                  errmsg("cannot enable parameter when \"log_statement_stats\" is true")));
7539                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
7540                 if (source != PGC_S_OVERRIDE)
7541                         return false;
7542         }
7543         return true;
7544 }
7545
7546 static bool
7547 assign_log_stats(bool newval, bool doit, GucSource source)
7548 {
7549         if (newval &&
7550                 (log_parser_stats || log_planner_stats || log_executor_stats))
7551         {
7552                 ereport(GUC_complaint_elevel(source),
7553                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7554                                  errmsg("cannot enable \"log_statement_stats\" when "
7555                                                 "\"log_parser_stats\", \"log_planner_stats\", "
7556                                                 "or \"log_executor_stats\" is true")));
7557                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
7558                 if (source != PGC_S_OVERRIDE)
7559                         return false;
7560         }
7561         return true;
7562 }
7563
7564 static bool
7565 assign_transaction_read_only(bool newval, bool doit, GucSource source)
7566 {
7567         /* Can't go to r/w mode inside a r/o transaction */
7568         if (newval == false && XactReadOnly && IsSubTransaction())
7569         {
7570                 ereport(GUC_complaint_elevel(source),
7571                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7572                                  errmsg("cannot set transaction read-write mode inside a read-only transaction")));
7573                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
7574                 if (source != PGC_S_OVERRIDE)
7575                         return false;
7576         }
7577
7578         /* Can't go to r/w mode while recovery is still active */
7579         if (newval == false && XactReadOnly && RecoveryInProgress())
7580         {
7581                 ereport(GUC_complaint_elevel(source),
7582                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7583                                  errmsg("cannot set transaction read-write mode during recovery")));
7584                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
7585                 if (source != PGC_S_OVERRIDE)
7586                         return false;
7587         }
7588
7589         return true;
7590 }
7591
7592 static const char *
7593 assign_canonical_path(const char *newval, bool doit, GucSource source)
7594 {
7595         if (doit)
7596         {
7597                 char       *canon_val = guc_strdup(ERROR, newval);
7598
7599                 canonicalize_path(canon_val);
7600                 return canon_val;
7601         }
7602         else
7603                 return newval;
7604 }
7605
7606 static const char *
7607 assign_timezone_abbreviations(const char *newval, bool doit, GucSource source)
7608 {
7609         /*
7610          * The powerup value shown above for timezone_abbreviations is "UNKNOWN".
7611          * When we see this we just do nothing.  If this value isn't overridden
7612          * from the config file then pg_timezone_abbrev_initialize() will
7613          * eventually replace it with "Default".  This hack has two purposes: to
7614          * avoid wasting cycles loading values that might soon be overridden from
7615          * the config file, and to avoid trying to read the timezone abbrev files
7616          * during InitializeGUCOptions().  The latter doesn't work in an
7617          * EXEC_BACKEND subprocess because my_exec_path hasn't been set yet and so
7618          * we can't locate PGSHAREDIR.  (Essentially the same hack is used to
7619          * delay initializing TimeZone ... if we have any more, we should try to
7620          * clean up and centralize this mechanism ...)
7621          */
7622         if (strcmp(newval, "UNKNOWN") == 0)
7623         {
7624                 return newval;
7625         }
7626
7627         /* Loading abbrev file is expensive, so only do it when value changes */
7628         if (timezone_abbreviations_string == NULL ||
7629                 strcmp(timezone_abbreviations_string, newval) != 0)
7630         {
7631                 int                     elevel;
7632
7633                 /*
7634                  * If reading config file, only the postmaster should bleat loudly
7635                  * about problems.      Otherwise, it's just this one process doing it,
7636                  * and we use WARNING message level.
7637                  */
7638                 if (source == PGC_S_FILE)
7639                         elevel = IsUnderPostmaster ? DEBUG3 : LOG;
7640                 else
7641                         elevel = WARNING;
7642                 if (!load_tzoffsets(newval, doit, elevel))
7643                         return NULL;
7644         }
7645         return newval;
7646 }
7647
7648 /*
7649  * pg_timezone_abbrev_initialize --- set default value if not done already
7650  *
7651  * This is called after initial loading of postgresql.conf.  If no
7652  * timezone_abbreviations setting was found therein, select default.
7653  */
7654 void
7655 pg_timezone_abbrev_initialize(void)
7656 {
7657         if (strcmp(timezone_abbreviations_string, "UNKNOWN") == 0)
7658         {
7659                 SetConfigOption("timezone_abbreviations", "Default",
7660                                                 PGC_POSTMASTER, PGC_S_ARGV);
7661         }
7662 }
7663
7664 static const char *
7665 show_archive_command(void)
7666 {
7667         if (XLogArchiveMode)
7668                 return XLogArchiveCommand;
7669         else
7670                 return "(disabled)";
7671 }
7672
7673 static bool
7674 assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
7675 {
7676         if (doit)
7677                 return (pq_setkeepalivesidle(newval, MyProcPort) == STATUS_OK);
7678
7679         return true;
7680 }
7681
7682 static const char *
7683 show_tcp_keepalives_idle(void)
7684 {
7685         static char nbuf[16];
7686
7687         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
7688         return nbuf;
7689 }
7690
7691 static bool
7692 assign_tcp_keepalives_interval(int newval, bool doit, GucSource source)
7693 {
7694         if (doit)
7695                 return (pq_setkeepalivesinterval(newval, MyProcPort) == STATUS_OK);
7696
7697         return true;
7698 }
7699
7700 static const char *
7701 show_tcp_keepalives_interval(void)
7702 {
7703         static char nbuf[16];
7704
7705         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
7706         return nbuf;
7707 }
7708
7709 static bool
7710 assign_tcp_keepalives_count(int newval, bool doit, GucSource source)
7711 {
7712         if (doit)
7713                 return (pq_setkeepalivescount(newval, MyProcPort) == STATUS_OK);
7714
7715         return true;
7716 }
7717
7718 static const char *
7719 show_tcp_keepalives_count(void)
7720 {
7721         static char nbuf[16];
7722
7723         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
7724         return nbuf;
7725 }
7726
7727 static bool
7728 assign_maxconnections(int newval, bool doit, GucSource source)
7729 {
7730         if (newval + autovacuum_max_workers + 1 > INT_MAX / 4)
7731                 return false;
7732
7733         if (doit)
7734                 MaxBackends = newval + autovacuum_max_workers + 1;
7735
7736         return true;
7737 }
7738
7739 static bool
7740 assign_autovacuum_max_workers(int newval, bool doit, GucSource source)
7741 {
7742         if (MaxConnections + newval + 1 > INT_MAX / 4)
7743                 return false;
7744
7745         if (doit)
7746                 MaxBackends = MaxConnections + newval + 1;
7747
7748         return true;
7749 }
7750
7751 static bool
7752 assign_effective_io_concurrency(int newval, bool doit, GucSource source)
7753 {
7754 #ifdef USE_PREFETCH
7755         double          new_prefetch_pages = 0.0;
7756         int                     i;
7757
7758         /*----------
7759          * The user-visible GUC parameter is the number of drives (spindles),
7760          * which we need to translate to a number-of-pages-to-prefetch target.
7761          *
7762          * The expected number of prefetch pages needed to keep N drives busy is:
7763          *
7764          * drives |   I/O requests
7765          * -------+----------------
7766          *              1 |   1
7767          *              2 |   2/1 + 2/2 = 3
7768          *              3 |   3/1 + 3/2 + 3/3 = 5 1/2
7769          *              4 |   4/1 + 4/2 + 4/3 + 4/4 = 8 1/3
7770          *              n |   n * H(n)
7771          *
7772          * This is called the "coupon collector problem" and H(n) is called the
7773          * harmonic series.  This could be approximated by n * ln(n), but for
7774          * reasonable numbers of drives we might as well just compute the series.
7775          *
7776          * Alternatively we could set the target to the number of pages necessary
7777          * so that the expected number of active spindles is some arbitrary
7778          * percentage of the total.  This sounds the same but is actually slightly
7779          * different.  The result ends up being ln(1-P)/ln((n-1)/n) where P is
7780          * that desired fraction.
7781          *
7782          * Experimental results show that both of these formulas aren't aggressive
7783          * enough, but we don't really have any better proposals.
7784          *
7785          * Note that if newval = 0 (disabled), we must set target = 0.
7786          *----------
7787          */
7788
7789         for (i = 1; i <= newval; i++)
7790                 new_prefetch_pages += (double) newval / (double) i;
7791
7792         /* This range check shouldn't fail, but let's be paranoid */
7793         if (new_prefetch_pages >= 0.0 && new_prefetch_pages < (double) INT_MAX)
7794         {
7795                 if (doit)
7796                         target_prefetch_pages = (int) rint(new_prefetch_pages);
7797                 return true;
7798         }
7799         else
7800                 return false;
7801 #else
7802         return true;
7803 #endif   /* USE_PREFETCH */
7804 }
7805
7806 static const char *
7807 assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source)
7808 {
7809         if (doit)
7810         {
7811                 char       *canon_val = guc_strdup(ERROR, newval);
7812                 char       *tname;
7813                 char       *fname;
7814
7815                 canonicalize_path(canon_val);
7816
7817                 tname = guc_malloc(ERROR, strlen(canon_val) + 12);              /* /pgstat.tmp */
7818                 sprintf(tname, "%s/pgstat.tmp", canon_val);
7819                 fname = guc_malloc(ERROR, strlen(canon_val) + 13);              /* /pgstat.stat */
7820                 sprintf(fname, "%s/pgstat.stat", canon_val);
7821
7822                 if (pgstat_stat_tmpname)
7823                         free(pgstat_stat_tmpname);
7824                 pgstat_stat_tmpname = tname;
7825                 if (pgstat_stat_filename)
7826                         free(pgstat_stat_filename);
7827                 pgstat_stat_filename = fname;
7828
7829                 return canon_val;
7830         }
7831         else
7832                 return newval;
7833 }
7834
7835 static const char *
7836 assign_application_name(const char *newval, bool doit, GucSource source)
7837 {
7838         if (doit)
7839         {
7840                 /* Only allow clean ASCII chars in the application name */
7841                 char       *repval = guc_strdup(ERROR, newval);
7842                 char       *p;
7843
7844                 for (p = repval; *p; p++)
7845                 {
7846                         if (*p < 32 || *p > 126)
7847                                 *p = '?';
7848                 }
7849
7850                 /* Update the pg_stat_activity view */
7851                 pgstat_report_appname(repval);
7852
7853                 return repval;
7854         }
7855         else
7856                 return newval;
7857 }
7858
7859 #include "guc-file.c"