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