]> granicus.if.org Git - postgresql/blob - src/backend/utils/misc/guc.c
Split apart message_level_options into one set for server-side settings and
[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.459 2008/07/01 06:08:31 mha 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, false},
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, false},
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         {"default", PGERROR_DEFAULT, false},
216         {"terse", PGERROR_TERSE, 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 an 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                         gettext_noop("Valid values are ON, OFF, and SAFE_ENCODING.")
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                         gettext_noop("Each SQL transaction has an isolation level, which "
2485                                                  "can be either \"read uncommitted\", \"read committed\", \"repeatable read\", or \"serializable\".")
2486                 },
2487                 &DefaultXactIsoLevel,
2488                 XACT_READ_COMMITTED, isolation_level_options, NULL, NULL
2489         },
2490
2491         {
2492                 {"log_error_verbosity", PGC_SUSET, LOGGING_WHEN,
2493                         gettext_noop("Sets the verbosity of logged messages."),
2494                         gettext_noop("Valid values are \"terse\", \"default\", and \"verbose\".")
2495                 },
2496                 &Log_error_verbosity,
2497                 PGERROR_DEFAULT, log_error_verbosity_options, NULL, NULL
2498         },
2499
2500         {
2501                 {"log_min_messages", PGC_SUSET, LOGGING_WHEN,
2502                         gettext_noop("Sets the message levels that are logged."),
2503                         gettext_noop("Each level includes all levels that follow it.")
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("All SQL statements that cause an error of the "
2513                                                  "specified level or a higher level are logged.")
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                         gettext_noop("Valid values are \"none\", \"ddl\", \"mod\", and \"all\".")
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                         gettext_noop("Valid values are LOCAL0, LOCAL1, LOCAL2, LOCAL3, "
2533                                                  "LOCAL4, LOCAL5, LOCAL6, LOCAL7.")
2534                 },
2535                 &syslog_facility,
2536                 LOG_LOCAL0, syslog_facility_options, assign_syslog_facility, NULL
2537         },
2538 #endif
2539
2540         {
2541                 {"regex_flavor", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
2542                         gettext_noop("Sets the regular expression \"flavor\"."),
2543                         gettext_noop("This can be set to advanced, extended, or basic.")
2544                 },
2545                 &regex_flavor,
2546                 REG_ADVANCED, regex_flavor_options, NULL, NULL
2547         },
2548
2549         {
2550                 {"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
2551                         gettext_noop("Sets the session's behavior for triggers and rewrite rules."),
2552                         gettext_noop("Each session can be either"
2553                                                  " \"origin\", \"replica\", or \"local\".")
2554                 },
2555                 &SessionReplicationRole,
2556                 SESSION_REPLICATION_ROLE_ORIGIN, session_replication_role_options,
2557                 assign_session_replication_role, NULL
2558         },
2559
2560         {
2561                 {"track_functions", PGC_SUSET, STATS_COLLECTOR,
2562                         gettext_noop("Collects function-level statistics on database activity."),
2563                         gettext_noop("Valid values are: NONE, PL, and ALL.")
2564                 },
2565                 &pgstat_track_functions,
2566                 TRACK_FUNC_OFF, track_function_options, NULL, NULL
2567         },
2568
2569         {
2570                 {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
2571                         gettext_noop("Selects the method used for forcing WAL updates to disk."),
2572                         NULL
2573                 },
2574                 &sync_method,
2575                 DEFAULT_SYNC_METHOD, sync_method_options, 
2576                 assign_xlog_sync_method, NULL
2577         },
2578
2579         {
2580                 {"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
2581                         gettext_noop("Sets how binary values are to be encoded in XML."),
2582                         gettext_noop("Valid values are BASE64 and HEX.")
2583                 },
2584                 &xmlbinary,
2585                 XMLBINARY_BASE64, xmlbinary_options, NULL, NULL
2586         },
2587
2588         {
2589                 {"xmloption", PGC_USERSET, CLIENT_CONN_STATEMENT,
2590                         gettext_noop("Sets whether XML data in implicit parsing and serialization "
2591                                                  "operations is to be considered as documents or content fragments."),
2592                         gettext_noop("Valid values are DOCUMENT and CONTENT.")
2593                 },
2594                 &xmloption,
2595                 XMLOPTION_CONTENT, xmloption_options, NULL, NULL
2596         },
2597
2598
2599         /* End-of-list marker */
2600         {
2601                 {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL
2602         }
2603 };
2604
2605 /******** end of options list ********/
2606
2607
2608 /*
2609  * To allow continued support of obsolete names for GUC variables, we apply
2610  * the following mappings to any unrecognized name.  Note that an old name
2611  * should be mapped to a new one only if the new variable has very similar
2612  * semantics to the old.
2613  */
2614 static const char *const map_old_guc_names[] = {
2615         "sort_mem", "work_mem",
2616         "vacuum_mem", "maintenance_work_mem",
2617         NULL
2618 };
2619
2620
2621 /*
2622  * Actual lookup of variables is done through this single, sorted array.
2623  */
2624 static struct config_generic **guc_variables;
2625
2626 /* Current number of variables contained in the vector */
2627 static int      num_guc_variables;
2628
2629 /* Vector capacity */
2630 static int      size_guc_variables;
2631
2632
2633 static bool guc_dirty;                  /* TRUE if need to do commit/abort work */
2634
2635 static bool reporting_enabled;  /* TRUE to enable GUC_REPORT */
2636
2637 static int      GUCNestLevel = 0;       /* 1 when in main transaction */
2638
2639
2640 static int      guc_var_compare(const void *a, const void *b);
2641 static int      guc_name_compare(const char *namea, const char *nameb);
2642 static void push_old_value(struct config_generic * gconf, GucAction action);
2643 static void ReportGUCOption(struct config_generic * record);
2644 static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
2645 static void ShowAllGUCConfig(DestReceiver *dest);
2646 static char *_ShowOption(struct config_generic * record, bool use_units);
2647 static bool is_newvalue_equal(struct config_generic * record, const char *newvalue);
2648
2649
2650 /*
2651  * Some infrastructure for checking malloc/strdup/realloc calls
2652  */
2653 static void *
2654 guc_malloc(int elevel, size_t size)
2655 {
2656         void       *data;
2657
2658         data = malloc(size);
2659         if (data == NULL)
2660                 ereport(elevel,
2661                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2662                                  errmsg("out of memory")));
2663         return data;
2664 }
2665
2666 static void *
2667 guc_realloc(int elevel, void *old, size_t size)
2668 {
2669         void       *data;
2670
2671         data = realloc(old, size);
2672         if (data == NULL)
2673                 ereport(elevel,
2674                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2675                                  errmsg("out of memory")));
2676         return data;
2677 }
2678
2679 static char *
2680 guc_strdup(int elevel, const char *src)
2681 {
2682         char       *data;
2683
2684         data = strdup(src);
2685         if (data == NULL)
2686                 ereport(elevel,
2687                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2688                                  errmsg("out of memory")));
2689         return data;
2690 }
2691
2692
2693 /*
2694  * Support for assigning to a field of a string GUC item.  Free the prior
2695  * value if it's not referenced anywhere else in the item (including stacked
2696  * states).
2697  */
2698 static void
2699 set_string_field(struct config_string * conf, char **field, char *newval)
2700 {
2701         char       *oldval = *field;
2702         GucStack   *stack;
2703
2704         /* Do the assignment */
2705         *field = newval;
2706
2707         /* Exit if any duplicate references, or if old value was NULL anyway */
2708         if (oldval == NULL ||
2709                 oldval == *(conf->variable) ||
2710                 oldval == conf->reset_val ||
2711                 oldval == conf->boot_val)
2712                 return;
2713         for (stack = conf->gen.stack; stack; stack = stack->prev)
2714         {
2715                 if (oldval == stack->prior.stringval ||
2716                         oldval == stack->masked.stringval)
2717                         return;
2718         }
2719
2720         /* Not used anymore, so free it */
2721         free(oldval);
2722 }
2723
2724 /*
2725  * Detect whether strval is referenced anywhere in a GUC string item
2726  */
2727 static bool
2728 string_field_used(struct config_string * conf, char *strval)
2729 {
2730         GucStack   *stack;
2731
2732         if (strval == *(conf->variable) ||
2733                 strval == conf->reset_val ||
2734                 strval == conf->boot_val)
2735                 return true;
2736         for (stack = conf->gen.stack; stack; stack = stack->prev)
2737         {
2738                 if (strval == stack->prior.stringval ||
2739                         strval == stack->masked.stringval)
2740                         return true;
2741         }
2742         return false;
2743 }
2744
2745 /*
2746  * Support for copying a variable's active value into a stack entry
2747  */
2748 static void
2749 set_stack_value(struct config_generic * gconf, union config_var_value * val)
2750 {
2751         switch (gconf->vartype)
2752         {
2753                 case PGC_BOOL:
2754                         val->boolval =
2755                                 *((struct config_bool *) gconf)->variable;
2756                         break;
2757                 case PGC_INT:
2758                         val->intval =
2759                                 *((struct config_int *) gconf)->variable;
2760                         break;
2761                 case PGC_REAL:
2762                         val->realval =
2763                                 *((struct config_real *) gconf)->variable;
2764                         break;
2765                 case PGC_STRING:
2766                         /* we assume stringval is NULL if not valid */
2767                         set_string_field((struct config_string *) gconf,
2768                                                          &(val->stringval),
2769                                                          *((struct config_string *) gconf)->variable);
2770                         break;
2771                 case PGC_ENUM:
2772                         val->enumval = 
2773                                 *((struct config_enum *) gconf)->variable;
2774                         break;
2775         }
2776 }
2777
2778 /*
2779  * Support for discarding a no-longer-needed value in a stack entry
2780  */
2781 static void
2782 discard_stack_value(struct config_generic * gconf, union config_var_value * val)
2783 {
2784         switch (gconf->vartype)
2785         {
2786                 case PGC_BOOL:
2787                 case PGC_INT:
2788                 case PGC_REAL:
2789                 case PGC_ENUM:
2790                         /* no need to do anything */
2791                         break;
2792                 case PGC_STRING:
2793                         set_string_field((struct config_string *) gconf,
2794                                                          &(val->stringval),
2795                                                          NULL);
2796                         break;
2797         }
2798 }
2799
2800
2801 /*
2802  * Fetch the sorted array pointer (exported for help_config.c's use ONLY)
2803  */
2804 struct config_generic **
2805 get_guc_variables(void)
2806 {
2807         return guc_variables;
2808 }
2809
2810
2811 /*
2812  * Build the sorted array.      This is split out so that it could be
2813  * re-executed after startup (eg, we could allow loadable modules to
2814  * add vars, and then we'd need to re-sort).
2815  */
2816 void
2817 build_guc_variables(void)
2818 {
2819         int                     size_vars;
2820         int                     num_vars = 0;
2821         struct config_generic **guc_vars;
2822         int                     i;
2823
2824         for (i = 0; ConfigureNamesBool[i].gen.name; i++)
2825         {
2826                 struct config_bool *conf = &ConfigureNamesBool[i];
2827
2828                 /* Rather than requiring vartype to be filled in by hand, do this: */
2829                 conf->gen.vartype = PGC_BOOL;
2830                 num_vars++;
2831         }
2832
2833         for (i = 0; ConfigureNamesInt[i].gen.name; i++)
2834         {
2835                 struct config_int *conf = &ConfigureNamesInt[i];
2836
2837                 conf->gen.vartype = PGC_INT;
2838                 num_vars++;
2839         }
2840
2841         for (i = 0; ConfigureNamesReal[i].gen.name; i++)
2842         {
2843                 struct config_real *conf = &ConfigureNamesReal[i];
2844
2845                 conf->gen.vartype = PGC_REAL;
2846                 num_vars++;
2847         }
2848
2849         for (i = 0; ConfigureNamesString[i].gen.name; i++)
2850         {
2851                 struct config_string *conf = &ConfigureNamesString[i];
2852
2853                 conf->gen.vartype = PGC_STRING;
2854                 num_vars++;
2855         }
2856
2857         for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
2858         {
2859                 struct config_enum *conf = &ConfigureNamesEnum[i];
2860
2861                 conf->gen.vartype = PGC_ENUM;
2862                 num_vars++;
2863         }
2864
2865         /*
2866          * Create table with 20% slack
2867          */
2868         size_vars = num_vars + num_vars / 4;
2869
2870         guc_vars = (struct config_generic **)
2871                 guc_malloc(FATAL, size_vars * sizeof(struct config_generic *));
2872
2873         num_vars = 0;
2874
2875         for (i = 0; ConfigureNamesBool[i].gen.name; i++)
2876                 guc_vars[num_vars++] = &ConfigureNamesBool[i].gen;
2877
2878         for (i = 0; ConfigureNamesInt[i].gen.name; i++)
2879                 guc_vars[num_vars++] = &ConfigureNamesInt[i].gen;
2880
2881         for (i = 0; ConfigureNamesReal[i].gen.name; i++)
2882                 guc_vars[num_vars++] = &ConfigureNamesReal[i].gen;
2883
2884         for (i = 0; ConfigureNamesString[i].gen.name; i++)
2885                 guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
2886
2887         for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
2888                 guc_vars[num_vars++] = &ConfigureNamesEnum[i].gen;
2889
2890         if (guc_variables)
2891                 free(guc_variables);
2892         guc_variables = guc_vars;
2893         num_guc_variables = num_vars;
2894         size_guc_variables = size_vars;
2895         qsort((void *) guc_variables, num_guc_variables,
2896                   sizeof(struct config_generic *), guc_var_compare);
2897 }
2898
2899 /*
2900  * Add a new GUC variable to the list of known variables. The
2901  * list is expanded if needed.
2902  */
2903 static bool
2904 add_guc_variable(struct config_generic * var, int elevel)
2905 {
2906         if (num_guc_variables + 1 >= size_guc_variables)
2907         {
2908                 /*
2909                  * Increase the vector by 25%
2910                  */
2911                 int                     size_vars = size_guc_variables + size_guc_variables / 4;
2912                 struct config_generic **guc_vars;
2913
2914                 if (size_vars == 0)
2915                 {
2916                         size_vars = 100;
2917                         guc_vars = (struct config_generic **)
2918                                 guc_malloc(elevel, size_vars * sizeof(struct config_generic *));
2919                 }
2920                 else
2921                 {
2922                         guc_vars = (struct config_generic **)
2923                                 guc_realloc(elevel, guc_variables, size_vars * sizeof(struct config_generic *));
2924                 }
2925
2926                 if (guc_vars == NULL)
2927                         return false;           /* out of memory */
2928
2929                 guc_variables = guc_vars;
2930                 size_guc_variables = size_vars;
2931         }
2932         guc_variables[num_guc_variables++] = var;
2933         qsort((void *) guc_variables, num_guc_variables,
2934                   sizeof(struct config_generic *), guc_var_compare);
2935         return true;
2936 }
2937
2938 /*
2939  * Create and add a placeholder variable. It's presumed to belong
2940  * to a valid custom variable class at this point.
2941  */
2942 static struct config_generic *
2943 add_placeholder_variable(const char *name, int elevel)
2944 {
2945         size_t          sz = sizeof(struct config_string) + sizeof(char *);
2946         struct config_string *var;
2947         struct config_generic *gen;
2948
2949         var = (struct config_string *) guc_malloc(elevel, sz);
2950         if (var == NULL)
2951                 return NULL;
2952         memset(var, 0, sz);
2953         gen = &var->gen;
2954
2955         gen->name = guc_strdup(elevel, name);
2956         if (gen->name == NULL)
2957         {
2958                 free(var);
2959                 return NULL;
2960         }
2961
2962         gen->context = PGC_USERSET;
2963         gen->group = CUSTOM_OPTIONS;
2964         gen->short_desc = "GUC placeholder variable";
2965         gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER;
2966         gen->vartype = PGC_STRING;
2967
2968         /*
2969          * The char* is allocated at the end of the struct since we have no
2970          * 'static' place to point to.  Note that the current value, as well as
2971          * the boot and reset values, start out NULL.
2972          */
2973         var->variable = (char **) (var + 1);
2974
2975         if (!add_guc_variable((struct config_generic *) var, elevel))
2976         {
2977                 free((void *) gen->name);
2978                 free(var);
2979                 return NULL;
2980         }
2981
2982         return gen;
2983 }
2984
2985 /*
2986  * Detect whether the portion of "name" before dotPos matches any custom
2987  * variable class name listed in custom_var_classes.  The latter must be
2988  * formatted the way that assign_custom_variable_classes does it, ie,
2989  * no whitespace.  NULL is valid for custom_var_classes.
2990  */
2991 static bool
2992 is_custom_class(const char *name, int dotPos, const char *custom_var_classes)
2993 {
2994         bool            result = false;
2995         const char *ccs = custom_var_classes;
2996
2997         if (ccs != NULL)
2998         {
2999                 const char *start = ccs;
3000
3001                 for (;; ++ccs)
3002                 {
3003                         char            c = *ccs;
3004
3005                         if (c == '\0' || c == ',')
3006                         {
3007                                 if (dotPos == ccs - start && strncmp(start, name, dotPos) == 0)
3008                                 {
3009                                         result = true;
3010                                         break;
3011                                 }
3012                                 if (c == '\0')
3013                                         break;
3014                                 start = ccs + 1;
3015                         }
3016                 }
3017         }
3018         return result;
3019 }
3020
3021 /*
3022  * Look up option NAME.  If it exists, return a pointer to its record,
3023  * else return NULL.  If create_placeholders is TRUE, we'll create a
3024  * placeholder record for a valid-looking custom variable name.
3025  */
3026 static struct config_generic *
3027 find_option(const char *name, bool create_placeholders, int elevel)
3028 {
3029         const char **key = &name;
3030         struct config_generic **res;
3031         int                     i;
3032
3033         Assert(name);
3034
3035         /*
3036          * By equating const char ** with struct config_generic *, we are assuming
3037          * the name field is first in config_generic.
3038          */
3039         res = (struct config_generic **) bsearch((void *) &key,
3040                                                                                          (void *) guc_variables,
3041                                                                                          num_guc_variables,
3042                                                                                          sizeof(struct config_generic *),
3043                                                                                          guc_var_compare);
3044         if (res)
3045                 return *res;
3046
3047         /*
3048          * See if the name is an obsolete name for a variable.  We assume that the
3049          * set of supported old names is short enough that a brute-force search is
3050          * the best way.
3051          */
3052         for (i = 0; map_old_guc_names[i] != NULL; i += 2)
3053         {
3054                 if (guc_name_compare(name, map_old_guc_names[i]) == 0)
3055                         return find_option(map_old_guc_names[i + 1], false, elevel);
3056         }
3057
3058         if (create_placeholders)
3059         {
3060                 /*
3061                  * Check if the name is qualified, and if so, check if the qualifier
3062                  * matches any custom variable class.  If so, add a placeholder.
3063                  */
3064                 const char *dot = strchr(name, GUC_QUALIFIER_SEPARATOR);
3065
3066                 if (dot != NULL &&
3067                         is_custom_class(name, dot - name, custom_variable_classes))
3068                         return add_placeholder_variable(name, elevel);
3069         }
3070
3071         /* Unknown name */
3072         return NULL;
3073 }
3074
3075
3076 /*
3077  * comparator for qsorting and bsearching guc_variables array
3078  */
3079 static int
3080 guc_var_compare(const void *a, const void *b)
3081 {
3082         struct config_generic *confa = *(struct config_generic **) a;
3083         struct config_generic *confb = *(struct config_generic **) b;
3084
3085         return guc_name_compare(confa->name, confb->name);
3086 }
3087
3088 /*
3089  * the bare comparison function for GUC names
3090  */
3091 static int
3092 guc_name_compare(const char *namea, const char *nameb)
3093 {
3094         /*
3095          * The temptation to use strcasecmp() here must be resisted, because the
3096          * array ordering has to remain stable across setlocale() calls. So, build
3097          * our own with a simple ASCII-only downcasing.
3098          */
3099         while (*namea && *nameb)
3100         {
3101                 char            cha = *namea++;
3102                 char            chb = *nameb++;
3103
3104                 if (cha >= 'A' && cha <= 'Z')
3105                         cha += 'a' - 'A';
3106                 if (chb >= 'A' && chb <= 'Z')
3107                         chb += 'a' - 'A';
3108                 if (cha != chb)
3109                         return cha - chb;
3110         }
3111         if (*namea)
3112                 return 1;                               /* a is longer */
3113         if (*nameb)
3114                 return -1;                              /* b is longer */
3115         return 0;
3116 }
3117
3118
3119 /*
3120  * Initialize GUC options during program startup.
3121  *
3122  * Note that we cannot read the config file yet, since we have not yet
3123  * processed command-line switches.
3124  */
3125 void
3126 InitializeGUCOptions(void)
3127 {
3128         int                     i;
3129         char       *env;
3130         long            stack_rlimit;
3131
3132         /*
3133          * Before log_line_prefix could possibly receive a nonempty setting, make
3134          * sure that timezone processing is minimally alive (see elog.c).
3135          */
3136         pg_timezone_pre_initialize();
3137
3138         /*
3139          * Build sorted array of all GUC variables.
3140          */
3141         build_guc_variables();
3142
3143         /*
3144          * Load all variables with their compiled-in defaults, and initialize
3145          * status fields as needed.
3146          */
3147         for (i = 0; i < num_guc_variables; i++)
3148         {
3149                 struct config_generic *gconf = guc_variables[i];
3150
3151                 gconf->status = 0;
3152                 gconf->reset_source = PGC_S_DEFAULT;
3153                 gconf->source = PGC_S_DEFAULT;
3154                 gconf->stack = NULL;
3155
3156                 switch (gconf->vartype)
3157                 {
3158                         case PGC_BOOL:
3159                                 {
3160                                         struct config_bool *conf = (struct config_bool *) gconf;
3161
3162                                         if (conf->assign_hook)
3163                                                 if (!(*conf->assign_hook) (conf->boot_val, true,
3164                                                                                                    PGC_S_DEFAULT))
3165                                                         elog(FATAL, "failed to initialize %s to %d",
3166                                                                  conf->gen.name, (int) conf->boot_val);
3167                                         *conf->variable = conf->reset_val = conf->boot_val;
3168                                         break;
3169                                 }
3170                         case PGC_INT:
3171                                 {
3172                                         struct config_int *conf = (struct config_int *) gconf;
3173
3174                                         Assert(conf->boot_val >= conf->min);
3175                                         Assert(conf->boot_val <= conf->max);
3176                                         if (conf->assign_hook)
3177                                                 if (!(*conf->assign_hook) (conf->boot_val, true,
3178                                                                                                    PGC_S_DEFAULT))
3179                                                         elog(FATAL, "failed to initialize %s to %d",
3180                                                                  conf->gen.name, conf->boot_val);
3181                                         *conf->variable = conf->reset_val = conf->boot_val;
3182                                         break;
3183                                 }
3184                         case PGC_REAL:
3185                                 {
3186                                         struct config_real *conf = (struct config_real *) gconf;
3187
3188                                         Assert(conf->boot_val >= conf->min);
3189                                         Assert(conf->boot_val <= conf->max);
3190                                         if (conf->assign_hook)
3191                                                 if (!(*conf->assign_hook) (conf->boot_val, true,
3192                                                                                                    PGC_S_DEFAULT))
3193                                                         elog(FATAL, "failed to initialize %s to %g",
3194                                                                  conf->gen.name, conf->boot_val);
3195                                         *conf->variable = conf->reset_val = conf->boot_val;
3196                                         break;
3197                                 }
3198                         case PGC_STRING:
3199                                 {
3200                                         struct config_string *conf = (struct config_string *) gconf;
3201                                         char       *str;
3202
3203                                         *conf->variable = NULL;
3204                                         conf->reset_val = NULL;
3205
3206                                         if (conf->boot_val == NULL)
3207                                         {
3208                                                 /* leave the value NULL, do not call assign hook */
3209                                                 break;
3210                                         }
3211
3212                                         str = guc_strdup(FATAL, conf->boot_val);
3213                                         conf->reset_val = str;
3214
3215                                         if (conf->assign_hook)
3216                                         {
3217                                                 const char *newstr;
3218
3219                                                 newstr = (*conf->assign_hook) (str, true,
3220                                                                                                            PGC_S_DEFAULT);
3221                                                 if (newstr == NULL)
3222                                                 {
3223                                                         elog(FATAL, "failed to initialize %s to \"%s\"",
3224                                                                  conf->gen.name, str);
3225                                                 }
3226                                                 else if (newstr != str)
3227                                                 {
3228                                                         free(str);
3229
3230                                                         /*
3231                                                          * See notes in set_config_option about casting
3232                                                          */
3233                                                         str = (char *) newstr;
3234                                                         conf->reset_val = str;
3235                                                 }
3236                                         }
3237                                         *conf->variable = str;
3238                                         break;
3239                                 }
3240                         case PGC_ENUM:
3241                                 {
3242                                         struct config_enum *conf = (struct config_enum *) gconf;
3243
3244                                         if (conf->assign_hook)
3245                                                 if (!(*conf->assign_hook) (conf->boot_val, true,
3246                                                                                                    PGC_S_DEFAULT))
3247                                                         elog(FATAL, "failed to initialize %s to %s",
3248                                                                  conf->gen.name, 
3249                                                                  config_enum_lookup_by_value(conf, conf->boot_val));
3250                                         *conf->variable = conf->reset_val = conf->boot_val;
3251                                         break;
3252                                 }
3253                 }
3254         }
3255
3256         guc_dirty = false;
3257
3258         reporting_enabled = false;
3259
3260         /*
3261          * Prevent any attempt to override the transaction modes from
3262          * non-interactive sources.
3263          */
3264         SetConfigOption("transaction_isolation", "default",
3265                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
3266         SetConfigOption("transaction_read_only", "no",
3267                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
3268
3269         /*
3270          * For historical reasons, some GUC parameters can receive defaults from
3271          * environment variables.  Process those settings.      NB: if you add or
3272          * remove anything here, see also ProcessConfigFile().
3273          */
3274
3275         env = getenv("PGPORT");
3276         if (env != NULL)
3277                 SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
3278
3279         env = getenv("PGDATESTYLE");
3280         if (env != NULL)
3281                 SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
3282
3283         env = getenv("PGCLIENTENCODING");
3284         if (env != NULL)
3285                 SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
3286
3287         /*
3288          * rlimit isn't exactly an "environment variable", but it behaves about
3289          * the same.  If we can identify the platform stack depth rlimit, increase
3290          * default stack depth setting up to whatever is safe (but at most 2MB).
3291          */
3292         stack_rlimit = get_stack_depth_rlimit();
3293         if (stack_rlimit > 0)
3294         {
3295                 int                     new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;
3296
3297                 if (new_limit > 100)
3298                 {
3299                         char            limbuf[16];
3300
3301                         new_limit = Min(new_limit, 2048);
3302                         sprintf(limbuf, "%d", new_limit);
3303                         SetConfigOption("max_stack_depth", limbuf,
3304                                                         PGC_POSTMASTER, PGC_S_ENV_VAR);
3305                 }
3306         }
3307 }
3308
3309
3310 /*
3311  * Select the configuration files and data directory to be used, and
3312  * do the initial read of postgresql.conf.
3313  *
3314  * This is called after processing command-line switches.
3315  *              userDoption is the -D switch value if any (NULL if unspecified).
3316  *              progname is just for use in error messages.
3317  *
3318  * Returns true on success; on failure, prints a suitable error message
3319  * to stderr and returns false.
3320  */
3321 bool
3322 SelectConfigFiles(const char *userDoption, const char *progname)
3323 {
3324         char       *configdir;
3325         char       *fname;
3326         struct stat stat_buf;
3327
3328         /* configdir is -D option, or $PGDATA if no -D */
3329         if (userDoption)
3330                 configdir = make_absolute_path(userDoption);
3331         else
3332                 configdir = make_absolute_path(getenv("PGDATA"));
3333
3334         /*
3335          * Find the configuration file: if config_file was specified on the
3336          * command line, use it, else use configdir/postgresql.conf.  In any case
3337          * ensure the result is an absolute path, so that it will be interpreted
3338          * the same way by future backends.
3339          */
3340         if (ConfigFileName)
3341                 fname = make_absolute_path(ConfigFileName);
3342         else if (configdir)
3343         {
3344                 fname = guc_malloc(FATAL,
3345                                                    strlen(configdir) + strlen(CONFIG_FILENAME) + 2);
3346                 sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);
3347         }
3348         else
3349         {
3350                 write_stderr("%s does not know where to find the server configuration file.\n"
3351                                          "You must specify the --config-file or -D invocation "
3352                                          "option or set the PGDATA environment variable.\n",
3353                                          progname);
3354                 return false;
3355         }
3356
3357         /*
3358          * Set the ConfigFileName GUC variable to its final value, ensuring that
3359          * it can't be overridden later.
3360          */
3361         SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
3362         free(fname);
3363
3364         /*
3365          * Now read the config file for the first time.
3366          */
3367         if (stat(ConfigFileName, &stat_buf) != 0)
3368         {
3369                 write_stderr("%s cannot access the server configuration file \"%s\": %s\n",
3370                                          progname, ConfigFileName, strerror(errno));
3371                 return false;
3372         }
3373
3374         ProcessConfigFile(PGC_POSTMASTER);
3375
3376         /*
3377          * If the data_directory GUC variable has been set, use that as DataDir;
3378          * otherwise use configdir if set; else punt.
3379          *
3380          * Note: SetDataDir will copy and absolute-ize its argument, so we don't
3381          * have to.
3382          */
3383         if (data_directory)
3384                 SetDataDir(data_directory);
3385         else if (configdir)
3386                 SetDataDir(configdir);
3387         else
3388         {
3389                 write_stderr("%s does not know where to find the database system data.\n"
3390                                          "This can be specified as \"data_directory\" in \"%s\", "
3391                                          "or by the -D invocation option, or by the "
3392                                          "PGDATA environment variable.\n",
3393                                          progname, ConfigFileName);
3394                 return false;
3395         }
3396
3397         /*
3398          * Reflect the final DataDir value back into the data_directory GUC var.
3399          * (If you are wondering why we don't just make them a single variable,
3400          * it's because the EXEC_BACKEND case needs DataDir to be transmitted to
3401          * child backends specially.  XXX is that still true?  Given that we now
3402          * chdir to DataDir, EXEC_BACKEND can read the config file without knowing
3403          * DataDir in advance.)
3404          */
3405         SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
3406
3407         /*
3408          * Figure out where pg_hba.conf is, and make sure the path is absolute.
3409          */
3410         if (HbaFileName)
3411                 fname = make_absolute_path(HbaFileName);
3412         else if (configdir)
3413         {
3414                 fname = guc_malloc(FATAL,
3415                                                    strlen(configdir) + strlen(HBA_FILENAME) + 2);
3416                 sprintf(fname, "%s/%s", configdir, HBA_FILENAME);
3417         }
3418         else
3419         {
3420                 write_stderr("%s does not know where to find the \"hba\" configuration file.\n"
3421                                          "This can be specified as \"hba_file\" in \"%s\", "
3422                                          "or by the -D invocation option, or by the "
3423                                          "PGDATA environment variable.\n",
3424                                          progname, ConfigFileName);
3425                 return false;
3426         }
3427         SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
3428         free(fname);
3429
3430         /*
3431          * Likewise for pg_ident.conf.
3432          */
3433         if (IdentFileName)
3434                 fname = make_absolute_path(IdentFileName);
3435         else if (configdir)
3436         {
3437                 fname = guc_malloc(FATAL,
3438                                                    strlen(configdir) + strlen(IDENT_FILENAME) + 2);
3439                 sprintf(fname, "%s/%s", configdir, IDENT_FILENAME);
3440         }
3441         else
3442         {
3443                 write_stderr("%s does not know where to find the \"ident\" configuration file.\n"
3444                                          "This can be specified as \"ident_file\" in \"%s\", "
3445                                          "or by the -D invocation option, or by the "
3446                                          "PGDATA environment variable.\n",
3447                                          progname, ConfigFileName);
3448                 return false;
3449         }
3450         SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
3451         free(fname);
3452
3453         free(configdir);
3454
3455         return true;
3456 }
3457
3458
3459 /*
3460  * Reset all options to their saved default values (implements RESET ALL)
3461  */
3462 void
3463 ResetAllOptions(void)
3464 {
3465         int                     i;
3466
3467         for (i = 0; i < num_guc_variables; i++)
3468         {
3469                 struct config_generic *gconf = guc_variables[i];
3470
3471                 /* Don't reset non-SET-able values */
3472                 if (gconf->context != PGC_SUSET &&
3473                         gconf->context != PGC_USERSET)
3474                         continue;
3475                 /* Don't reset if special exclusion from RESET ALL */
3476                 if (gconf->flags & GUC_NO_RESET_ALL)
3477                         continue;
3478                 /* No need to reset if wasn't SET */
3479                 if (gconf->source <= PGC_S_OVERRIDE)
3480                         continue;
3481
3482                 /* Save old value to support transaction abort */
3483                 push_old_value(gconf, GUC_ACTION_SET);
3484
3485                 switch (gconf->vartype)
3486                 {
3487                         case PGC_BOOL:
3488                                 {
3489                                         struct config_bool *conf = (struct config_bool *) gconf;
3490
3491                                         if (conf->assign_hook)
3492                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
3493                                                                                                    PGC_S_SESSION))
3494                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
3495                                         *conf->variable = conf->reset_val;
3496                                         conf->gen.source = conf->gen.reset_source;
3497                                         break;
3498                                 }
3499                         case PGC_INT:
3500                                 {
3501                                         struct config_int *conf = (struct config_int *) gconf;
3502
3503                                         if (conf->assign_hook)
3504                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
3505                                                                                                    PGC_S_SESSION))
3506                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
3507                                         *conf->variable = conf->reset_val;
3508                                         conf->gen.source = conf->gen.reset_source;
3509                                         break;
3510                                 }
3511                         case PGC_REAL:
3512                                 {
3513                                         struct config_real *conf = (struct config_real *) gconf;
3514
3515                                         if (conf->assign_hook)
3516                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
3517                                                                                                    PGC_S_SESSION))
3518                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
3519                                         *conf->variable = conf->reset_val;
3520                                         conf->gen.source = conf->gen.reset_source;
3521                                         break;
3522                                 }
3523                         case PGC_STRING:
3524                                 {
3525                                         struct config_string *conf = (struct config_string *) gconf;
3526                                         char       *str;
3527
3528                                         /* We need not strdup here */
3529                                         str = conf->reset_val;
3530
3531                                         if (conf->assign_hook && str)
3532                                         {
3533                                                 const char *newstr;
3534
3535                                                 newstr = (*conf->assign_hook) (str, true,
3536                                                                                                            PGC_S_SESSION);
3537                                                 if (newstr == NULL)
3538                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
3539                                                 else if (newstr != str)
3540                                                 {
3541                                                         /*
3542                                                          * See notes in set_config_option about casting
3543                                                          */
3544                                                         str = (char *) newstr;
3545                                                 }
3546                                         }
3547
3548                                         set_string_field(conf, conf->variable, str);
3549                                         conf->gen.source = conf->gen.reset_source;
3550                                         break;
3551                                 }
3552                         case PGC_ENUM:
3553                                 {
3554                                         struct config_enum *conf = (struct config_enum *) gconf;
3555
3556                                         if (conf->assign_hook)
3557                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
3558                                                                                                    PGC_S_SESSION))
3559                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
3560                                         *conf->variable = conf->reset_val;
3561                                         conf->gen.source = conf->gen.reset_source;
3562                                         break;
3563                                 }
3564                 }
3565
3566                 if (gconf->flags & GUC_REPORT)
3567                         ReportGUCOption(gconf);
3568         }
3569 }
3570
3571
3572 /*
3573  * push_old_value
3574  *              Push previous state during transactional assignment to a GUC variable.
3575  */
3576 static void
3577 push_old_value(struct config_generic * gconf, GucAction action)
3578 {
3579         GucStack   *stack;
3580
3581         /* If we're not inside a nest level, do nothing */
3582         if (GUCNestLevel == 0)
3583                 return;
3584
3585         /* Do we already have a stack entry of the current nest level? */
3586         stack = gconf->stack;
3587         if (stack && stack->nest_level >= GUCNestLevel)
3588         {
3589                 /* Yes, so adjust its state if necessary */
3590                 Assert(stack->nest_level == GUCNestLevel);
3591                 switch (action)
3592                 {
3593                         case GUC_ACTION_SET:
3594                                 /* SET overrides any prior action at same nest level */
3595                                 if (stack->state == GUC_SET_LOCAL)
3596                                 {
3597                                         /* must discard old masked value */
3598                                         discard_stack_value(gconf, &stack->masked);
3599                                 }
3600                                 stack->state = GUC_SET;
3601                                 break;
3602                         case GUC_ACTION_LOCAL:
3603                                 if (stack->state == GUC_SET)
3604                                 {
3605                                         /* SET followed by SET LOCAL, remember SET's value */
3606                                         set_stack_value(gconf, &stack->masked);
3607                                         stack->state = GUC_SET_LOCAL;
3608                                 }
3609                                 /* in all other cases, no change to stack entry */
3610                                 break;
3611                         case GUC_ACTION_SAVE:
3612                                 /* Could only have a prior SAVE of same variable */
3613                                 Assert(stack->state == GUC_SAVE);
3614                                 break;
3615                 }
3616                 Assert(guc_dirty);              /* must be set already */
3617                 return;
3618         }
3619
3620         /*
3621          * Push a new stack entry
3622          *
3623          * We keep all the stack entries in TopTransactionContext for simplicity.
3624          */
3625         stack = (GucStack *) MemoryContextAllocZero(TopTransactionContext,
3626                                                                                                 sizeof(GucStack));
3627
3628         stack->prev = gconf->stack;
3629         stack->nest_level = GUCNestLevel;
3630         switch (action)
3631         {
3632                 case GUC_ACTION_SET:
3633                         stack->state = GUC_SET;
3634                         break;
3635                 case GUC_ACTION_LOCAL:
3636                         stack->state = GUC_LOCAL;
3637                         break;
3638                 case GUC_ACTION_SAVE:
3639                         stack->state = GUC_SAVE;
3640                         break;
3641         }
3642         stack->source = gconf->source;
3643         set_stack_value(gconf, &stack->prior);
3644
3645         gconf->stack = stack;
3646
3647         /* Ensure we remember to pop at end of xact */
3648         guc_dirty = true;
3649 }
3650
3651
3652 /*
3653  * Do GUC processing at main transaction start.
3654  */
3655 void
3656 AtStart_GUC(void)
3657 {
3658         /*
3659          * The nest level should be 0 between transactions; if it isn't, somebody
3660          * didn't call AtEOXact_GUC, or called it with the wrong nestLevel.  We
3661          * throw a warning but make no other effort to clean up.
3662          */
3663         if (GUCNestLevel != 0)
3664                 elog(WARNING, "GUC nest level = %d at transaction start",
3665                          GUCNestLevel);
3666         GUCNestLevel = 1;
3667 }
3668
3669 /*
3670  * Enter a new nesting level for GUC values.  This is called at subtransaction
3671  * start and when entering a function that has proconfig settings.      NOTE that
3672  * we must not risk error here, else subtransaction start will be unhappy.
3673  */
3674 int
3675 NewGUCNestLevel(void)
3676 {
3677         return ++GUCNestLevel;
3678 }
3679
3680 /*
3681  * Do GUC processing at transaction or subtransaction commit or abort, or
3682  * when exiting a function that has proconfig settings.  (The name is thus
3683  * a bit of a misnomer; perhaps it should be ExitGUCNestLevel or some such.)
3684  * During abort, we discard all GUC settings that were applied at nesting
3685  * levels >= nestLevel.  nestLevel == 1 corresponds to the main transaction.
3686  */
3687 void
3688 AtEOXact_GUC(bool isCommit, int nestLevel)
3689 {
3690         bool            still_dirty;
3691         int                     i;
3692
3693         Assert(nestLevel > 0 && nestLevel <= GUCNestLevel);
3694
3695         /* Quick exit if nothing's changed in this transaction */
3696         if (!guc_dirty)
3697         {
3698                 GUCNestLevel = nestLevel - 1;
3699                 return;
3700         }
3701
3702         still_dirty = false;
3703         for (i = 0; i < num_guc_variables; i++)
3704         {
3705                 struct config_generic *gconf = guc_variables[i];
3706                 GucStack   *stack;
3707
3708                 /*
3709                  * Process and pop each stack entry within the nest level.      To
3710                  * simplify fmgr_security_definer(), we allow failure exit from a
3711                  * function-with-SET-options to be recovered at the surrounding
3712                  * transaction or subtransaction abort; so there could be more than
3713                  * one stack entry to pop.
3714                  */
3715                 while ((stack = gconf->stack) != NULL &&
3716                            stack->nest_level >= nestLevel)
3717                 {
3718                         GucStack   *prev = stack->prev;
3719                         bool            restorePrior = false;
3720                         bool            restoreMasked = false;
3721                         bool            changed;
3722
3723                         /*
3724                          * In this next bit, if we don't set either restorePrior or
3725                          * restoreMasked, we must "discard" any unwanted fields of the
3726                          * stack entries to avoid leaking memory.  If we do set one of
3727                          * those flags, unused fields will be cleaned up after restoring.
3728                          */
3729                         if (!isCommit)          /* if abort, always restore prior value */
3730                                 restorePrior = true;
3731                         else if (stack->state == GUC_SAVE)
3732                                 restorePrior = true;
3733                         else if (stack->nest_level == 1)
3734                         {
3735                                 /* transaction commit */
3736                                 if (stack->state == GUC_SET_LOCAL)
3737                                         restoreMasked = true;
3738                                 else if (stack->state == GUC_SET)
3739                                 {
3740                                         /* we keep the current active value */
3741                                         discard_stack_value(gconf, &stack->prior);
3742                                 }
3743                                 else    /* must be GUC_LOCAL */
3744                                         restorePrior = true;
3745                         }
3746                         else if (prev == NULL ||
3747                                          prev->nest_level < stack->nest_level - 1)
3748                         {
3749                                 /* decrement entry's level and do not pop it */
3750                                 stack->nest_level--;
3751                                 continue;
3752                         }
3753                         else
3754                         {
3755                                 /*
3756                                  * We have to merge this stack entry into prev. See README for
3757                                  * discussion of this bit.
3758                                  */
3759                                 switch (stack->state)
3760                                 {
3761                                         case GUC_SAVE:
3762                                                 Assert(false);  /* can't get here */
3763
3764                                         case GUC_SET:
3765                                                 /* next level always becomes SET */
3766                                                 discard_stack_value(gconf, &stack->prior);
3767                                                 if (prev->state == GUC_SET_LOCAL)
3768                                                         discard_stack_value(gconf, &prev->masked);
3769                                                 prev->state = GUC_SET;
3770                                                 break;
3771
3772                                         case GUC_LOCAL:
3773                                                 if (prev->state == GUC_SET)
3774                                                 {
3775                                                         /* LOCAL migrates down */
3776                                                         prev->masked = stack->prior;
3777                                                         prev->state = GUC_SET_LOCAL;
3778                                                 }
3779                                                 else
3780                                                 {
3781                                                         /* else just forget this stack level */
3782                                                         discard_stack_value(gconf, &stack->prior);
3783                                                 }
3784                                                 break;
3785
3786                                         case GUC_SET_LOCAL:
3787                                                 /* prior state at this level no longer wanted */
3788                                                 discard_stack_value(gconf, &stack->prior);
3789                                                 /* copy down the masked state */
3790                                                 if (prev->state == GUC_SET_LOCAL)
3791                                                         discard_stack_value(gconf, &prev->masked);
3792                                                 prev->masked = stack->masked;
3793                                                 prev->state = GUC_SET_LOCAL;
3794                                                 break;
3795                                 }
3796                         }
3797
3798                         changed = false;
3799
3800                         if (restorePrior || restoreMasked)
3801                         {
3802                                 /* Perform appropriate restoration of the stacked value */
3803                                 union config_var_value newvalue;
3804                                 GucSource       newsource;
3805
3806                                 if (restoreMasked)
3807                                 {
3808                                         newvalue = stack->masked;
3809                                         newsource = PGC_S_SESSION;
3810                                 }
3811                                 else
3812                                 {
3813                                         newvalue = stack->prior;
3814                                         newsource = stack->source;
3815                                 }
3816
3817                                 switch (gconf->vartype)
3818                                 {
3819                                         case PGC_BOOL:
3820                                                 {
3821                                                         struct config_bool *conf = (struct config_bool *) gconf;
3822                                                         bool            newval = newvalue.boolval;
3823
3824                                                         if (*conf->variable != newval)
3825                                                         {
3826                                                                 if (conf->assign_hook)
3827                                                                         if (!(*conf->assign_hook) (newval,
3828                                                                                                            true, PGC_S_OVERRIDE))
3829                                                                                 elog(LOG, "failed to commit %s",
3830                                                                                          conf->gen.name);
3831                                                                 *conf->variable = newval;
3832                                                                 changed = true;
3833                                                         }
3834                                                         break;
3835                                                 }
3836                                         case PGC_INT:
3837                                                 {
3838                                                         struct config_int *conf = (struct config_int *) gconf;
3839                                                         int                     newval = newvalue.intval;
3840
3841                                                         if (*conf->variable != newval)
3842                                                         {
3843                                                                 if (conf->assign_hook)
3844                                                                         if (!(*conf->assign_hook) (newval,
3845                                                                                                            true, PGC_S_OVERRIDE))
3846                                                                                 elog(LOG, "failed to commit %s",
3847                                                                                          conf->gen.name);
3848                                                                 *conf->variable = newval;
3849                                                                 changed = true;
3850                                                         }
3851                                                         break;
3852                                                 }
3853                                         case PGC_REAL:
3854                                                 {
3855                                                         struct config_real *conf = (struct config_real *) gconf;
3856                                                         double          newval = newvalue.realval;
3857
3858                                                         if (*conf->variable != newval)
3859                                                         {
3860                                                                 if (conf->assign_hook)
3861                                                                         if (!(*conf->assign_hook) (newval,
3862                                                                                                            true, PGC_S_OVERRIDE))
3863                                                                                 elog(LOG, "failed to commit %s",
3864                                                                                          conf->gen.name);
3865                                                                 *conf->variable = newval;
3866                                                                 changed = true;
3867                                                         }
3868                                                         break;
3869                                                 }
3870                                         case PGC_STRING:
3871                                                 {
3872                                                         struct config_string *conf = (struct config_string *) gconf;
3873                                                         char       *newval = newvalue.stringval;
3874
3875                                                         if (*conf->variable != newval)
3876                                                         {
3877                                                                 if (conf->assign_hook && newval)
3878                                                                 {
3879                                                                         const char *newstr;
3880
3881                                                                         newstr = (*conf->assign_hook) (newval, true,
3882                                                                                                                          PGC_S_OVERRIDE);
3883                                                                         if (newstr == NULL)
3884                                                                                 elog(LOG, "failed to commit %s",
3885                                                                                          conf->gen.name);
3886                                                                         else if (newstr != newval)
3887                                                                         {
3888                                                                                 /*
3889                                                                                  * If newval should now be freed,
3890                                                                                  * it'll be taken care of below.
3891                                                                                  *
3892                                                                                  * See notes in set_config_option
3893                                                                                  * about casting
3894                                                                                  */
3895                                                                                 newval = (char *) newstr;
3896                                                                         }
3897                                                                 }
3898
3899                                                                 set_string_field(conf, conf->variable, newval);
3900                                                                 changed = true;
3901                                                         }
3902
3903                                                         /*
3904                                                          * Release stacked values if not used anymore. We
3905                                                          * could use discard_stack_value() here, but since
3906                                                          * we have type-specific code anyway, might as
3907                                                          * well inline it.
3908                                                          */
3909                                                         set_string_field(conf, &stack->prior.stringval, NULL);
3910                                                         set_string_field(conf, &stack->masked.stringval, NULL);
3911                                                         break;
3912                                                 }
3913                                         case PGC_ENUM:
3914                                                 {
3915                                                         struct config_enum *conf = (struct config_enum *) gconf;
3916                                                         int newval = newvalue.enumval;
3917
3918                                                         if (*conf->variable != newval)
3919                                                         {
3920                                                                 if (conf->assign_hook)
3921                                                                         if (!(*conf->assign_hook) (newval,
3922                                                                                                                            true, PGC_S_OVERRIDE))
3923                                                                                 elog(LOG, "failed to commit %s",
3924                                                                                          conf->gen.name);
3925                                                                 *conf->variable = newval;
3926                                                                 changed = true;
3927                                                         }
3928                                                         break;
3929                                                 }
3930                                 }
3931
3932                                 gconf->source = newsource;
3933                         }
3934
3935                         /* Finish popping the state stack */
3936                         gconf->stack = prev;
3937                         pfree(stack);
3938
3939                         /* Report new value if we changed it */
3940                         if (changed && (gconf->flags & GUC_REPORT))
3941                                 ReportGUCOption(gconf);
3942                 }                                               /* end of stack-popping loop */
3943
3944                 if (stack != NULL)
3945                         still_dirty = true;
3946         }
3947
3948         /* If there are no remaining stack entries, we can reset guc_dirty */
3949         guc_dirty = still_dirty;
3950
3951         /* Update nesting level */
3952         GUCNestLevel = nestLevel - 1;
3953 }
3954
3955
3956 /*
3957  * Start up automatic reporting of changes to variables marked GUC_REPORT.
3958  * This is executed at completion of backend startup.
3959  */
3960 void
3961 BeginReportingGUCOptions(void)
3962 {
3963         int                     i;
3964
3965         /*
3966          * Don't do anything unless talking to an interactive frontend of protocol
3967          * 3.0 or later.
3968          */
3969         if (whereToSendOutput != DestRemote ||
3970                 PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
3971                 return;
3972
3973         reporting_enabled = true;
3974
3975         /* Transmit initial values of interesting variables */
3976         for (i = 0; i < num_guc_variables; i++)
3977         {
3978                 struct config_generic *conf = guc_variables[i];
3979
3980                 if (conf->flags & GUC_REPORT)
3981                         ReportGUCOption(conf);
3982         }
3983 }
3984
3985 /*
3986  * ReportGUCOption: if appropriate, transmit option value to frontend
3987  */
3988 static void
3989 ReportGUCOption(struct config_generic * record)
3990 {
3991         if (reporting_enabled && (record->flags & GUC_REPORT))
3992         {
3993                 char       *val = _ShowOption(record, false);
3994                 StringInfoData msgbuf;
3995
3996                 pq_beginmessage(&msgbuf, 'S');
3997                 pq_sendstring(&msgbuf, record->name);
3998                 pq_sendstring(&msgbuf, val);
3999                 pq_endmessage(&msgbuf);
4000
4001                 pfree(val);
4002         }
4003 }
4004
4005
4006 /*
4007  * Try to interpret value as boolean value.  Valid values are: true,
4008  * false, yes, no, on, off, 1, 0; as well as unique prefixes thereof.
4009  * If the string parses okay, return true, else false.
4010  * If okay and result is not NULL, return the value in *result.
4011  */
4012 bool
4013 parse_bool(const char *value, bool *result)
4014 {
4015         size_t          len = strlen(value);
4016
4017         if (pg_strncasecmp(value, "true", len) == 0)
4018         {
4019                 if (result)
4020                         *result = true;
4021         }
4022         else if (pg_strncasecmp(value, "false", len) == 0)
4023         {
4024                 if (result)
4025                         *result = false;
4026         }
4027
4028         else if (pg_strncasecmp(value, "yes", len) == 0)
4029         {
4030                 if (result)
4031                         *result = true;
4032         }
4033         else if (pg_strncasecmp(value, "no", len) == 0)
4034         {
4035                 if (result)
4036                         *result = false;
4037         }
4038
4039         /* 'o' is not unique enough */
4040         else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
4041         {
4042                 if (result)
4043                         *result = true;
4044         }
4045         else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
4046         {
4047                 if (result)
4048                         *result = false;
4049         }
4050
4051         else if (pg_strcasecmp(value, "1") == 0)
4052         {
4053                 if (result)
4054                         *result = true;
4055         }
4056         else if (pg_strcasecmp(value, "0") == 0)
4057         {
4058                 if (result)
4059                         *result = false;
4060         }
4061
4062         else
4063         {
4064                 if (result)
4065                         *result = false;        /* suppress compiler warning */
4066                 return false;
4067         }
4068         return true;
4069 }
4070
4071
4072
4073 /*
4074  * Try to parse value as an integer.  The accepted formats are the
4075  * usual decimal, octal, or hexadecimal formats, optionally followed by
4076  * a unit name if "flags" indicates a unit is allowed.
4077  *
4078  * If the string parses okay, return true, else false.
4079  * If okay and result is not NULL, return the value in *result.
4080  * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
4081  *      HINT message, or NULL if no hint provided.
4082  */
4083 static bool
4084 parse_int(const char *value, int *result, int flags, const char **hintmsg)
4085 {
4086         int64           val;
4087         char       *endptr;
4088
4089         /* To suppress compiler warnings, always set output params */
4090         if (result)
4091                 *result = 0;
4092         if (hintmsg)
4093                 *hintmsg = NULL;
4094
4095         /* We assume here that int64 is at least as wide as long */
4096         errno = 0;
4097         val = strtol(value, &endptr, 0);
4098
4099         if (endptr == value)
4100                 return false;                   /* no HINT for integer syntax error */
4101
4102         if (errno == ERANGE || val != (int64) ((int32) val))
4103         {
4104                 if (hintmsg)
4105                         *hintmsg = gettext_noop("Value exceeds integer range.");
4106                 return false;
4107         }
4108
4109         /* allow whitespace between integer and unit */
4110         while (isspace((unsigned char) *endptr))
4111                 endptr++;
4112
4113         /* Handle possible unit */
4114         if (*endptr != '\0')
4115         {
4116                 /*
4117                  * Note: the multiple-switch coding technique here is a bit tedious,
4118                  * but seems necessary to avoid intermediate-value overflows.
4119                  *
4120                  * If INT64_IS_BUSTED (ie, it's really int32) we will fail to detect
4121                  * overflow due to units conversion, but there are few enough such
4122                  * machines that it does not seem worth trying to be smarter.
4123                  */
4124                 if (flags & GUC_UNIT_MEMORY)
4125                 {
4126                         /* Set hint for use if no match or trailing garbage */
4127                         if (hintmsg)
4128                                 *hintmsg = gettext_noop("Valid units for this parameter are \"kB\", \"MB\", and \"GB\".");
4129
4130 #if BLCKSZ < 1024 || BLCKSZ > (1024*1024)
4131 #error BLCKSZ must be between 1KB and 1MB
4132 #endif
4133 #if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024*1024)
4134 #error XLOG_BLCKSZ must be between 1KB and 1MB
4135 #endif
4136
4137                         if (strncmp(endptr, "kB", 2) == 0)
4138                         {
4139                                 endptr += 2;
4140                                 switch (flags & GUC_UNIT_MEMORY)
4141                                 {
4142                                         case GUC_UNIT_BLOCKS:
4143                                                 val /= (BLCKSZ / 1024);
4144                                                 break;
4145                                         case GUC_UNIT_XBLOCKS:
4146                                                 val /= (XLOG_BLCKSZ / 1024);
4147                                                 break;
4148                                 }
4149                         }
4150                         else if (strncmp(endptr, "MB", 2) == 0)
4151                         {
4152                                 endptr += 2;
4153                                 switch (flags & GUC_UNIT_MEMORY)
4154                                 {
4155                                         case GUC_UNIT_KB:
4156                                                 val *= KB_PER_MB;
4157                                                 break;
4158                                         case GUC_UNIT_BLOCKS:
4159                                                 val *= KB_PER_MB / (BLCKSZ / 1024);
4160                                                 break;
4161                                         case GUC_UNIT_XBLOCKS:
4162                                                 val *= KB_PER_MB / (XLOG_BLCKSZ / 1024);
4163                                                 break;
4164                                 }
4165                         }
4166                         else if (strncmp(endptr, "GB", 2) == 0)
4167                         {
4168                                 endptr += 2;
4169                                 switch (flags & GUC_UNIT_MEMORY)
4170                                 {
4171                                         case GUC_UNIT_KB:
4172                                                 val *= KB_PER_GB;
4173                                                 break;
4174                                         case GUC_UNIT_BLOCKS:
4175                                                 val *= KB_PER_GB / (BLCKSZ / 1024);
4176                                                 break;
4177                                         case GUC_UNIT_XBLOCKS:
4178                                                 val *= KB_PER_GB / (XLOG_BLCKSZ / 1024);
4179                                                 break;
4180                                 }
4181                         }
4182                 }
4183                 else if (flags & GUC_UNIT_TIME)
4184                 {
4185                         /* Set hint for use if no match or trailing garbage */
4186                         if (hintmsg)
4187                                 *hintmsg = gettext_noop("Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\".");
4188
4189                         if (strncmp(endptr, "ms", 2) == 0)
4190                         {
4191                                 endptr += 2;
4192                                 switch (flags & GUC_UNIT_TIME)
4193                                 {
4194                                         case GUC_UNIT_S:
4195                                                 val /= MS_PER_S;
4196                                                 break;
4197                                         case GUC_UNIT_MIN:
4198                                                 val /= MS_PER_MIN;
4199                                                 break;
4200                                 }
4201                         }
4202                         else if (strncmp(endptr, "s", 1) == 0)
4203                         {
4204                                 endptr += 1;
4205                                 switch (flags & GUC_UNIT_TIME)
4206                                 {
4207                                         case GUC_UNIT_MS:
4208                                                 val *= MS_PER_S;
4209                                                 break;
4210                                         case GUC_UNIT_MIN:
4211                                                 val /= S_PER_MIN;
4212                                                 break;
4213                                 }
4214                         }
4215                         else if (strncmp(endptr, "min", 3) == 0)
4216                         {
4217                                 endptr += 3;
4218                                 switch (flags & GUC_UNIT_TIME)
4219                                 {
4220                                         case GUC_UNIT_MS:
4221                                                 val *= MS_PER_MIN;
4222                                                 break;
4223                                         case GUC_UNIT_S:
4224                                                 val *= S_PER_MIN;
4225                                                 break;
4226                                 }
4227                         }
4228                         else if (strncmp(endptr, "h", 1) == 0)
4229                         {
4230                                 endptr += 1;
4231                                 switch (flags & GUC_UNIT_TIME)
4232                                 {
4233                                         case GUC_UNIT_MS:
4234                                                 val *= MS_PER_H;
4235                                                 break;
4236                                         case GUC_UNIT_S:
4237                                                 val *= S_PER_H;
4238                                                 break;
4239                                         case GUC_UNIT_MIN:
4240                                                 val *= MIN_PER_H;
4241                                                 break;
4242                                 }
4243                         }
4244                         else if (strncmp(endptr, "d", 1) == 0)
4245                         {
4246                                 endptr += 1;
4247                                 switch (flags & GUC_UNIT_TIME)
4248                                 {
4249                                         case GUC_UNIT_MS:
4250                                                 val *= MS_PER_D;
4251                                                 break;
4252                                         case GUC_UNIT_S:
4253                                                 val *= S_PER_D;
4254                                                 break;
4255                                         case GUC_UNIT_MIN:
4256                                                 val *= MIN_PER_D;
4257                                                 break;
4258                                 }
4259                         }
4260                 }
4261
4262                 /* allow whitespace after unit */
4263                 while (isspace((unsigned char) *endptr))
4264                         endptr++;
4265
4266                 if (*endptr != '\0')
4267                         return false;           /* appropriate hint, if any, already set */
4268
4269                 /* Check for overflow due to units conversion */
4270                 if (val != (int64) ((int32) val))
4271                 {
4272                         if (hintmsg)
4273                                 *hintmsg = gettext_noop("Value exceeds integer range.");
4274                         return false;
4275                 }
4276         }
4277
4278         if (result)
4279                 *result = (int) val;
4280         return true;
4281 }
4282
4283
4284
4285 /*
4286  * Try to parse value as a floating point number in the usual format.
4287  * If the string parses okay, return true, else false.
4288  * If okay and result is not NULL, return the value in *result.
4289  */
4290 static bool
4291 parse_real(const char *value, double *result)
4292 {
4293         double          val;
4294         char       *endptr;
4295
4296         if (result)
4297                 *result = 0;                    /* suppress compiler warning */
4298
4299         errno = 0;
4300         val = strtod(value, &endptr);
4301         if (endptr == value || errno == ERANGE)
4302                 return false;
4303
4304         /* allow whitespace after number */
4305         while (isspace((unsigned char) *endptr))
4306                 endptr++;
4307         if (*endptr != '\0')
4308                 return false;
4309
4310         if (result)
4311                 *result = val;
4312         return true;
4313 }
4314
4315
4316 /*
4317  * Lookup the name for an enum option with the selected value.
4318  * Should only ever be called with known-valid values, so throws
4319  * an elog(ERROR) if the enum option is not found.
4320  *
4321  * The returned string is a pointer to static data and not
4322  * allocated for modification.
4323  */
4324 const char *
4325 config_enum_lookup_by_value(struct config_enum *record, int val)
4326 {
4327         const struct config_enum_entry *entry = record->options;
4328         while (entry && entry->name)
4329         {
4330                 if (entry->val == val)
4331                         return entry->name;
4332                 entry++;
4333         }
4334         elog(ERROR, "could not find enum option %d for %s",
4335                  val, record->gen.name);
4336         return NULL; /* silence compiler */
4337 }
4338
4339
4340 /*
4341  * Lookup the value for an enum option with the selected name
4342  * (case-insensitive).
4343  * If the enum option is found, sets the retval value and returns
4344  * true. If it's not found, return FALSE and retval is set to 0.
4345  *
4346  */
4347 bool
4348 config_enum_lookup_by_name(struct config_enum *record, const char *value, int *retval)
4349 {
4350         const struct config_enum_entry *entry = record->options;
4351         
4352         if (retval)
4353                 *retval = 0;                    /* suppress compiler warning */
4354         
4355         while (entry && entry->name)
4356         {
4357                 if (pg_strcasecmp(value, entry->name) == 0)
4358                 {
4359                         *retval = entry->val;
4360                         return TRUE;
4361                 }
4362                 entry++;
4363         }
4364         return FALSE;
4365 }
4366
4367
4368 /*
4369  * Return a list of all available options for an enum, excluding
4370  * hidden ones, separated by ", " (comma-space).
4371  * If prefix is non-NULL, it is added before the first enum value.
4372  * If suffix is non-NULL, it is added to the end of the string.
4373  */
4374 static char *
4375 config_enum_get_options(struct config_enum *record, const char *prefix, const char *suffix)
4376 {
4377         const struct config_enum_entry *entry = record->options;
4378         int             len = 0;
4379         char   *hintmsg;
4380
4381         if (!entry || !entry->name)
4382                 return NULL;                                    /* Should not happen */
4383
4384         while (entry && entry->name)
4385         {
4386                 if (!entry->hidden)
4387                         len += strlen(entry->name) + 2; /* string and ", " */
4388
4389                 entry++;
4390         }
4391
4392         hintmsg = palloc(len + strlen(prefix) + strlen(suffix) + 2);
4393
4394         strcpy(hintmsg, prefix);
4395         
4396         entry = record->options;
4397         while (entry && entry->name)
4398         {
4399                 if (!entry->hidden)
4400                 {
4401                         strcat(hintmsg, entry->name);
4402                         strcat(hintmsg, ", ");
4403                 }
4404
4405                 entry++;
4406         }
4407
4408         len = strlen(hintmsg);
4409
4410         /*
4411          * All the entries may have been hidden, leaving the string empty
4412          * if no prefix was given. This indicates a broken GUC setup, since
4413          * there is no use for an enum without any values, so we just check
4414          * to make sure we don't write to invalid memory instead of actually
4415          * trying to do something smart with it.
4416          */
4417         if (len > 1)
4418                 /* Replace final comma/space */
4419                 hintmsg[len-2] = '\0';
4420
4421         strcat(hintmsg, suffix);
4422
4423         return hintmsg;
4424 }
4425
4426
4427 /*
4428  * Call a GucStringAssignHook function, being careful to free the
4429  * "newval" string if the hook ereports.
4430  *
4431  * This is split out of set_config_option just to avoid the "volatile"
4432  * qualifiers that would otherwise have to be plastered all over.
4433  */
4434 static const char *
4435 call_string_assign_hook(GucStringAssignHook assign_hook,
4436                                                 char *newval, bool doit, GucSource source)
4437 {
4438         const char *result;
4439
4440         PG_TRY();
4441         {
4442                 result = (*assign_hook) (newval, doit, source);
4443         }
4444         PG_CATCH();
4445         {
4446                 free(newval);
4447                 PG_RE_THROW();
4448         }
4449         PG_END_TRY();
4450
4451         return result;
4452 }
4453
4454
4455 /*
4456  * Sets option `name' to given value. The value should be a string
4457  * which is going to be parsed and converted to the appropriate data
4458  * type.  The context and source parameters indicate in which context this
4459  * function is being called so it can apply the access restrictions
4460  * properly.
4461  *
4462  * If value is NULL, set the option to its default value (normally the
4463  * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
4464  *
4465  * action indicates whether to set the value globally in the session, locally
4466  * to the current top transaction, or just for the duration of a function call.
4467  *
4468  * If changeVal is false then don't really set the option but do all
4469  * the checks to see if it would work.
4470  *
4471  * If there is an error (non-existing option, invalid value) then an
4472  * ereport(ERROR) is thrown *unless* this is called in a context where we
4473  * don't want to ereport (currently, startup or SIGHUP config file reread).
4474  * In that case we write a suitable error message via ereport(LOG) and
4475  * return false. This is working around the deficiencies in the ereport
4476  * mechanism, so don't blame me.  In all other cases, the function
4477  * returns true, including cases where the input is valid but we chose
4478  * not to apply it because of context or source-priority considerations.
4479  *
4480  * See also SetConfigOption for an external interface.
4481  */
4482 bool
4483 set_config_option(const char *name, const char *value,
4484                                   GucContext context, GucSource source,
4485                                   GucAction action, bool changeVal)
4486 {
4487         struct config_generic *record;
4488         int                     elevel;
4489         bool            makeDefault;
4490
4491         if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
4492         {
4493                 /*
4494                  * To avoid cluttering the log, only the postmaster bleats loudly
4495                  * about problems with the config file.
4496                  */
4497                 elevel = IsUnderPostmaster ? DEBUG3 : LOG;
4498         }
4499         else if (source == PGC_S_DATABASE || source == PGC_S_USER)
4500                 elevel = INFO;
4501         else
4502                 elevel = ERROR;
4503
4504         record = find_option(name, true, elevel);
4505         if (record == NULL)
4506         {
4507                 ereport(elevel,
4508                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
4509                            errmsg("unrecognized configuration parameter \"%s\"", name)));
4510                 return false;
4511         }
4512
4513         /*
4514          * If source is postgresql.conf, mark the found record with
4515          * GUC_IS_IN_FILE. This is for the convenience of ProcessConfigFile.  Note
4516          * that we do it even if changeVal is false, since ProcessConfigFile wants
4517          * the marking to occur during its testing pass.
4518          */
4519         if (source == PGC_S_FILE)
4520                 record->status |= GUC_IS_IN_FILE;
4521
4522         /*
4523          * Check if the option can be set at this time. See guc.h for the precise
4524          * rules. Note that we don't want to throw errors if we're in the SIGHUP
4525          * context. In that case we just ignore the attempt and return true.
4526          */
4527         switch (record->context)
4528         {
4529                 case PGC_INTERNAL:
4530                         if (context == PGC_SIGHUP)
4531                                 return true;
4532                         if (context != PGC_INTERNAL)
4533                         {
4534                                 ereport(elevel,
4535                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4536                                                  errmsg("parameter \"%s\" cannot be changed",
4537                                                                 name)));
4538                                 return false;
4539                         }
4540                         break;
4541                 case PGC_POSTMASTER:
4542                         if (context == PGC_SIGHUP)
4543                         {
4544                                 /*
4545                                  * We are reading a PGC_POSTMASTER var from postgresql.conf.
4546                                  * We can't change the setting, so give a warning if the DBA
4547                                  * tries to change it.  (Throwing an error would be more
4548                                  * consistent, but seems overly rigid.)
4549                                  */
4550                                 if (changeVal && !is_newvalue_equal(record, value))
4551                                         ereport(elevel,
4552                                                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4553                                                          errmsg("parameter \"%s\" cannot be changed after server start; configuration file change ignored",
4554                                                                         name)));
4555                                 return true;
4556                         }
4557                         if (context != PGC_POSTMASTER)
4558                         {
4559                                 ereport(elevel,
4560                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4561                                                  errmsg("parameter \"%s\" cannot be changed after server start",
4562                                                                 name)));
4563                                 return false;
4564                         }
4565                         break;
4566                 case PGC_SIGHUP:
4567                         if (context != PGC_SIGHUP && context != PGC_POSTMASTER)
4568                         {
4569                                 ereport(elevel,
4570                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4571                                                  errmsg("parameter \"%s\" cannot be changed now",
4572                                                                 name)));
4573                                 return false;
4574                         }
4575
4576                         /*
4577                          * Hmm, the idea of the SIGHUP context is "ought to be global, but
4578                          * can be changed after postmaster start". But there's nothing
4579                          * that prevents a crafty administrator from sending SIGHUP
4580                          * signals to individual backends only.
4581                          */
4582                         break;
4583                 case PGC_BACKEND:
4584                         if (context == PGC_SIGHUP)
4585                         {
4586                                 /*
4587                                  * If a PGC_BACKEND parameter is changed in the config file,
4588                                  * we want to accept the new value in the postmaster (whence
4589                                  * it will propagate to subsequently-started backends), but
4590                                  * ignore it in existing backends.      This is a tad klugy, but
4591                                  * necessary because we don't re-read the config file during
4592                                  * backend start.
4593                                  */
4594                                 if (IsUnderPostmaster)
4595                                         return true;
4596                         }
4597                         else if (context != PGC_BACKEND && context != PGC_POSTMASTER)
4598                         {
4599                                 ereport(elevel,
4600                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4601                                                  errmsg("parameter \"%s\" cannot be set after connection start",
4602                                                                 name)));
4603                                 return false;
4604                         }
4605                         break;
4606                 case PGC_SUSET:
4607                         if (context == PGC_USERSET || context == PGC_BACKEND)
4608                         {
4609                                 ereport(elevel,
4610                                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4611                                                  errmsg("permission denied to set parameter \"%s\"",
4612                                                                 name)));
4613                                 return false;
4614                         }
4615                         break;
4616                 case PGC_USERSET:
4617                         /* always okay */
4618                         break;
4619         }
4620
4621         /*
4622          * Should we set reset/stacked values?  (If so, the behavior is not
4623          * transactional.)      This is done either when we get a default value from
4624          * the database's/user's/client's default settings or when we reset a
4625          * value to its default.
4626          */
4627         makeDefault = changeVal && (source <= PGC_S_OVERRIDE) &&
4628                 ((value != NULL) || source == PGC_S_DEFAULT);
4629
4630         /*
4631          * Ignore attempted set if overridden by previously processed setting.
4632          * However, if changeVal is false then plow ahead anyway since we are
4633          * trying to find out if the value is potentially good, not actually use
4634          * it. Also keep going if makeDefault is true, since we may want to set
4635          * the reset/stacked values even if we can't set the variable itself.
4636          */
4637         if (record->source > source)
4638         {
4639                 if (changeVal && !makeDefault)
4640                 {
4641                         elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
4642                                  name);
4643                         return true;
4644                 }
4645                 changeVal = false;
4646         }
4647
4648         /*
4649          * Evaluate value and set variable.
4650          */
4651         switch (record->vartype)
4652         {
4653                 case PGC_BOOL:
4654                         {
4655                                 struct config_bool *conf = (struct config_bool *) record;
4656                                 bool            newval;
4657
4658                                 if (value)
4659                                 {
4660                                         if (!parse_bool(value, &newval))
4661                                         {
4662                                                 ereport(elevel,
4663                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4664                                                   errmsg("parameter \"%s\" requires a Boolean value",
4665                                                                  name)));
4666                                                 return false;
4667                                         }
4668                                 }
4669                                 else if (source == PGC_S_DEFAULT)
4670                                         newval = conf->boot_val;
4671                                 else
4672                                 {
4673                                         newval = conf->reset_val;
4674                                         source = conf->gen.reset_source;
4675                                 }
4676
4677                                 /* Save old value to support transaction abort */
4678                                 if (changeVal && !makeDefault)
4679                                         push_old_value(&conf->gen, action);
4680
4681                                 if (conf->assign_hook)
4682                                         if (!(*conf->assign_hook) (newval, changeVal, source))
4683                                         {
4684                                                 ereport(elevel,
4685                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4686                                                          errmsg("invalid value for parameter \"%s\": %d",
4687                                                                         name, (int) newval)));
4688                                                 return false;
4689                                         }
4690
4691                                 if (changeVal)
4692                                 {
4693                                         *conf->variable = newval;
4694                                         conf->gen.source = source;
4695                                 }
4696                                 if (makeDefault)
4697                                 {
4698                                         GucStack   *stack;
4699
4700                                         if (conf->gen.reset_source <= source)
4701                                         {
4702                                                 conf->reset_val = newval;
4703                                                 conf->gen.reset_source = source;
4704                                         }
4705                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
4706                                         {
4707                                                 if (stack->source <= source)
4708                                                 {
4709                                                         stack->prior.boolval = newval;
4710                                                         stack->source = source;
4711                                                 }
4712                                         }
4713                                 }
4714                                 break;
4715                         }
4716
4717                 case PGC_INT:
4718                         {
4719                                 struct config_int *conf = (struct config_int *) record;
4720                                 int                     newval;
4721
4722                                 if (value)
4723                                 {
4724                                         const char *hintmsg;
4725
4726                                         if (!parse_int(value, &newval, conf->gen.flags, &hintmsg))
4727                                         {
4728                                                 ereport(elevel,
4729                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4730                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
4731                                                                 name, value),
4732                                                                  hintmsg ? errhint(hintmsg) : 0));
4733                                                 return false;
4734                                         }
4735                                         if (newval < conf->min || newval > conf->max)
4736                                         {
4737                                                 ereport(elevel,
4738                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4739                                                                  errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
4740                                                                                 newval, name, conf->min, conf->max)));
4741                                                 return false;
4742                                         }
4743                                 }
4744                                 else if (source == PGC_S_DEFAULT)
4745                                         newval = conf->boot_val;
4746                                 else
4747                                 {
4748                                         newval = conf->reset_val;
4749                                         source = conf->gen.reset_source;
4750                                 }
4751
4752                                 /* Save old value to support transaction abort */
4753                                 if (changeVal && !makeDefault)
4754                                         push_old_value(&conf->gen, action);
4755
4756                                 if (conf->assign_hook)
4757                                         if (!(*conf->assign_hook) (newval, changeVal, source))
4758                                         {
4759                                                 ereport(elevel,
4760                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4761                                                          errmsg("invalid value for parameter \"%s\": %d",
4762                                                                         name, newval)));
4763                                                 return false;
4764                                         }
4765
4766                                 if (changeVal)
4767                                 {
4768                                         *conf->variable = newval;
4769                                         conf->gen.source = source;
4770                                 }
4771                                 if (makeDefault)
4772                                 {
4773                                         GucStack   *stack;
4774
4775                                         if (conf->gen.reset_source <= source)
4776                                         {
4777                                                 conf->reset_val = newval;
4778                                                 conf->gen.reset_source = source;
4779                                         }
4780                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
4781                                         {
4782                                                 if (stack->source <= source)
4783                                                 {
4784                                                         stack->prior.intval = newval;
4785                                                         stack->source = source;
4786                                                 }
4787                                         }
4788                                 }
4789                                 break;
4790                         }
4791
4792                 case PGC_REAL:
4793                         {
4794                                 struct config_real *conf = (struct config_real *) record;
4795                                 double          newval;
4796
4797                                 if (value)
4798                                 {
4799                                         if (!parse_real(value, &newval))
4800                                         {
4801                                                 ereport(elevel,
4802                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4803                                                   errmsg("parameter \"%s\" requires a numeric value",
4804                                                                  name)));
4805                                                 return false;
4806                                         }
4807                                         if (newval < conf->min || newval > conf->max)
4808                                         {
4809                                                 ereport(elevel,
4810                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4811                                                                  errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
4812                                                                                 newval, name, conf->min, conf->max)));
4813                                                 return false;
4814                                         }
4815                                 }
4816                                 else if (source == PGC_S_DEFAULT)
4817                                         newval = conf->boot_val;
4818                                 else
4819                                 {
4820                                         newval = conf->reset_val;
4821                                         source = conf->gen.reset_source;
4822                                 }
4823
4824                                 /* Save old value to support transaction abort */
4825                                 if (changeVal && !makeDefault)
4826                                         push_old_value(&conf->gen, action);
4827
4828                                 if (conf->assign_hook)
4829                                         if (!(*conf->assign_hook) (newval, changeVal, source))
4830                                         {
4831                                                 ereport(elevel,
4832                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4833                                                          errmsg("invalid value for parameter \"%s\": %g",
4834                                                                         name, newval)));
4835                                                 return false;
4836                                         }
4837
4838                                 if (changeVal)
4839                                 {
4840                                         *conf->variable = newval;
4841                                         conf->gen.source = source;
4842                                 }
4843                                 if (makeDefault)
4844                                 {
4845                                         GucStack   *stack;
4846
4847                                         if (conf->gen.reset_source <= source)
4848                                         {
4849                                                 conf->reset_val = newval;
4850                                                 conf->gen.reset_source = source;
4851                                         }
4852                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
4853                                         {
4854                                                 if (stack->source <= source)
4855                                                 {
4856                                                         stack->prior.realval = newval;
4857                                                         stack->source = source;
4858                                                 }
4859                                         }
4860                                 }
4861                                 break;
4862                         }
4863
4864                 case PGC_STRING:
4865                         {
4866                                 struct config_string *conf = (struct config_string *) record;
4867                                 char       *newval;
4868
4869                                 if (value)
4870                                 {
4871                                         newval = guc_strdup(elevel, value);
4872                                         if (newval == NULL)
4873                                                 return false;
4874
4875                                         /*
4876                                          * The only sort of "parsing" check we need to do is apply
4877                                          * truncation if GUC_IS_NAME.
4878                                          */
4879                                         if (conf->gen.flags & GUC_IS_NAME)
4880                                                 truncate_identifier(newval, strlen(newval), true);
4881                                 }
4882                                 else if (source == PGC_S_DEFAULT)
4883                                 {
4884                                         if (conf->boot_val == NULL)
4885                                                 newval = NULL;
4886                                         else
4887                                         {
4888                                                 newval = guc_strdup(elevel, conf->boot_val);
4889                                                 if (newval == NULL)
4890                                                         return false;
4891                                         }
4892                                 }
4893                                 else
4894                                 {
4895                                         /*
4896                                          * We could possibly avoid strdup here, but easier to make
4897                                          * this case work the same as the normal assignment case;
4898                                          * note the possible free of newval below.
4899                                          */
4900                                         if (conf->reset_val == NULL)
4901                                                 newval = NULL;
4902                                         else
4903                                         {
4904                                                 newval = guc_strdup(elevel, conf->reset_val);
4905                                                 if (newval == NULL)
4906                                                         return false;
4907                                         }
4908                                         source = conf->gen.reset_source;
4909                                 }
4910
4911                                 /* Save old value to support transaction abort */
4912                                 if (changeVal && !makeDefault)
4913                                         push_old_value(&conf->gen, action);
4914
4915                                 if (conf->assign_hook && newval)
4916                                 {
4917                                         const char *hookresult;
4918
4919                                         /*
4920                                          * If the hook ereports, we have to make sure we free
4921                                          * newval, else it will be a permanent memory leak.
4922                                          */
4923                                         hookresult = call_string_assign_hook(conf->assign_hook,
4924                                                                                                                  newval,
4925                                                                                                                  changeVal,
4926                                                                                                                  source);
4927                                         if (hookresult == NULL)
4928                                         {
4929                                                 free(newval);
4930                                                 ereport(elevel,
4931                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4932                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
4933                                                                 name, value ? value : "")));
4934                                                 return false;
4935                                         }
4936                                         else if (hookresult != newval)
4937                                         {
4938                                                 free(newval);
4939
4940                                                 /*
4941                                                  * Having to cast away const here is annoying, but the
4942                                                  * alternative is to declare assign_hooks as returning
4943                                                  * char*, which would mean they'd have to cast away
4944                                                  * const, or as both taking and returning char*, which
4945                                                  * doesn't seem attractive either --- we don't want
4946                                                  * them to scribble on the passed str.
4947                                                  */
4948                                                 newval = (char *) hookresult;
4949                                         }
4950                                 }
4951
4952                                 if (changeVal)
4953                                 {
4954                                         set_string_field(conf, conf->variable, newval);
4955                                         conf->gen.source = source;
4956                                 }
4957                                 if (makeDefault)
4958                                 {
4959                                         GucStack   *stack;
4960
4961                                         if (conf->gen.reset_source <= source)
4962                                         {
4963                                                 set_string_field(conf, &conf->reset_val, newval);
4964                                                 conf->gen.reset_source = source;
4965                                         }
4966                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
4967                                         {
4968                                                 if (stack->source <= source)
4969                                                 {
4970                                                         set_string_field(conf, &stack->prior.stringval,
4971                                                                                          newval);
4972                                                         stack->source = source;
4973                                                 }
4974                                         }
4975                                 }
4976                                 /* Perhaps we didn't install newval anywhere */
4977                                 if (newval && !string_field_used(conf, newval))
4978                                         free(newval);
4979                                 break;
4980                         }
4981                 case PGC_ENUM:
4982                         {
4983                                 struct config_enum *conf = (struct config_enum *) record;
4984                                 int                     newval;
4985
4986                                 if (value)
4987                                 {
4988                                         if (!config_enum_lookup_by_name(conf, value, &newval))
4989                                         {
4990                                                 char *hintmsg = config_enum_get_options(conf, "Available values: ", ".");
4991
4992                                                 ereport(elevel,
4993                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4994                                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
4995                                                                                 name, value),
4996                                                                  hintmsg ? errhint(hintmsg) : 0));
4997
4998                                                 if (hintmsg)
4999                                                         pfree(hintmsg);
5000                                                 return false;
5001                                         }
5002                                 }
5003                                 else if (source == PGC_S_DEFAULT)
5004                                         newval = conf->boot_val;
5005                                 else
5006                                 {
5007                                         newval = conf->reset_val;
5008                                         source = conf->gen.reset_source;
5009                                 }
5010
5011                                 /* Save old value to support transaction abort */
5012                                 if (changeVal && !makeDefault)
5013                                         push_old_value(&conf->gen, action);
5014
5015                                 if (conf->assign_hook)
5016                                         if (!(*conf->assign_hook) (newval, changeVal, source))
5017                                         {
5018                                                 ereport(elevel,
5019                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5020                                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
5021                                                                                 name, 
5022                                                                                 config_enum_lookup_by_value(conf, newval))));
5023                                                 return false;
5024                                         }
5025
5026                                 if (changeVal)
5027                                 {
5028                                         *conf->variable = newval;
5029                                         conf->gen.source = source;
5030                                 }
5031                                 if (makeDefault)
5032                                 {
5033                                         GucStack   *stack;
5034
5035                                         if (conf->gen.reset_source <= source)
5036                                         {
5037                                                 conf->reset_val = newval;
5038                                                 conf->gen.reset_source = source;
5039                                         }
5040                                         for (stack = conf->gen.stack; stack; stack = stack->prev)
5041                                         {
5042                                                 if (stack->source <= source)
5043                                                 {
5044                                                         stack->prior.enumval = newval;
5045                                                         stack->source = source;
5046                                                 }
5047                                         }
5048                                 }
5049                                 break;
5050                         }
5051         }
5052
5053         if (changeVal && (record->flags & GUC_REPORT))
5054                 ReportGUCOption(record);
5055
5056         return true;
5057 }
5058
5059
5060 /*
5061  * Set a config option to the given value. See also set_config_option,
5062  * this is just the wrapper to be called from outside GUC.      NB: this
5063  * is used only for non-transactional operations.
5064  */
5065 void
5066 SetConfigOption(const char *name, const char *value,
5067                                 GucContext context, GucSource source)
5068 {
5069         (void) set_config_option(name, value, context, source,
5070                                                          GUC_ACTION_SET, true);
5071 }
5072
5073
5074
5075 /*
5076  * Fetch the current value of the option `name'. If the option doesn't exist,
5077  * throw an ereport and don't return.
5078  *
5079  * The string is *not* allocated for modification and is really only
5080  * valid until the next call to configuration related functions.
5081  */
5082 const char *
5083 GetConfigOption(const char *name)
5084 {
5085         struct config_generic *record;
5086         static char buffer[256];
5087
5088         record = find_option(name, false, ERROR);
5089         if (record == NULL)
5090                 ereport(ERROR,
5091                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
5092                            errmsg("unrecognized configuration parameter \"%s\"", name)));
5093         if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
5094                 ereport(ERROR,
5095                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5096                                  errmsg("must be superuser to examine \"%s\"", name)));
5097
5098         switch (record->vartype)
5099         {
5100                 case PGC_BOOL:
5101                         return *((struct config_bool *) record)->variable ? "on" : "off";
5102
5103                 case PGC_INT:
5104                         snprintf(buffer, sizeof(buffer), "%d",
5105                                          *((struct config_int *) record)->variable);
5106                         return buffer;
5107
5108                 case PGC_REAL:
5109                         snprintf(buffer, sizeof(buffer), "%g",
5110                                          *((struct config_real *) record)->variable);
5111                         return buffer;
5112
5113                 case PGC_STRING:
5114                         return *((struct config_string *) record)->variable;
5115
5116                 case PGC_ENUM:
5117                         return config_enum_lookup_by_value((struct config_enum *) record,
5118                                                                                         *((struct config_enum *) record)->variable);
5119         }
5120         return NULL;
5121 }
5122
5123 /*
5124  * Get the RESET value associated with the given option.
5125  *
5126  * Note: this is not re-entrant, due to use of static result buffer;
5127  * not to mention that a string variable could have its reset_val changed.
5128  * Beware of assuming the result value is good for very long.
5129  */
5130 const char *
5131 GetConfigOptionResetString(const char *name)
5132 {
5133         struct config_generic *record;
5134         static char buffer[256];
5135
5136         record = find_option(name, false, ERROR);
5137         if (record == NULL)
5138                 ereport(ERROR,
5139                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
5140                            errmsg("unrecognized configuration parameter \"%s\"", name)));
5141         if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
5142                 ereport(ERROR,
5143                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5144                                  errmsg("must be superuser to examine \"%s\"", name)));
5145
5146         switch (record->vartype)
5147         {
5148                 case PGC_BOOL:
5149                         return ((struct config_bool *) record)->reset_val ? "on" : "off";
5150
5151                 case PGC_INT:
5152                         snprintf(buffer, sizeof(buffer), "%d",
5153                                          ((struct config_int *) record)->reset_val);
5154                         return buffer;
5155
5156                 case PGC_REAL:
5157                         snprintf(buffer, sizeof(buffer), "%g",
5158                                          ((struct config_real *) record)->reset_val);
5159                         return buffer;
5160
5161                 case PGC_STRING:
5162                         return ((struct config_string *) record)->reset_val;
5163
5164                 case PGC_ENUM:
5165                         return config_enum_lookup_by_value((struct config_enum *) record,
5166                                                                                     ((struct config_enum *) record)->reset_val);
5167         }
5168         return NULL;
5169 }
5170
5171 /*
5172  * Detect whether the given configuration option can only be set by
5173  * a superuser.
5174  */
5175 bool
5176 IsSuperuserConfigOption(const char *name)
5177 {
5178         struct config_generic *record;
5179
5180         record = find_option(name, false, ERROR);
5181         /* On an unrecognized name, don't error, just return false. */
5182         if (record == NULL)
5183                 return false;
5184         return (record->context == PGC_SUSET);
5185 }
5186
5187
5188 /*
5189  * GUC_complaint_elevel
5190  *              Get the ereport error level to use in an assign_hook's error report.
5191  *
5192  * This should be used by assign hooks that want to emit a custom error
5193  * report (in addition to the generic "invalid value for option FOO" that
5194  * guc.c will provide).  Note that the result might be ERROR or a lower
5195  * level, so the caller must be prepared for control to return from ereport,
5196  * or not.  If control does return, return false/NULL from the hook function.
5197  *
5198  * At some point it'd be nice to replace this with a mechanism that allows
5199  * the custom message to become the DETAIL line of guc.c's generic message.
5200  */
5201 int
5202 GUC_complaint_elevel(GucSource source)
5203 {
5204         int                     elevel;
5205
5206         if (source == PGC_S_FILE)
5207         {
5208                 /*
5209                  * To avoid cluttering the log, only the postmaster bleats loudly
5210                  * about problems with the config file.
5211                  */
5212                 elevel = IsUnderPostmaster ? DEBUG3 : LOG;
5213         }
5214         else if (source == PGC_S_OVERRIDE)
5215         {
5216                 /*
5217                  * If we're a postmaster child, this is probably "undo" during
5218                  * transaction abort, so we don't want to clutter the log.  There's
5219                  * a small chance of a real problem with an OVERRIDE setting,
5220                  * though, so suppressing the message entirely wouldn't be desirable.
5221                  */
5222                 elevel = IsUnderPostmaster ? DEBUG5 : LOG;
5223         }
5224         else if (source < PGC_S_INTERACTIVE)
5225                 elevel = LOG;
5226         else
5227                 elevel = ERROR;
5228
5229         return elevel;
5230 }
5231
5232
5233 /*
5234  * flatten_set_variable_args
5235  *              Given a parsenode List as emitted by the grammar for SET,
5236  *              convert to the flat string representation used by GUC.
5237  *
5238  * We need to be told the name of the variable the args are for, because
5239  * the flattening rules vary (ugh).
5240  *
5241  * The result is NULL if args is NIL (ie, SET ... TO DEFAULT), otherwise
5242  * a palloc'd string.
5243  */
5244 static char *
5245 flatten_set_variable_args(const char *name, List *args)
5246 {
5247         struct config_generic *record;
5248         int                     flags;
5249         StringInfoData buf;
5250         ListCell   *l;
5251
5252         /* Fast path if just DEFAULT */
5253         if (args == NIL)
5254                 return NULL;
5255
5256         /* Else get flags for the variable */
5257         record = find_option(name, true, ERROR);
5258         if (record == NULL)
5259                 ereport(ERROR,
5260                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
5261                            errmsg("unrecognized configuration parameter \"%s\"", name)));
5262
5263         flags = record->flags;
5264
5265         /* Complain if list input and non-list variable */
5266         if ((flags & GUC_LIST_INPUT) == 0 &&
5267                 list_length(args) != 1)
5268                 ereport(ERROR,
5269                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5270                                  errmsg("SET %s takes only one argument", name)));
5271
5272         initStringInfo(&buf);
5273
5274         /*
5275          * Each list member may be a plain A_Const node, or an A_Const within a
5276          * TypeCast; the latter case is supported only for ConstInterval
5277          * arguments (for SET TIME ZONE).
5278          */
5279         foreach(l, args)
5280         {
5281                 Node       *arg = (Node *) lfirst(l);
5282                 char       *val;
5283                 TypeName   *typename = NULL;
5284                 A_Const    *con;
5285
5286                 if (l != list_head(args))
5287                         appendStringInfo(&buf, ", ");
5288
5289                 if (IsA(arg, TypeCast))
5290                 {
5291                         TypeCast *tc = (TypeCast *) arg;
5292
5293                         arg = tc->arg;
5294                         typename = tc->typename;
5295                 }
5296
5297                 if (!IsA(arg, A_Const))
5298                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
5299                 con = (A_Const *) arg;
5300
5301                 switch (nodeTag(&con->val))
5302                 {
5303                         case T_Integer:
5304                                 appendStringInfo(&buf, "%ld", intVal(&con->val));
5305                                 break;
5306                         case T_Float:
5307                                 /* represented as a string, so just copy it */
5308                                 appendStringInfoString(&buf, strVal(&con->val));
5309                                 break;
5310                         case T_String:
5311                                 val = strVal(&con->val);
5312                                 if (typename != NULL)
5313                                 {
5314                                         /*
5315                                          * Must be a ConstInterval argument for TIME ZONE. Coerce
5316                                          * to interval and back to normalize the value and account
5317                                          * for any typmod.
5318                                          */
5319                                         Oid                     typoid;
5320                                         int32           typmod;
5321                                         Datum           interval;
5322                                         char       *intervalout;
5323
5324                                         typoid = typenameTypeId(NULL, typename, &typmod);
5325                                         Assert(typoid == INTERVALOID);
5326
5327                                         interval =
5328                                                 DirectFunctionCall3(interval_in,
5329                                                                                         CStringGetDatum(val),
5330                                                                                         ObjectIdGetDatum(InvalidOid),
5331                                                                                         Int32GetDatum(typmod));
5332
5333                                         intervalout =
5334                                                 DatumGetCString(DirectFunctionCall1(interval_out,
5335                                                                                                                         interval));
5336                                         appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
5337                                 }
5338                                 else
5339                                 {
5340                                         /*
5341                                          * Plain string literal or identifier.  For quote mode,
5342                                          * quote it if it's not a vanilla identifier.
5343                                          */
5344                                         if (flags & GUC_LIST_QUOTE)
5345                                                 appendStringInfoString(&buf, quote_identifier(val));
5346                                         else
5347                                                 appendStringInfoString(&buf, val);
5348                                 }
5349                                 break;
5350                         default:
5351                                 elog(ERROR, "unrecognized node type: %d",
5352                                          (int) nodeTag(&con->val));
5353                                 break;
5354                 }
5355         }
5356
5357         return buf.data;
5358 }
5359
5360
5361 /*
5362  * SET command
5363  */
5364 void
5365 ExecSetVariableStmt(VariableSetStmt *stmt)
5366 {
5367         GucAction       action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
5368
5369         switch (stmt->kind)
5370         {
5371                 case VAR_SET_VALUE:
5372                 case VAR_SET_CURRENT:
5373                         set_config_option(stmt->name,
5374                                                           ExtractSetVariableArgs(stmt),
5375                                                           (superuser() ? PGC_SUSET : PGC_USERSET),
5376                                                           PGC_S_SESSION,
5377                                                           action,
5378                                                           true);
5379                         break;
5380                 case VAR_SET_MULTI:
5381
5382                         /*
5383                          * Special case for special SQL syntax that effectively sets more
5384                          * than one variable per statement.
5385                          */
5386                         if (strcmp(stmt->name, "TRANSACTION") == 0)
5387                         {
5388                                 ListCell   *head;
5389
5390                                 foreach(head, stmt->args)
5391                                 {
5392                                         DefElem    *item = (DefElem *) lfirst(head);
5393
5394                                         if (strcmp(item->defname, "transaction_isolation") == 0)
5395                                                 SetPGVariable("transaction_isolation",
5396                                                                           list_make1(item->arg), stmt->is_local);
5397                                         else if (strcmp(item->defname, "transaction_read_only") == 0)
5398                                                 SetPGVariable("transaction_read_only",
5399                                                                           list_make1(item->arg), stmt->is_local);
5400                                         else
5401                                                 elog(ERROR, "unexpected SET TRANSACTION element: %s",
5402                                                          item->defname);
5403                                 }
5404                         }
5405                         else if (strcmp(stmt->name, "SESSION CHARACTERISTICS") == 0)
5406                         {
5407                                 ListCell   *head;
5408
5409                                 foreach(head, stmt->args)
5410                                 {
5411                                         DefElem    *item = (DefElem *) lfirst(head);
5412
5413                                         if (strcmp(item->defname, "transaction_isolation") == 0)
5414                                                 SetPGVariable("default_transaction_isolation",
5415                                                                           list_make1(item->arg), stmt->is_local);
5416                                         else if (strcmp(item->defname, "transaction_read_only") == 0)
5417                                                 SetPGVariable("default_transaction_read_only",
5418                                                                           list_make1(item->arg), stmt->is_local);
5419                                         else
5420                                                 elog(ERROR, "unexpected SET SESSION element: %s",
5421                                                          item->defname);
5422                                 }
5423                         }
5424                         else
5425                                 elog(ERROR, "unexpected SET MULTI element: %s",
5426                                          stmt->name);
5427                         break;
5428                 case VAR_SET_DEFAULT:
5429                 case VAR_RESET:
5430                         set_config_option(stmt->name,
5431                                                           NULL,
5432                                                           (superuser() ? PGC_SUSET : PGC_USERSET),
5433                                                           PGC_S_SESSION,
5434                                                           action,
5435                                                           true);
5436                         break;
5437                 case VAR_RESET_ALL:
5438                         ResetAllOptions();
5439                         break;
5440         }
5441 }
5442
5443 /*
5444  * Get the value to assign for a VariableSetStmt, or NULL if it's RESET.
5445  * The result is palloc'd.
5446  *
5447  * This is exported for use by actions such as ALTER ROLE SET.
5448  */
5449 char *
5450 ExtractSetVariableArgs(VariableSetStmt *stmt)
5451 {
5452         switch (stmt->kind)
5453         {
5454                 case VAR_SET_VALUE:
5455                         return flatten_set_variable_args(stmt->name, stmt->args);
5456                 case VAR_SET_CURRENT:
5457                         return GetConfigOptionByName(stmt->name, NULL);
5458                 default:
5459                         return NULL;
5460         }
5461 }
5462
5463 /*
5464  * SetPGVariable - SET command exported as an easily-C-callable function.
5465  *
5466  * This provides access to SET TO value, as well as SET TO DEFAULT (expressed
5467  * by passing args == NIL), but not SET FROM CURRENT functionality.
5468  */
5469 void
5470 SetPGVariable(const char *name, List *args, bool is_local)
5471 {
5472         char       *argstring = flatten_set_variable_args(name, args);
5473
5474         /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
5475         set_config_option(name,
5476                                           argstring,
5477                                           (superuser() ? PGC_SUSET : PGC_USERSET),
5478                                           PGC_S_SESSION,
5479                                           is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
5480                                           true);
5481 }
5482
5483 /*
5484  * SET command wrapped as a SQL callable function.
5485  */
5486 Datum
5487 set_config_by_name(PG_FUNCTION_ARGS)
5488 {
5489         char       *name;
5490         char       *value;
5491         char       *new_value;
5492         bool            is_local;
5493
5494         if (PG_ARGISNULL(0))
5495                 ereport(ERROR,
5496                                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5497                                  errmsg("SET requires parameter name")));
5498
5499         /* Get the GUC variable name */
5500         name = TextDatumGetCString(PG_GETARG_DATUM(0));
5501
5502         /* Get the desired value or set to NULL for a reset request */
5503         if (PG_ARGISNULL(1))
5504                 value = NULL;
5505         else
5506                 value = TextDatumGetCString(PG_GETARG_DATUM(1));
5507
5508         /*
5509          * Get the desired state of is_local. Default to false if provided value
5510          * is NULL
5511          */
5512         if (PG_ARGISNULL(2))
5513                 is_local = false;
5514         else
5515                 is_local = PG_GETARG_BOOL(2);
5516
5517         /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
5518         set_config_option(name,
5519                                           value,
5520                                           (superuser() ? PGC_SUSET : PGC_USERSET),
5521                                           PGC_S_SESSION,
5522                                           is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
5523                                           true);
5524
5525         /* get the new current value */
5526         new_value = GetConfigOptionByName(name, NULL);
5527
5528         /* Convert return string to text */
5529         PG_RETURN_TEXT_P(cstring_to_text(new_value));
5530 }
5531
5532
5533 /*
5534  * Common code for DefineCustomXXXVariable subroutines: allocate the
5535  * new variable's config struct and fill in generic fields.
5536  */
5537 static struct config_generic *
5538 init_custom_variable(const char *name,
5539                                          const char *short_desc,
5540                                          const char *long_desc,
5541                                          GucContext context,
5542                                          enum config_type type,
5543                                          size_t sz)
5544 {
5545         struct config_generic *gen;
5546
5547         gen = (struct config_generic *) guc_malloc(ERROR, sz);
5548         memset(gen, 0, sz);
5549
5550         gen->name = guc_strdup(ERROR, name);
5551         gen->context = context;
5552         gen->group = CUSTOM_OPTIONS;
5553         gen->short_desc = short_desc;
5554         gen->long_desc = long_desc;
5555         gen->vartype = type;
5556
5557         return gen;
5558 }
5559
5560 /*
5561  * Common code for DefineCustomXXXVariable subroutines: insert the new
5562  * variable into the GUC variable array, replacing any placeholder.
5563  */
5564 static void
5565 define_custom_variable(struct config_generic * variable)
5566 {
5567         const char *name = variable->name;
5568         const char **nameAddr = &name;
5569         const char *value;
5570         struct config_string *pHolder;
5571         struct config_generic **res;
5572
5573         res = (struct config_generic **) bsearch((void *) &nameAddr,
5574                                                                                          (void *) guc_variables,
5575                                                                                          num_guc_variables,
5576                                                                                          sizeof(struct config_generic *),
5577                                                                                          guc_var_compare);
5578         if (res == NULL)
5579         {
5580                 /* No placeholder to replace, so just add it */
5581                 add_guc_variable(variable, ERROR);
5582                 return;
5583         }
5584
5585         /*
5586          * This better be a placeholder
5587          */
5588         if (((*res)->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
5589                 ereport(ERROR,
5590                                 (errcode(ERRCODE_INTERNAL_ERROR),
5591                                  errmsg("attempt to redefine parameter \"%s\"", name)));
5592
5593         Assert((*res)->vartype == PGC_STRING);
5594         pHolder = (struct config_string *) (*res);
5595
5596         /*
5597          * Replace the placeholder. We aren't changing the name, so no re-sorting
5598          * is necessary
5599          */
5600         *res = variable;
5601
5602         /*
5603          * Assign the string value stored in the placeholder to the real variable.
5604          *
5605          * XXX this is not really good enough --- it should be a nontransactional
5606          * assignment, since we don't want it to roll back if the current xact
5607          * fails later.
5608          */
5609         value = *pHolder->variable;
5610
5611         if (value)
5612                 set_config_option(name, value,
5613                                                   pHolder->gen.context, pHolder->gen.source,
5614                                                   GUC_ACTION_SET, true);
5615
5616         /*
5617          * Free up as much as we conveniently can of the placeholder structure
5618          * (this neglects any stack items...)
5619          */
5620         set_string_field(pHolder, pHolder->variable, NULL);
5621         set_string_field(pHolder, &pHolder->reset_val, NULL);
5622
5623         free(pHolder);
5624 }
5625
5626 void
5627 DefineCustomBoolVariable(const char *name,
5628                                                  const char *short_desc,
5629                                                  const char *long_desc,
5630                                                  bool *valueAddr,
5631                                                  GucContext context,
5632                                                  GucBoolAssignHook assign_hook,
5633                                                  GucShowHook show_hook)
5634 {
5635         struct config_bool *var;
5636
5637         var = (struct config_bool *)
5638                 init_custom_variable(name, short_desc, long_desc, context,
5639                                                          PGC_BOOL, sizeof(struct config_bool));
5640         var->variable = valueAddr;
5641         var->boot_val = *valueAddr;
5642         var->reset_val = *valueAddr;
5643         var->assign_hook = assign_hook;
5644         var->show_hook = show_hook;
5645         define_custom_variable(&var->gen);
5646 }
5647
5648 void
5649 DefineCustomIntVariable(const char *name,
5650                                                 const char *short_desc,
5651                                                 const char *long_desc,
5652                                                 int *valueAddr,
5653                                                 int minValue,
5654                                                 int maxValue,
5655                                                 GucContext context,
5656                                                 GucIntAssignHook assign_hook,
5657                                                 GucShowHook show_hook)
5658 {
5659         struct config_int *var;
5660
5661         var = (struct config_int *)
5662                 init_custom_variable(name, short_desc, long_desc, context,
5663                                                          PGC_INT, sizeof(struct config_int));
5664         var->variable = valueAddr;
5665         var->boot_val = *valueAddr;
5666         var->reset_val = *valueAddr;
5667         var->min = minValue;
5668         var->max = maxValue;
5669         var->assign_hook = assign_hook;
5670         var->show_hook = show_hook;
5671         define_custom_variable(&var->gen);
5672 }
5673
5674 void
5675 DefineCustomRealVariable(const char *name,
5676                                                  const char *short_desc,
5677                                                  const char *long_desc,
5678                                                  double *valueAddr,
5679                                                  double minValue,
5680                                                  double maxValue,
5681                                                  GucContext context,
5682                                                  GucRealAssignHook assign_hook,
5683                                                  GucShowHook show_hook)
5684 {
5685         struct config_real *var;
5686
5687         var = (struct config_real *)
5688                 init_custom_variable(name, short_desc, long_desc, context,
5689                                                          PGC_REAL, sizeof(struct config_real));
5690         var->variable = valueAddr;
5691         var->boot_val = *valueAddr;
5692         var->reset_val = *valueAddr;
5693         var->min = minValue;
5694         var->max = maxValue;
5695         var->assign_hook = assign_hook;
5696         var->show_hook = show_hook;
5697         define_custom_variable(&var->gen);
5698 }
5699
5700 void
5701 DefineCustomStringVariable(const char *name,
5702                                                    const char *short_desc,
5703                                                    const char *long_desc,
5704                                                    char **valueAddr,
5705                                                    GucContext context,
5706                                                    GucStringAssignHook assign_hook,
5707                                                    GucShowHook show_hook)
5708 {
5709         struct config_string *var;
5710
5711         var = (struct config_string *)
5712                 init_custom_variable(name, short_desc, long_desc, context,
5713                                                          PGC_STRING, sizeof(struct config_string));
5714         var->variable = valueAddr;
5715         var->boot_val = *valueAddr;
5716         /* we could probably do without strdup, but keep it like normal case */
5717         if (var->boot_val)
5718                 var->reset_val = guc_strdup(ERROR, var->boot_val);
5719         var->assign_hook = assign_hook;
5720         var->show_hook = show_hook;
5721         define_custom_variable(&var->gen);
5722 }
5723
5724 void
5725 DefineCustomEnumVariable(const char *name,
5726                                                  const char *short_desc,
5727                                                  const char *long_desc,
5728                                                  int *valueAddr,
5729                                                  const struct config_enum_entry *options,
5730                                                  GucContext context,
5731                                                  GucEnumAssignHook assign_hook,
5732                                                  GucShowHook show_hook)
5733 {
5734         struct config_enum *var;
5735
5736         var = (struct config_enum *)
5737                 init_custom_variable(name, short_desc, long_desc, context,
5738                                                          PGC_ENUM, sizeof(struct config_enum));
5739         var->variable = valueAddr;
5740         var->boot_val = *valueAddr;
5741         var->reset_val = *valueAddr;
5742         var->options = options;
5743         var->assign_hook = assign_hook;
5744         var->show_hook = show_hook;
5745         define_custom_variable(&var->gen);
5746 }
5747
5748 void
5749 EmitWarningsOnPlaceholders(const char *className)
5750 {
5751         struct config_generic **vars = guc_variables;
5752         struct config_generic **last = vars + num_guc_variables;
5753
5754         int                     nameLen = strlen(className);
5755
5756         while (vars < last)
5757         {
5758                 struct config_generic *var = *vars++;
5759
5760                 if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
5761                         strncmp(className, var->name, nameLen) == 0 &&
5762                         var->name[nameLen] == GUC_QUALIFIER_SEPARATOR)
5763                 {
5764                         ereport(INFO,
5765                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
5766                                          errmsg("unrecognized configuration parameter \"%s\"", var->name)));
5767                 }
5768         }
5769 }
5770
5771
5772 /*
5773  * SHOW command
5774  */
5775 void
5776 GetPGVariable(const char *name, DestReceiver *dest)
5777 {
5778         if (guc_name_compare(name, "all") == 0)
5779                 ShowAllGUCConfig(dest);
5780         else
5781                 ShowGUCConfigOption(name, dest);
5782 }
5783
5784 TupleDesc
5785 GetPGVariableResultDesc(const char *name)
5786 {
5787         TupleDesc       tupdesc;
5788
5789         if (guc_name_compare(name, "all") == 0)
5790         {
5791                 /* need a tuple descriptor representing three TEXT columns */
5792                 tupdesc = CreateTemplateTupleDesc(3, false);
5793                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
5794                                                    TEXTOID, -1, 0);
5795                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
5796                                                    TEXTOID, -1, 0);
5797                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
5798                                                    TEXTOID, -1, 0);
5799
5800         }
5801         else
5802         {
5803                 const char *varname;
5804
5805                 /* Get the canonical spelling of name */
5806                 (void) GetConfigOptionByName(name, &varname);
5807
5808                 /* need a tuple descriptor representing a single TEXT column */
5809                 tupdesc = CreateTemplateTupleDesc(1, false);
5810                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
5811                                                    TEXTOID, -1, 0);
5812         }
5813         return tupdesc;
5814 }
5815
5816
5817 /*
5818  * SHOW command
5819  */
5820 static void
5821 ShowGUCConfigOption(const char *name, DestReceiver *dest)
5822 {
5823         TupOutputState *tstate;
5824         TupleDesc       tupdesc;
5825         const char *varname;
5826         char       *value;
5827
5828         /* Get the value and canonical spelling of name */
5829         value = GetConfigOptionByName(name, &varname);
5830
5831         /* need a tuple descriptor representing a single TEXT column */
5832         tupdesc = CreateTemplateTupleDesc(1, false);
5833         TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
5834                                            TEXTOID, -1, 0);
5835
5836         /* prepare for projection of tuples */
5837         tstate = begin_tup_output_tupdesc(dest, tupdesc);
5838
5839         /* Send it */
5840         do_text_output_oneline(tstate, value);
5841
5842         end_tup_output(tstate);
5843 }
5844
5845 /*
5846  * SHOW ALL command
5847  */
5848 static void
5849 ShowAllGUCConfig(DestReceiver *dest)
5850 {
5851         bool            am_superuser = superuser();
5852         int                     i;
5853         TupOutputState *tstate;
5854         TupleDesc       tupdesc;
5855         char       *values[3];
5856
5857         /* need a tuple descriptor representing three TEXT columns */
5858         tupdesc = CreateTemplateTupleDesc(3, false);
5859         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
5860                                            TEXTOID, -1, 0);
5861         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
5862                                            TEXTOID, -1, 0);
5863         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
5864                                            TEXTOID, -1, 0);
5865
5866
5867         /* prepare for projection of tuples */
5868         tstate = begin_tup_output_tupdesc(dest, tupdesc);
5869
5870         for (i = 0; i < num_guc_variables; i++)
5871         {
5872                 struct config_generic *conf = guc_variables[i];
5873
5874                 if ((conf->flags & GUC_NO_SHOW_ALL) ||
5875                         ((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser))
5876                         continue;
5877
5878                 /* assign to the values array */
5879                 values[0] = (char *) conf->name;
5880                 values[1] = _ShowOption(conf, true);
5881                 values[2] = (char *) conf->short_desc;
5882
5883                 /* send it to dest */
5884                 do_tup_output(tstate, values);
5885
5886                 /* clean up */
5887                 if (values[1] != NULL)
5888                         pfree(values[1]);
5889         }
5890
5891         end_tup_output(tstate);
5892 }
5893
5894 /*
5895  * Return GUC variable value by name; optionally return canonical
5896  * form of name.  Return value is palloc'd.
5897  */
5898 char *
5899 GetConfigOptionByName(const char *name, const char **varname)
5900 {
5901         struct config_generic *record;
5902
5903         record = find_option(name, false, ERROR);
5904         if (record == NULL)
5905                 ereport(ERROR,
5906                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
5907                            errmsg("unrecognized configuration parameter \"%s\"", name)));
5908         if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
5909                 ereport(ERROR,
5910                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5911                                  errmsg("must be superuser to examine \"%s\"", name)));
5912
5913         if (varname)
5914                 *varname = record->name;
5915
5916         return _ShowOption(record, true);
5917 }
5918
5919 /*
5920  * Return GUC variable value by variable number; optionally return canonical
5921  * form of name.  Return value is palloc'd.
5922  */
5923 void
5924 GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
5925 {
5926         char            buffer[256];
5927         struct config_generic *conf;
5928
5929         /* check requested variable number valid */
5930         Assert((varnum >= 0) && (varnum < num_guc_variables));
5931
5932         conf = guc_variables[varnum];
5933
5934         if (noshow)
5935         {
5936                 if ((conf->flags & GUC_NO_SHOW_ALL) ||
5937                         ((conf->flags & GUC_SUPERUSER_ONLY) && !superuser()))
5938                         *noshow = true;
5939                 else
5940                         *noshow = false;
5941         }
5942
5943         /* first get the generic attributes */
5944
5945         /* name */
5946         values[0] = conf->name;
5947
5948         /* setting : use _ShowOption in order to avoid duplicating the logic */
5949         values[1] = _ShowOption(conf, false);
5950
5951         /* unit */
5952         if (conf->vartype == PGC_INT)
5953         {
5954                 static char buf[8];
5955
5956                 switch (conf->flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME))
5957                 {
5958                         case GUC_UNIT_KB:
5959                                 values[2] = "kB";
5960                                 break;
5961                         case GUC_UNIT_BLOCKS:
5962                                 snprintf(buf, sizeof(buf), "%dkB", BLCKSZ / 1024);
5963                                 values[2] = buf;
5964                                 break;
5965                         case GUC_UNIT_XBLOCKS:
5966                                 snprintf(buf, sizeof(buf), "%dkB", XLOG_BLCKSZ / 1024);
5967                                 values[2] = buf;
5968                                 break;
5969                         case GUC_UNIT_MS:
5970                                 values[2] = "ms";
5971                                 break;
5972                         case GUC_UNIT_S:
5973                                 values[2] = "s";
5974                                 break;
5975                         case GUC_UNIT_MIN:
5976                                 values[2] = "min";
5977                                 break;
5978                         default:
5979                                 values[2] = "";
5980                                 break;
5981                 }
5982         }
5983         else
5984                 values[2] = NULL;
5985
5986         /* group */
5987         values[3] = config_group_names[conf->group];
5988
5989         /* short_desc */
5990         values[4] = conf->short_desc;
5991
5992         /* extra_desc */
5993         values[5] = conf->long_desc;
5994
5995         /* context */
5996         values[6] = GucContext_Names[conf->context];
5997
5998         /* vartype */
5999         values[7] = config_type_names[conf->vartype];
6000
6001         /* source */
6002         values[8] = GucSource_Names[conf->source];
6003
6004         /* now get the type specifc attributes */
6005         switch (conf->vartype)
6006         {
6007                 case PGC_BOOL:
6008                         {
6009                                 /* min_val */
6010                                 values[9] = NULL;
6011
6012                                 /* max_val */
6013                                 values[10] = NULL;
6014
6015                                 /* enumvals */
6016                                 values[11] = NULL;
6017                         }
6018                         break;
6019
6020                 case PGC_INT:
6021                         {
6022                                 struct config_int *lconf = (struct config_int *) conf;
6023
6024                                 /* min_val */
6025                                 snprintf(buffer, sizeof(buffer), "%d", lconf->min);
6026                                 values[9] = pstrdup(buffer);
6027
6028                                 /* max_val */
6029                                 snprintf(buffer, sizeof(buffer), "%d", lconf->max);
6030                                 values[10] = pstrdup(buffer);
6031
6032                                 /* enumvals */
6033                                 values[11] = NULL;
6034                         }
6035                         break;
6036
6037                 case PGC_REAL:
6038                         {
6039                                 struct config_real *lconf = (struct config_real *) conf;
6040
6041                                 /* min_val */
6042                                 snprintf(buffer, sizeof(buffer), "%g", lconf->min);
6043                                 values[9] = pstrdup(buffer);
6044
6045                                 /* max_val */
6046                                 snprintf(buffer, sizeof(buffer), "%g", lconf->max);
6047                                 values[10] = pstrdup(buffer);
6048
6049                                 /* enumvals */
6050                                 values[11] = NULL;
6051                         }
6052                         break;
6053
6054                 case PGC_STRING:
6055                         {
6056                                 /* min_val */
6057                                 values[9] = NULL;
6058
6059                                 /* max_val */
6060                                 values[10] = NULL;
6061
6062                                 /* enumvals */
6063                                 values[11] = NULL;
6064                         }
6065                         break;
6066
6067                 case PGC_ENUM:
6068                         {
6069                                 /* min_val */
6070                                 values[9] = NULL;
6071
6072                                 /* max_val */
6073                                 values[10] = NULL;
6074
6075                                 /* enumvals */
6076                                 values[11] = config_enum_get_options((struct config_enum *) conf, "", "");
6077                         }
6078                         break;
6079
6080                 default:
6081                         {
6082                                 /*
6083                                  * should never get here, but in case we do, set 'em to NULL
6084                                  */
6085
6086                                 /* min_val */
6087                                 values[9] = NULL;
6088
6089                                 /* max_val */
6090                                 values[10] = NULL;
6091
6092                                 /* enumvals */
6093                                 values[11] = NULL;
6094                         }
6095                         break;
6096         }
6097 }
6098
6099 /*
6100  * Return the total number of GUC variables
6101  */
6102 int
6103 GetNumConfigOptions(void)
6104 {
6105         return num_guc_variables;
6106 }
6107
6108 /*
6109  * show_config_by_name - equiv to SHOW X command but implemented as
6110  * a function.
6111  */
6112 Datum
6113 show_config_by_name(PG_FUNCTION_ARGS)
6114 {
6115         char       *varname;
6116         char       *varval;
6117
6118         /* Get the GUC variable name */
6119         varname = TextDatumGetCString(PG_GETARG_DATUM(0));
6120
6121         /* Get the value */
6122         varval = GetConfigOptionByName(varname, NULL);
6123
6124         /* Convert to text */
6125         PG_RETURN_TEXT_P(cstring_to_text(varval));
6126 }
6127
6128 /*
6129  * show_all_settings - equiv to SHOW ALL command but implemented as
6130  * a Table Function.
6131  */
6132 #define NUM_PG_SETTINGS_ATTS    12
6133
6134 Datum
6135 show_all_settings(PG_FUNCTION_ARGS)
6136 {
6137         FuncCallContext *funcctx;
6138         TupleDesc       tupdesc;
6139         int                     call_cntr;
6140         int                     max_calls;
6141         AttInMetadata *attinmeta;
6142         MemoryContext oldcontext;
6143
6144         /* stuff done only on the first call of the function */
6145         if (SRF_IS_FIRSTCALL())
6146         {
6147                 /* create a function context for cross-call persistence */
6148                 funcctx = SRF_FIRSTCALL_INIT();
6149
6150                 /*
6151                  * switch to memory context appropriate for multiple function calls
6152                  */
6153                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
6154
6155                 /*
6156                  * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
6157                  * of the appropriate types
6158                  */
6159                 tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS, false);
6160                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
6161                                                    TEXTOID, -1, 0);
6162                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
6163                                                    TEXTOID, -1, 0);
6164                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit",
6165                                                    TEXTOID, -1, 0);
6166                 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category",
6167                                                    TEXTOID, -1, 0);
6168                 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc",
6169                                                    TEXTOID, -1, 0);
6170                 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc",
6171                                                    TEXTOID, -1, 0);
6172                 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context",
6173                                                    TEXTOID, -1, 0);
6174                 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype",
6175                                                    TEXTOID, -1, 0);
6176                 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source",
6177                                                    TEXTOID, -1, 0);
6178                 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val",
6179                                                    TEXTOID, -1, 0);
6180                 TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
6181                                                    TEXTOID, -1, 0);
6182                 TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
6183                                                    TEXTOID, -1, 0);
6184
6185                 /*
6186                  * Generate attribute metadata needed later to produce tuples from raw
6187                  * C strings
6188                  */
6189                 attinmeta = TupleDescGetAttInMetadata(tupdesc);
6190                 funcctx->attinmeta = attinmeta;
6191
6192                 /* total number of tuples to be returned */
6193                 funcctx->max_calls = GetNumConfigOptions();
6194
6195                 MemoryContextSwitchTo(oldcontext);
6196         }
6197
6198         /* stuff done on every call of the function */
6199         funcctx = SRF_PERCALL_SETUP();
6200
6201         call_cntr = funcctx->call_cntr;
6202         max_calls = funcctx->max_calls;
6203         attinmeta = funcctx->attinmeta;
6204
6205         if (call_cntr < max_calls)      /* do when there is more left to send */
6206         {
6207                 char       *values[NUM_PG_SETTINGS_ATTS];
6208                 bool            noshow;
6209                 HeapTuple       tuple;
6210                 Datum           result;
6211
6212                 /*
6213                  * Get the next visible GUC variable name and value
6214                  */
6215                 do
6216                 {
6217                         GetConfigOptionByNum(call_cntr, (const char **) values, &noshow);
6218                         if (noshow)
6219                         {
6220                                 /* bump the counter and get the next config setting */
6221                                 call_cntr = ++funcctx->call_cntr;
6222
6223                                 /* make sure we haven't gone too far now */
6224                                 if (call_cntr >= max_calls)
6225                                         SRF_RETURN_DONE(funcctx);
6226                         }
6227                 } while (noshow);
6228
6229                 /* build a tuple */
6230                 tuple = BuildTupleFromCStrings(attinmeta, values);
6231
6232                 /* make the tuple into a datum */
6233                 result = HeapTupleGetDatum(tuple);
6234
6235                 SRF_RETURN_NEXT(funcctx, result);
6236         }
6237         else
6238         {
6239                 /* do when there is no more left */
6240                 SRF_RETURN_DONE(funcctx);
6241         }
6242 }
6243
6244 static char *
6245 _ShowOption(struct config_generic * record, bool use_units)
6246 {
6247         char            buffer[256];
6248         const char *val;
6249
6250         switch (record->vartype)
6251         {
6252                 case PGC_BOOL:
6253                         {
6254                                 struct config_bool *conf = (struct config_bool *) record;
6255
6256                                 if (conf->show_hook)
6257                                         val = (*conf->show_hook) ();
6258                                 else
6259                                         val = *conf->variable ? "on" : "off";
6260                         }
6261                         break;
6262
6263                 case PGC_INT:
6264                         {
6265                                 struct config_int *conf = (struct config_int *) record;
6266
6267                                 if (conf->show_hook)
6268                                         val = (*conf->show_hook) ();
6269                                 else
6270                                 {
6271                                         char            unit[4];
6272                                         int                     result = *conf->variable;
6273
6274                                         if (use_units && result > 0 && (record->flags & GUC_UNIT_MEMORY))
6275                                         {
6276                                                 switch (record->flags & GUC_UNIT_MEMORY)
6277                                                 {
6278                                                         case GUC_UNIT_BLOCKS:
6279                                                                 result *= BLCKSZ / 1024;
6280                                                                 break;
6281                                                         case GUC_UNIT_XBLOCKS:
6282                                                                 result *= XLOG_BLCKSZ / 1024;
6283                                                                 break;
6284                                                 }
6285
6286                                                 if (result % KB_PER_GB == 0)
6287                                                 {
6288                                                         result /= KB_PER_GB;
6289                                                         strcpy(unit, "GB");
6290                                                 }
6291                                                 else if (result % KB_PER_MB == 0)
6292                                                 {
6293                                                         result /= KB_PER_MB;
6294                                                         strcpy(unit, "MB");
6295                                                 }
6296                                                 else
6297                                                 {
6298                                                         strcpy(unit, "kB");
6299                                                 }
6300                                         }
6301                                         else if (use_units && result > 0 && (record->flags & GUC_UNIT_TIME))
6302                                         {
6303                                                 switch (record->flags & GUC_UNIT_TIME)
6304                                                 {
6305                                                         case GUC_UNIT_S:
6306                                                                 result *= MS_PER_S;
6307                                                                 break;
6308                                                         case GUC_UNIT_MIN:
6309                                                                 result *= MS_PER_MIN;
6310                                                                 break;
6311                                                 }
6312
6313                                                 if (result % MS_PER_D == 0)
6314                                                 {
6315                                                         result /= MS_PER_D;
6316                                                         strcpy(unit, "d");
6317                                                 }
6318                                                 else if (result % MS_PER_H == 0)
6319                                                 {
6320                                                         result /= MS_PER_H;
6321                                                         strcpy(unit, "h");
6322                                                 }
6323                                                 else if (result % MS_PER_MIN == 0)
6324                                                 {
6325                                                         result /= MS_PER_MIN;
6326                                                         strcpy(unit, "min");
6327                                                 }
6328                                                 else if (result % MS_PER_S == 0)
6329                                                 {
6330                                                         result /= MS_PER_S;
6331                                                         strcpy(unit, "s");
6332                                                 }
6333                                                 else
6334                                                 {
6335                                                         strcpy(unit, "ms");
6336                                                 }
6337                                         }
6338                                         else
6339                                                 strcpy(unit, "");
6340
6341                                         snprintf(buffer, sizeof(buffer), "%d%s",
6342                                                          (int) result, unit);
6343                                         val = buffer;
6344                                 }
6345                         }
6346                         break;
6347
6348                 case PGC_REAL:
6349                         {
6350                                 struct config_real *conf = (struct config_real *) record;
6351
6352                                 if (conf->show_hook)
6353                                         val = (*conf->show_hook) ();
6354                                 else
6355                                 {
6356                                         snprintf(buffer, sizeof(buffer), "%g",
6357                                                          *conf->variable);
6358                                         val = buffer;
6359                                 }
6360                         }
6361                         break;
6362
6363                 case PGC_STRING:
6364                         {
6365                                 struct config_string *conf = (struct config_string *) record;
6366
6367                                 if (conf->show_hook)
6368                                         val = (*conf->show_hook) ();
6369                                 else if (*conf->variable && **conf->variable)
6370                                         val = *conf->variable;
6371                                 else
6372                                         val = "";
6373                         }
6374                         break;
6375
6376                 case PGC_ENUM:
6377                         {
6378                                 struct config_enum *conf = (struct config_enum *) record;
6379
6380                                 if(conf->show_hook)
6381                                         val = (*conf->show_hook) ();
6382                                 else
6383                                         val = config_enum_lookup_by_value(conf, *conf->variable);
6384                         }
6385                         break;
6386
6387                 default:
6388                         /* just to keep compiler quiet */
6389                         val = "???";
6390                         break;
6391         }
6392
6393         return pstrdup(val);
6394 }
6395
6396
6397 /*
6398  * Attempt (badly) to detect if a proposed new GUC setting is the same
6399  * as the current value.
6400  *
6401  * XXX this does not really work because it doesn't account for the
6402  * effects of canonicalization of string values by assign_hooks.
6403  */
6404 static bool
6405 is_newvalue_equal(struct config_generic * record, const char *newvalue)
6406 {
6407         /* newvalue == NULL isn't supported */
6408         Assert(newvalue != NULL);
6409
6410         switch (record->vartype)
6411         {
6412                 case PGC_BOOL:
6413                         {
6414                                 struct config_bool *conf = (struct config_bool *) record;
6415                                 bool            newval;
6416
6417                                 return parse_bool(newvalue, &newval)
6418                                         && *conf->variable == newval;
6419                         }
6420                 case PGC_INT:
6421                         {
6422                                 struct config_int *conf = (struct config_int *) record;
6423                                 int                     newval;
6424
6425                                 return parse_int(newvalue, &newval, record->flags, NULL)
6426                                         && *conf->variable == newval;
6427                         }
6428                 case PGC_REAL:
6429                         {
6430                                 struct config_real *conf = (struct config_real *) record;
6431                                 double          newval;
6432
6433                                 return parse_real(newvalue, &newval)
6434                                         && *conf->variable == newval;
6435                         }
6436                 case PGC_STRING:
6437                         {
6438                                 struct config_string *conf = (struct config_string *) record;
6439
6440                                 return *conf->variable != NULL &&
6441                                         strcmp(*conf->variable, newvalue) == 0;
6442                         }
6443
6444                 case PGC_ENUM:
6445                         {
6446                                 struct config_enum *conf = (struct config_enum *) record;
6447                                 int                     newval;
6448
6449                                 return config_enum_lookup_by_name(conf, newvalue, &newval)
6450                                         && *conf->variable == newval;
6451                         }
6452         }
6453
6454         return false;
6455 }
6456
6457
6458 #ifdef EXEC_BACKEND
6459
6460 /*
6461  *      This routine dumps out all non-default GUC options into a binary
6462  *      file that is read by all exec'ed backends.  The format is:
6463  *
6464  *              variable name, string, null terminated
6465  *              variable value, string, null terminated
6466  *              variable source, integer
6467  */
6468 void
6469 write_nondefault_variables(GucContext context)
6470 {
6471         int                     i;
6472         int                     elevel;
6473         FILE       *fp;
6474
6475         Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
6476
6477         elevel = (context == PGC_SIGHUP) ? LOG : ERROR;
6478
6479         /*
6480          * Open file
6481          */
6482         fp = AllocateFile(CONFIG_EXEC_PARAMS_NEW, "w");
6483         if (!fp)
6484         {
6485                 ereport(elevel,
6486                                 (errcode_for_file_access(),
6487                                  errmsg("could not write to file \"%s\": %m",
6488                                                 CONFIG_EXEC_PARAMS_NEW)));
6489                 return;
6490         }
6491
6492         for (i = 0; i < num_guc_variables; i++)
6493         {
6494                 struct config_generic *gconf = guc_variables[i];
6495
6496                 if (gconf->source != PGC_S_DEFAULT)
6497                 {
6498                         fprintf(fp, "%s", gconf->name);
6499                         fputc(0, fp);
6500
6501                         switch (gconf->vartype)
6502                         {
6503                                 case PGC_BOOL:
6504                                         {
6505                                                 struct config_bool *conf = (struct config_bool *) gconf;
6506
6507                                                 if (*conf->variable == 0)
6508                                                         fprintf(fp, "false");
6509                                                 else
6510                                                         fprintf(fp, "true");
6511                                         }
6512                                         break;
6513
6514                                 case PGC_INT:
6515                                         {
6516                                                 struct config_int *conf = (struct config_int *) gconf;
6517
6518                                                 fprintf(fp, "%d", *conf->variable);
6519                                         }
6520                                         break;
6521
6522                                 case PGC_REAL:
6523                                         {
6524                                                 struct config_real *conf = (struct config_real *) gconf;
6525
6526                                                 /* Could lose precision here? */
6527                                                 fprintf(fp, "%f", *conf->variable);
6528                                         }
6529                                         break;
6530
6531                                 case PGC_STRING:
6532                                         {
6533                                                 struct config_string *conf = (struct config_string *) gconf;
6534
6535                                                 fprintf(fp, "%s", *conf->variable);
6536                                         }
6537                                         break;
6538
6539                                 case PGC_ENUM:
6540                                         {
6541                                                 struct config_enum *conf = (struct config_enum *) gconf;
6542                                                 
6543                                                 fprintf(fp, "%s", config_enum_lookup_by_value(conf, *conf->variable));
6544                                         }
6545                                         break;
6546                         }
6547
6548                         fputc(0, fp);
6549
6550                         fwrite(&gconf->source, sizeof(gconf->source), 1, fp);
6551                 }
6552         }
6553
6554         if (FreeFile(fp))
6555         {
6556                 ereport(elevel,
6557                                 (errcode_for_file_access(),
6558                                  errmsg("could not write to file \"%s\": %m",
6559                                                 CONFIG_EXEC_PARAMS_NEW)));
6560                 return;
6561         }
6562
6563         /*
6564          * Put new file in place.  This could delay on Win32, but we don't hold
6565          * any exclusive locks.
6566          */
6567         rename(CONFIG_EXEC_PARAMS_NEW, CONFIG_EXEC_PARAMS);
6568 }
6569
6570
6571 /*
6572  *      Read string, including null byte from file
6573  *
6574  *      Return NULL on EOF and nothing read
6575  */
6576 static char *
6577 read_string_with_null(FILE *fp)
6578 {
6579         int                     i = 0,
6580                                 ch,
6581                                 maxlen = 256;
6582         char       *str = NULL;
6583
6584         do
6585         {
6586                 if ((ch = fgetc(fp)) == EOF)
6587                 {
6588                         if (i == 0)
6589                                 return NULL;
6590                         else
6591                                 elog(FATAL, "invalid format of exec config params file");
6592                 }
6593                 if (i == 0)
6594                         str = guc_malloc(FATAL, maxlen);
6595                 else if (i == maxlen)
6596                         str = guc_realloc(FATAL, str, maxlen *= 2);
6597                 str[i++] = ch;
6598         } while (ch != 0);
6599
6600         return str;
6601 }
6602
6603
6604 /*
6605  *      This routine loads a previous postmaster dump of its non-default
6606  *      settings.
6607  */
6608 void
6609 read_nondefault_variables(void)
6610 {
6611         FILE       *fp;
6612         char       *varname,
6613                            *varvalue;
6614         int                     varsource;
6615
6616         /*
6617          * Open file
6618          */
6619         fp = AllocateFile(CONFIG_EXEC_PARAMS, "r");
6620         if (!fp)
6621         {
6622                 /* File not found is fine */
6623                 if (errno != ENOENT)
6624                         ereport(FATAL,
6625                                         (errcode_for_file_access(),
6626                                          errmsg("could not read from file \"%s\": %m",
6627                                                         CONFIG_EXEC_PARAMS)));
6628                 return;
6629         }
6630
6631         for (;;)
6632         {
6633                 struct config_generic *record;
6634
6635                 if ((varname = read_string_with_null(fp)) == NULL)
6636                         break;
6637
6638                 if ((record = find_option(varname, true, FATAL)) == NULL)
6639                         elog(FATAL, "failed to locate variable %s in exec config params file", varname);
6640                 if ((varvalue = read_string_with_null(fp)) == NULL)
6641                         elog(FATAL, "invalid format of exec config params file");
6642                 if (fread(&varsource, sizeof(varsource), 1, fp) == 0)
6643                         elog(FATAL, "invalid format of exec config params file");
6644
6645                 (void) set_config_option(varname, varvalue, record->context,
6646                                                                  varsource, GUC_ACTION_SET, true);
6647                 free(varname);
6648                 free(varvalue);
6649         }
6650
6651         FreeFile(fp);
6652 }
6653 #endif   /* EXEC_BACKEND */
6654
6655
6656 /*
6657  * A little "long argument" simulation, although not quite GNU
6658  * compliant. Takes a string of the form "some-option=some value" and
6659  * returns name = "some_option" and value = "some value" in malloc'ed
6660  * storage. Note that '-' is converted to '_' in the option name. If
6661  * there is no '=' in the input string then value will be NULL.
6662  */
6663 void
6664 ParseLongOption(const char *string, char **name, char **value)
6665 {
6666         size_t          equal_pos;
6667         char       *cp;
6668
6669         AssertArg(string);
6670         AssertArg(name);
6671         AssertArg(value);
6672
6673         equal_pos = strcspn(string, "=");
6674
6675         if (string[equal_pos] == '=')
6676         {
6677                 *name = guc_malloc(FATAL, equal_pos + 1);
6678                 strlcpy(*name, string, equal_pos + 1);
6679
6680                 *value = guc_strdup(FATAL, &string[equal_pos + 1]);
6681         }
6682         else
6683         {
6684                 /* no equal sign in string */
6685                 *name = guc_strdup(FATAL, string);
6686                 *value = NULL;
6687         }
6688
6689         for (cp = *name; *cp; cp++)
6690                 if (*cp == '-')
6691                         *cp = '_';
6692 }
6693
6694
6695 /*
6696  * Handle options fetched from pg_database.datconfig, pg_authid.rolconfig,
6697  * pg_proc.proconfig, etc.      Caller must specify proper context/source/action.
6698  *
6699  * The array parameter must be an array of TEXT (it must not be NULL).
6700  */
6701 void
6702 ProcessGUCArray(ArrayType *array,
6703                                 GucContext context, GucSource source, GucAction action)
6704 {
6705         int                     i;
6706
6707         Assert(array != NULL);
6708         Assert(ARR_ELEMTYPE(array) == TEXTOID);
6709         Assert(ARR_NDIM(array) == 1);
6710         Assert(ARR_LBOUND(array)[0] == 1);
6711
6712         for (i = 1; i <= ARR_DIMS(array)[0]; i++)
6713         {
6714                 Datum           d;
6715                 bool            isnull;
6716                 char       *s;
6717                 char       *name;
6718                 char       *value;
6719
6720                 d = array_ref(array, 1, &i,
6721                                           -1 /* varlenarray */ ,
6722                                           -1 /* TEXT's typlen */ ,
6723                                           false /* TEXT's typbyval */ ,
6724                                           'i' /* TEXT's typalign */ ,
6725                                           &isnull);
6726
6727                 if (isnull)
6728                         continue;
6729
6730                 s = TextDatumGetCString(d);
6731
6732                 ParseLongOption(s, &name, &value);
6733                 if (!value)
6734                 {
6735                         ereport(WARNING,
6736                                         (errcode(ERRCODE_SYNTAX_ERROR),
6737                                          errmsg("could not parse setting for parameter \"%s\"",
6738                                                         name)));
6739                         free(name);
6740                         continue;
6741                 }
6742
6743                 (void) set_config_option(name, value, context, source, action, true);
6744
6745                 free(name);
6746                 if (value)
6747                         free(value);
6748         }
6749 }
6750
6751
6752 /*
6753  * Add an entry to an option array.  The array parameter may be NULL
6754  * to indicate the current table entry is NULL.
6755  */
6756 ArrayType *
6757 GUCArrayAdd(ArrayType *array, const char *name, const char *value)
6758 {
6759         const char *varname;
6760         Datum           datum;
6761         char       *newval;
6762         ArrayType  *a;
6763
6764         Assert(name);
6765         Assert(value);
6766
6767         /* test if the option is valid */
6768         set_config_option(name, value,
6769                                           superuser() ? PGC_SUSET : PGC_USERSET,
6770                                           PGC_S_TEST, GUC_ACTION_SET, false);
6771
6772         /* convert name to canonical spelling, so we can use plain strcmp */
6773         (void) GetConfigOptionByName(name, &varname);
6774         name = varname;
6775
6776         newval = palloc(strlen(name) + 1 + strlen(value) + 1);
6777         sprintf(newval, "%s=%s", name, value);
6778         datum = CStringGetTextDatum(newval);
6779
6780         if (array)
6781         {
6782                 int                     index;
6783                 bool            isnull;
6784                 int                     i;
6785
6786                 Assert(ARR_ELEMTYPE(array) == TEXTOID);
6787                 Assert(ARR_NDIM(array) == 1);
6788                 Assert(ARR_LBOUND(array)[0] == 1);
6789
6790                 index = ARR_DIMS(array)[0] + 1; /* add after end */
6791
6792                 for (i = 1; i <= ARR_DIMS(array)[0]; i++)
6793                 {
6794                         Datum           d;
6795                         char       *current;
6796
6797                         d = array_ref(array, 1, &i,
6798                                                   -1 /* varlenarray */ ,
6799                                                   -1 /* TEXT's typlen */ ,
6800                                                   false /* TEXT's typbyval */ ,
6801                                                   'i' /* TEXT's typalign */ ,
6802                                                   &isnull);
6803                         if (isnull)
6804                                 continue;
6805                         current = TextDatumGetCString(d);
6806                         if (strncmp(current, newval, strlen(name) + 1) == 0)
6807                         {
6808                                 index = i;
6809                                 break;
6810                         }
6811                 }
6812
6813                 a = array_set(array, 1, &index,
6814                                           datum,
6815                                           false,
6816                                           -1 /* varlena array */ ,
6817                                           -1 /* TEXT's typlen */ ,
6818                                           false /* TEXT's typbyval */ ,
6819                                           'i' /* TEXT's typalign */ );
6820         }
6821         else
6822                 a = construct_array(&datum, 1,
6823                                                         TEXTOID,
6824                                                         -1, false, 'i');
6825
6826         return a;
6827 }
6828
6829
6830 /*
6831  * Delete an entry from an option array.  The array parameter may be NULL
6832  * to indicate the current table entry is NULL.  Also, if the return value
6833  * is NULL then a null should be stored.
6834  */
6835 ArrayType *
6836 GUCArrayDelete(ArrayType *array, const char *name)
6837 {
6838         const char *varname;
6839         ArrayType  *newarray;
6840         int                     i;
6841         int                     index;
6842
6843         Assert(name);
6844
6845         /* test if the option is valid */
6846         set_config_option(name, NULL,
6847                                           superuser() ? PGC_SUSET : PGC_USERSET,
6848                                           PGC_S_TEST, GUC_ACTION_SET, false);
6849
6850         /* convert name to canonical spelling, so we can use plain strcmp */
6851         (void) GetConfigOptionByName(name, &varname);
6852         name = varname;
6853
6854         /* if array is currently null, then surely nothing to delete */
6855         if (!array)
6856                 return NULL;
6857
6858         newarray = NULL;
6859         index = 1;
6860
6861         for (i = 1; i <= ARR_DIMS(array)[0]; i++)
6862         {
6863                 Datum           d;
6864                 char       *val;
6865                 bool            isnull;
6866
6867                 d = array_ref(array, 1, &i,
6868                                           -1 /* varlenarray */ ,
6869                                           -1 /* TEXT's typlen */ ,
6870                                           false /* TEXT's typbyval */ ,
6871                                           'i' /* TEXT's typalign */ ,
6872                                           &isnull);
6873                 if (isnull)
6874                         continue;
6875                 val = TextDatumGetCString(d);
6876
6877                 /* ignore entry if it's what we want to delete */
6878                 if (strncmp(val, name, strlen(name)) == 0
6879                         && val[strlen(name)] == '=')
6880                         continue;
6881
6882                 /* else add it to the output array */
6883                 if (newarray)
6884                 {
6885                         newarray = array_set(newarray, 1, &index,
6886                                                                  d,
6887                                                                  false,
6888                                                                  -1 /* varlenarray */ ,
6889                                                                  -1 /* TEXT's typlen */ ,
6890                                                                  false /* TEXT's typbyval */ ,
6891                                                                  'i' /* TEXT's typalign */ );
6892                 }
6893                 else
6894                         newarray = construct_array(&d, 1,
6895                                                                            TEXTOID,
6896                                                                            -1, false, 'i');
6897
6898                 index++;
6899         }
6900
6901         return newarray;
6902 }
6903
6904
6905 /*
6906  * assign_hook and show_hook subroutines
6907  */
6908
6909 static const char *
6910 assign_log_destination(const char *value, bool doit, GucSource source)
6911 {
6912         char       *rawstring;
6913         List       *elemlist;
6914         ListCell   *l;
6915         int                     newlogdest = 0;
6916
6917         /* Need a modifiable copy of string */
6918         rawstring = pstrdup(value);
6919
6920         /* Parse string into list of identifiers */
6921         if (!SplitIdentifierString(rawstring, ',', &elemlist))
6922         {
6923                 /* syntax error in list */
6924                 pfree(rawstring);
6925                 list_free(elemlist);
6926                 ereport(GUC_complaint_elevel(source),
6927                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6928                         errmsg("invalid list syntax for parameter \"log_destination\"")));
6929                 return NULL;
6930         }
6931
6932         foreach(l, elemlist)
6933         {
6934                 char       *tok = (char *) lfirst(l);
6935
6936                 if (pg_strcasecmp(tok, "stderr") == 0)
6937                         newlogdest |= LOG_DESTINATION_STDERR;
6938                 else if (pg_strcasecmp(tok, "csvlog") == 0)
6939                         newlogdest |= LOG_DESTINATION_CSVLOG;
6940 #ifdef HAVE_SYSLOG
6941                 else if (pg_strcasecmp(tok, "syslog") == 0)
6942                         newlogdest |= LOG_DESTINATION_SYSLOG;
6943 #endif
6944 #ifdef WIN32
6945                 else if (pg_strcasecmp(tok, "eventlog") == 0)
6946                         newlogdest |= LOG_DESTINATION_EVENTLOG;
6947 #endif
6948                 else
6949                 {
6950                         ereport(GUC_complaint_elevel(source),
6951                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6952                                   errmsg("unrecognized \"log_destination\" key word: \"%s\"",
6953                                                  tok)));
6954                         pfree(rawstring);
6955                         list_free(elemlist);
6956                         return NULL;
6957                 }
6958         }
6959
6960         if (doit)
6961                 Log_destination = newlogdest;
6962
6963         pfree(rawstring);
6964         list_free(elemlist);
6965
6966         return value;
6967 }
6968
6969 #ifdef HAVE_SYSLOG
6970
6971 static bool
6972 assign_syslog_facility(int newval, bool doit, GucSource source)
6973 {
6974         if (doit)
6975                 set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
6976                                                           newval);
6977
6978         return true;
6979 }
6980
6981 static const char *
6982 assign_syslog_ident(const char *ident, bool doit, GucSource source)
6983 {
6984         if (doit)
6985                 set_syslog_parameters(ident, syslog_facility);
6986
6987         return ident;
6988 }
6989 #endif   /* HAVE_SYSLOG */
6990
6991
6992 static bool
6993 assign_session_replication_role(int newval, bool doit, GucSource source)
6994 {
6995         /*
6996          * Must flush the plan cache when changing replication role; but don't
6997          * flush unnecessarily.
6998          */
6999         if (doit && SessionReplicationRole != newval)
7000         {
7001                 ResetPlanCache();
7002         }
7003
7004         return true;
7005 }
7006
7007 static const char *
7008 show_num_temp_buffers(void)
7009 {
7010         /*
7011          * We show the GUC var until local buffers have been initialized, and
7012          * NLocBuffer afterwards.
7013          */
7014         static char nbuf[32];
7015
7016         sprintf(nbuf, "%d", NLocBuffer ? NLocBuffer : num_temp_buffers);
7017         return nbuf;
7018 }
7019
7020 static bool
7021 assign_phony_autocommit(bool newval, bool doit, GucSource source)
7022 {
7023         if (!newval)
7024         {
7025                 ereport(GUC_complaint_elevel(source),
7026                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7027                                  errmsg("SET AUTOCOMMIT TO OFF is no longer supported")));
7028                 return false;
7029         }
7030         return true;
7031 }
7032
7033 static const char *
7034 assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
7035 {
7036         /*
7037          * Check syntax. newval must be a comma separated list of identifiers.
7038          * Whitespace is allowed but removed from the result.
7039          */
7040         bool            hasSpaceAfterToken = false;
7041         const char *cp = newval;
7042         int                     symLen = 0;
7043         char            c;
7044         StringInfoData buf;
7045
7046         initStringInfo(&buf);
7047         while ((c = *cp++) != '\0')
7048         {
7049                 if (isspace((unsigned char) c))
7050                 {
7051                         if (symLen > 0)
7052                                 hasSpaceAfterToken = true;
7053                         continue;
7054                 }
7055
7056                 if (c == ',')
7057                 {
7058                         if (symLen > 0)         /* terminate identifier */
7059                         {
7060                                 appendStringInfoChar(&buf, ',');
7061                                 symLen = 0;
7062                         }
7063                         hasSpaceAfterToken = false;
7064                         continue;
7065                 }
7066
7067                 if (hasSpaceAfterToken || !isalnum((unsigned char) c))
7068                 {
7069                         /*
7070                          * Syntax error due to token following space after token or non
7071                          * alpha numeric character
7072                          */
7073                         pfree(buf.data);
7074                         return NULL;
7075                 }
7076                 appendStringInfoChar(&buf, c);
7077                 symLen++;
7078         }
7079
7080         /* Remove stray ',' at end */
7081         if (symLen == 0 && buf.len > 0)
7082                 buf.data[--buf.len] = '\0';
7083
7084         /* GUC wants the result malloc'd */
7085         newval = guc_strdup(LOG, buf.data);
7086
7087         pfree(buf.data);
7088         return newval;
7089 }
7090
7091 static bool
7092 assign_debug_assertions(bool newval, bool doit, GucSource source)
7093 {
7094 #ifndef USE_ASSERT_CHECKING
7095         if (newval)
7096         {
7097                 ereport(GUC_complaint_elevel(source),
7098                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7099                            errmsg("assertion checking is not supported by this build")));
7100                 return false;
7101         }
7102 #endif
7103         return true;
7104 }
7105
7106 static bool
7107 assign_ssl(bool newval, bool doit, GucSource source)
7108 {
7109 #ifndef USE_SSL
7110         if (newval)
7111         {
7112                 ereport(GUC_complaint_elevel(source),
7113                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7114                                  errmsg("SSL is not supported by this build")));
7115                 return false;
7116         }
7117 #endif
7118         return true;
7119 }
7120
7121 static bool
7122 assign_stage_log_stats(bool newval, bool doit, GucSource source)
7123 {
7124         if (newval && log_statement_stats)
7125         {
7126                 ereport(GUC_complaint_elevel(source),
7127                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7128                                  errmsg("cannot enable parameter when \"log_statement_stats\" is true")));
7129                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
7130                 if (source != PGC_S_OVERRIDE)
7131                         return false;
7132         }
7133         return true;
7134 }
7135
7136 static bool
7137 assign_log_stats(bool newval, bool doit, GucSource source)
7138 {
7139         if (newval &&
7140                 (log_parser_stats || log_planner_stats || log_executor_stats))
7141         {
7142                 ereport(GUC_complaint_elevel(source),
7143                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7144                                  errmsg("cannot enable \"log_statement_stats\" when "
7145                                                 "\"log_parser_stats\", \"log_planner_stats\", "
7146                                                 "or \"log_executor_stats\" is true")));
7147                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
7148                 if (source != PGC_S_OVERRIDE)
7149                         return false;
7150         }
7151         return true;
7152 }
7153
7154 static bool
7155 assign_transaction_read_only(bool newval, bool doit, GucSource source)
7156 {
7157         /* Can't go to r/w mode inside a r/o transaction */
7158         if (newval == false && XactReadOnly && IsSubTransaction())
7159         {
7160                 ereport(GUC_complaint_elevel(source),
7161                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7162                                  errmsg("cannot set transaction read-write mode inside a read-only transaction")));
7163                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
7164                 if (source != PGC_S_OVERRIDE)
7165                         return false;
7166         }
7167         return true;
7168 }
7169
7170 static const char *
7171 assign_canonical_path(const char *newval, bool doit, GucSource source)
7172 {
7173         if (doit)
7174         {
7175                 char       *canon_val = guc_strdup(ERROR, newval);
7176
7177                 canonicalize_path(canon_val);
7178                 return canon_val;
7179         }
7180         else
7181                 return newval;
7182 }
7183
7184 static const char *
7185 assign_timezone_abbreviations(const char *newval, bool doit, GucSource source)
7186 {
7187         /*
7188          * The powerup value shown above for timezone_abbreviations is "UNKNOWN".
7189          * When we see this we just do nothing.  If this value isn't overridden
7190          * from the config file then pg_timezone_abbrev_initialize() will
7191          * eventually replace it with "Default".  This hack has two purposes: to
7192          * avoid wasting cycles loading values that might soon be overridden from
7193          * the config file, and to avoid trying to read the timezone abbrev files
7194          * during InitializeGUCOptions().  The latter doesn't work in an
7195          * EXEC_BACKEND subprocess because my_exec_path hasn't been set yet and so
7196          * we can't locate PGSHAREDIR.  (Essentially the same hack is used to
7197          * delay initializing TimeZone ... if we have any more, we should try to
7198          * clean up and centralize this mechanism ...)
7199          */
7200         if (strcmp(newval, "UNKNOWN") == 0)
7201         {
7202                 return newval;
7203         }
7204
7205         /* Loading abbrev file is expensive, so only do it when value changes */
7206         if (timezone_abbreviations_string == NULL ||
7207                 strcmp(timezone_abbreviations_string, newval) != 0)
7208         {
7209                 int                     elevel;
7210
7211                 /*
7212                  * If reading config file, only the postmaster should bleat loudly
7213                  * about problems.      Otherwise, it's just this one process doing it,
7214                  * and we use WARNING message level.
7215                  */
7216                 if (source == PGC_S_FILE)
7217                         elevel = IsUnderPostmaster ? DEBUG3 : LOG;
7218                 else
7219                         elevel = WARNING;
7220                 if (!load_tzoffsets(newval, doit, elevel))
7221                         return NULL;
7222         }
7223         return newval;
7224 }
7225
7226 /*
7227  * pg_timezone_abbrev_initialize --- set default value if not done already
7228  *
7229  * This is called after initial loading of postgresql.conf.  If no
7230  * timezone_abbreviations setting was found therein, select default.
7231  */
7232 void
7233 pg_timezone_abbrev_initialize(void)
7234 {
7235         if (strcmp(timezone_abbreviations_string, "UNKNOWN") == 0)
7236         {
7237                 SetConfigOption("timezone_abbreviations", "Default",
7238                                                 PGC_POSTMASTER, PGC_S_ARGV);
7239         }
7240 }
7241
7242 static const char *
7243 show_archive_command(void)
7244 {
7245         if (XLogArchiveMode)
7246                 return XLogArchiveCommand;
7247         else
7248                 return "(disabled)";
7249 }
7250
7251 static bool
7252 assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
7253 {
7254         if (doit)
7255                 return (pq_setkeepalivesidle(newval, MyProcPort) == STATUS_OK);
7256
7257         return true;
7258 }
7259
7260 static const char *
7261 show_tcp_keepalives_idle(void)
7262 {
7263         static char nbuf[16];
7264
7265         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
7266         return nbuf;
7267 }
7268
7269 static bool
7270 assign_tcp_keepalives_interval(int newval, bool doit, GucSource source)
7271 {
7272         if (doit)
7273                 return (pq_setkeepalivesinterval(newval, MyProcPort) == STATUS_OK);
7274
7275         return true;
7276 }
7277
7278 static const char *
7279 show_tcp_keepalives_interval(void)
7280 {
7281         static char nbuf[16];
7282
7283         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
7284         return nbuf;
7285 }
7286
7287 static bool
7288 assign_tcp_keepalives_count(int newval, bool doit, GucSource source)
7289 {
7290         if (doit)
7291                 return (pq_setkeepalivescount(newval, MyProcPort) == STATUS_OK);
7292
7293         return true;
7294 }
7295
7296 static const char *
7297 show_tcp_keepalives_count(void)
7298 {
7299         static char nbuf[16];
7300
7301         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
7302         return nbuf;
7303 }
7304
7305 static bool
7306 assign_maxconnections(int newval, bool doit, GucSource source)
7307 {
7308         if (newval + autovacuum_max_workers > INT_MAX / 4)
7309                 return false;
7310
7311         if (doit)
7312                 MaxBackends = newval + autovacuum_max_workers;
7313
7314         return true;
7315 }
7316
7317 static bool
7318 assign_autovacuum_max_workers(int newval, bool doit, GucSource source)
7319 {
7320         if (newval + MaxConnections > INT_MAX / 4)
7321                 return false;
7322
7323         if (doit)
7324                 MaxBackends = newval + MaxConnections;
7325
7326         return true;
7327 }
7328
7329 #include "guc-file.c"