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