]> granicus.if.org Git - postgresql/blob - src/backend/utils/misc/guc.c
Rewrite ProcessConfigFile() to avoid misbehavior at EOF, as per report
[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-2005, 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.305 2005/12/30 00:13:50 petere 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 "utils/guc.h"
29 #include "utils/guc_tables.h"
30
31 #include "access/twophase.h"
32 #include "catalog/namespace.h"
33 #include "catalog/pg_type.h"
34 #include "commands/async.h"
35 #include "commands/variable.h"
36 #include "commands/vacuum.h"
37 #include "executor/executor.h"
38 #include "fmgr.h"
39 #include "funcapi.h"
40 #include "libpq/auth.h"
41 #include "libpq/pqcomm.h"
42 #include "libpq/pqformat.h"
43 #include "mb/pg_wchar.h"
44 #include "miscadmin.h"
45 #include "optimizer/cost.h"
46 #include "optimizer/geqo.h"
47 #include "optimizer/paths.h"
48 #include "optimizer/planmain.h"
49 #include "parser/parse_expr.h"
50 #include "parser/parse_relation.h"
51 #include "postmaster/autovacuum.h"
52 #include "postmaster/bgwriter.h"
53 #include "postmaster/syslogger.h"
54 #include "postmaster/postmaster.h"
55 #include "storage/bufmgr.h"
56 #include "storage/fd.h"
57 #include "storage/freespace.h"
58 #include "storage/lock.h"
59 #include "storage/proc.h"
60 #include "tcop/tcopprot.h"
61 #include "utils/array.h"
62 #include "utils/builtins.h"
63 #include "utils/memutils.h"
64 #include "utils/pg_locale.h"
65 #include "pgstat.h"
66
67
68 #ifndef PG_KRB_SRVTAB
69 #define PG_KRB_SRVTAB ""
70 #endif
71 #ifndef PG_KRB_SRVNAM
72 #define PG_KRB_SRVNAM ""
73 #endif
74
75 #define CONFIG_FILENAME "postgresql.conf"
76 #define HBA_FILENAME    "pg_hba.conf"
77 #define IDENT_FILENAME  "pg_ident.conf"
78
79 #ifdef EXEC_BACKEND
80 #define CONFIG_EXEC_PARAMS "global/config_exec_params"
81 #define CONFIG_EXEC_PARAMS_NEW "global/config_exec_params.new"
82 #endif
83
84 /* upper limit for GUC variables measured in kilobytes of memory */
85 #if SIZEOF_SIZE_T > 4
86 #define MAX_KILOBYTES   INT_MAX
87 #else
88 #define MAX_KILOBYTES   (INT_MAX / 1024)
89 #endif
90
91 /* XXX these should appear in other modules' header files */
92 extern bool Log_disconnections;
93 extern bool check_function_bodies;
94 extern int      CommitDelay;
95 extern int      CommitSiblings;
96 extern char *default_tablespace;
97 extern bool fullPageWrites;
98
99 #ifdef TRACE_SORT
100 extern bool trace_sort;
101 #endif
102
103 static const char *assign_log_destination(const char *value,
104                                            bool doit, GucSource source);
105
106 #ifdef HAVE_SYSLOG
107 static int      syslog_facility = LOG_LOCAL0;
108
109 static const char *assign_syslog_facility(const char *facility,
110                                            bool doit, GucSource source);
111 static const char *assign_syslog_ident(const char *ident,
112                                         bool doit, GucSource source);
113 #endif
114
115 static const char *assign_defaultxactisolevel(const char *newval, bool doit,
116                                                    GucSource source);
117 static const char *assign_log_min_messages(const char *newval, bool doit,
118                                                 GucSource source);
119 static const char *assign_client_min_messages(const char *newval,
120                                                    bool doit, GucSource source);
121 static const char *assign_min_error_statement(const char *newval, bool doit,
122                                                    GucSource source);
123 static const char *assign_msglvl(int *var, const char *newval, bool doit,
124                           GucSource source);
125 static const char *assign_log_error_verbosity(const char *newval, bool doit,
126                                                    GucSource source);
127 static const char *assign_log_statement(const char *newval, bool doit,
128                                          GucSource source);
129 static const char *show_num_temp_buffers(void);
130 static bool assign_phony_autocommit(bool newval, bool doit, GucSource source);
131 static const char *assign_custom_variable_classes(const char *newval, bool doit,
132                                                            GucSource source);
133 static bool assign_ssl(bool newval, bool doit, GucSource source);
134 static bool assign_stage_log_stats(bool newval, bool doit, GucSource source);
135 static bool assign_log_stats(bool newval, bool doit, GucSource source);
136 static bool assign_transaction_read_only(bool newval, bool doit, GucSource source);
137 static const char *assign_canonical_path(const char *newval, bool doit, GucSource source);
138
139 static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
140 static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
141 static bool assign_tcp_keepalives_count(int newval, bool doit, GucSource source);
142 static const char *show_tcp_keepalives_idle(void);
143 static const char *show_tcp_keepalives_interval(void);
144 static const char *show_tcp_keepalives_count(void);
145
146 /*
147  * GUC option variables that are exported from this module
148  */
149 #ifdef USE_ASSERT_CHECKING
150 bool            assert_enabled = true;
151 #endif
152 bool            log_duration = false;
153 bool            Debug_print_plan = false;
154 bool            Debug_print_parse = false;
155 bool            Debug_print_rewritten = false;
156 bool            Debug_pretty_print = false;
157 bool            Explain_pretty_print = true;
158
159 bool            log_parser_stats = false;
160 bool            log_planner_stats = false;
161 bool            log_executor_stats = false;
162 bool            log_statement_stats = false;            /* this is sort of all three
163                                                                                                  * above together */
164 bool            log_btree_build_stats = false;
165
166 bool            SQL_inheritance = true;
167
168 bool            Australian_timezones = false;
169
170 bool            Password_encryption = true;
171
172 bool            default_with_oids = false;
173
174 int                     log_min_error_statement = PANIC;
175 int                     log_min_messages = NOTICE;
176 int                     client_min_messages = NOTICE;
177 int                     log_min_duration_statement = -1;
178
179 int                     num_temp_buffers = 1000;
180
181 char       *ConfigFileName;
182 char       *HbaFileName;
183 char       *IdentFileName;
184 char       *external_pid_file;
185
186 int                     tcp_keepalives_idle;
187 int                     tcp_keepalives_interval;
188 int                     tcp_keepalives_count;
189
190 /*
191  * These variables are all dummies that don't do anything, except in some
192  * cases provide the value for SHOW to display.  The real state is elsewhere
193  * and is kept in sync by assign_hooks.
194  */
195 static char *client_min_messages_str;
196 static char *log_min_messages_str;
197 static char *log_error_verbosity_str;
198 static char *log_statement_str;
199 static char *log_min_error_statement_str;
200 static char *log_destination_string;
201 static char *syslog_facility_str;
202 static char *syslog_ident_str;
203 static bool phony_autocommit;
204 static bool session_auth_is_superuser;
205 static double phony_random_seed;
206 static char *client_encoding_string;
207 static char *datestyle_string;
208 static char *default_iso_level_string;
209 static char *locale_collate;
210 static char *locale_ctype;
211 static char *regex_flavor_string;
212 static char *server_encoding_string;
213 static char *server_version_string;
214 static char *timezone_string;
215 static char *XactIsoLevel_string;
216 static char *data_directory;
217 static char *custom_variable_classes;
218 static int      max_function_args;
219 static int      max_index_keys;
220 static int      max_identifier_length;
221 static int      block_size;
222 static bool integer_datetimes;
223 static bool standard_conforming_strings;
224
225 /* should be static, but commands/variable.c needs to get at these */
226 char       *role_string;
227 char       *session_authorization_string;
228
229
230 /*
231  * Displayable names for context types (enum GucContext)
232  *
233  * Note: these strings are deliberately not localized.
234  */
235 const char *const GucContext_Names[] =
236 {
237          /* PGC_INTERNAL */ "internal",
238          /* PGC_POSTMASTER */ "postmaster",
239          /* PGC_SIGHUP */ "sighup",
240          /* PGC_BACKEND */ "backend",
241          /* PGC_SUSET */ "superuser",
242          /* PGC_USERSET */ "user"
243 };
244
245 /*
246  * Displayable names for source types (enum GucSource)
247  *
248  * Note: these strings are deliberately not localized.
249  */
250 const char *const GucSource_Names[] =
251 {
252          /* PGC_S_DEFAULT */ "default",
253          /* PGC_S_ENV_VAR */ "environment variable",
254          /* PGC_S_FILE */ "configuration file",
255          /* PGC_S_ARGV */ "command line",
256          /* PGC_S_DATABASE */ "database",
257          /* PGC_S_USER */ "user",
258          /* PGC_S_CLIENT */ "client",
259          /* PGC_S_OVERRIDE */ "override",
260          /* PGC_S_INTERACTIVE */ "interactive",
261          /* PGC_S_TEST */ "test",
262          /* PGC_S_SESSION */ "session"
263 };
264
265 /*
266  * Displayable names for the groupings defined in enum config_group
267  */
268 const char *const config_group_names[] =
269 {
270         /* UNGROUPED */
271         gettext_noop("Ungrouped"),
272         /* FILE_LOCATIONS */
273         gettext_noop("File Locations"),
274         /* CONN_AUTH */
275         gettext_noop("Connections and Authentication"),
276         /* CONN_AUTH_SETTINGS */
277         gettext_noop("Connections and Authentication / Connection Settings"),
278         /* CONN_AUTH_SECURITY */
279         gettext_noop("Connections and Authentication / Security and Authentication"),
280         /* RESOURCES */
281         gettext_noop("Resource Usage"),
282         /* RESOURCES_MEM */
283         gettext_noop("Resource Usage / Memory"),
284         /* RESOURCES_FSM */
285         gettext_noop("Resource Usage / Free Space Map"),
286         /* RESOURCES_KERNEL */
287         gettext_noop("Resource Usage / Kernel Resources"),
288         /* WAL */
289         gettext_noop("Write-Ahead Log"),
290         /* WAL_SETTINGS */
291         gettext_noop("Write-Ahead Log / Settings"),
292         /* WAL_CHECKPOINTS */
293         gettext_noop("Write-Ahead Log / Checkpoints"),
294         /* QUERY_TUNING */
295         gettext_noop("Query Tuning"),
296         /* QUERY_TUNING_METHOD */
297         gettext_noop("Query Tuning / Planner Method Configuration"),
298         /* QUERY_TUNING_COST */
299         gettext_noop("Query Tuning / Planner Cost Constants"),
300         /* QUERY_TUNING_GEQO */
301         gettext_noop("Query Tuning / Genetic Query Optimizer"),
302         /* QUERY_TUNING_OTHER */
303         gettext_noop("Query Tuning / Other Planner Options"),
304         /* LOGGING */
305         gettext_noop("Reporting and Logging"),
306         /* LOGGING_WHERE */
307         gettext_noop("Reporting and Logging / Where to Log"),
308         /* LOGGING_WHEN */
309         gettext_noop("Reporting and Logging / When to Log"),
310         /* LOGGING_WHAT */
311         gettext_noop("Reporting and Logging / What to Log"),
312         /* STATS */
313         gettext_noop("Statistics"),
314         /* STATS_MONITORING */
315         gettext_noop("Statistics / Monitoring"),
316         /* STATS_COLLECTOR */
317         gettext_noop("Statistics / Query and Index Statistics Collector"),
318         /* AUTOVACUUM */
319         gettext_noop("Auto Vacuum"),
320         /* CLIENT_CONN */
321         gettext_noop("Client Connection Defaults"),
322         /* CLIENT_CONN_STATEMENT */
323         gettext_noop("Client Connection Defaults / Statement Behavior"),
324         /* CLIENT_CONN_LOCALE */
325         gettext_noop("Client Connection Defaults / Locale and Formatting"),
326         /* CLIENT_CONN_OTHER */
327         gettext_noop("Client Connection Defaults / Other Defaults"),
328         /* LOCK_MANAGEMENT */
329         gettext_noop("Lock Management"),
330         /* COMPAT_OPTIONS */
331         gettext_noop("Version and Platform Compatibility"),
332         /* COMPAT_OPTIONS_PREVIOUS */
333         gettext_noop("Version and Platform Compatibility / Previous PostgreSQL Versions"),
334         /* COMPAT_OPTIONS_CLIENT */
335         gettext_noop("Version and Platform Compatibility / Other Platforms and Clients"),
336         /* PRESET_OPTIONS */
337         gettext_noop("Preset Options"),
338         /* CUSTOM_OPTIONS */
339         gettext_noop("Customized Options"),
340         /* DEVELOPER_OPTIONS */
341         gettext_noop("Developer Options"),
342         /* help_config wants this array to be null-terminated */
343         NULL
344 };
345
346 /*
347  * Displayable names for GUC variable types (enum config_type)
348  *
349  * Note: these strings are deliberately not localized.
350  */
351 const char *const config_type_names[] =
352 {
353          /* PGC_BOOL */ "bool",
354          /* PGC_INT */ "integer",
355          /* PGC_REAL */ "real",
356          /* PGC_STRING */ "string"
357 };
358
359
360 /*
361  * Contents of GUC tables
362  *
363  * See src/backend/utils/misc/README for design notes.
364  *
365  * TO ADD AN OPTION:
366  *
367  * 1. Declare a global variable of type bool, int, double, or char*
368  *        and make use of it.
369  *
370  * 2. Decide at what times it's safe to set the option. See guc.h for
371  *        details.
372  *
373  * 3. Decide on a name, a default value, upper and lower bounds (if
374  *        applicable), etc.
375  *
376  * 4. Add a record below.
377  *
378  * 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
379  *        appropriate
380  *
381  * 6. Add it to src/bin/psql/tab-complete.c, if it's a USERSET option.
382  *
383  * 7. Don't forget to document the option.
384  *
385  * 8. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure
386  *        it is not single quoted at dump time.
387  */
388
389
390 /******** option records follow ********/
391
392 static struct config_bool ConfigureNamesBool[] =
393 {
394         {
395                 {"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
396                         gettext_noop("Enables the planner's use of sequential-scan plans."),
397                         NULL
398                 },
399                 &enable_seqscan,
400                 true, NULL, NULL
401         },
402         {
403                 {"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
404                         gettext_noop("Enables the planner's use of index-scan plans."),
405                         NULL
406                 },
407                 &enable_indexscan,
408                 true, NULL, NULL
409         },
410         {
411                 {"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
412                         gettext_noop("Enables the planner's use of bitmap-scan plans."),
413                         NULL
414                 },
415                 &enable_bitmapscan,
416                 true, NULL, NULL
417         },
418         {
419                 {"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
420                         gettext_noop("Enables the planner's use of TID scan plans."),
421                         NULL
422                 },
423                 &enable_tidscan,
424                 true, NULL, NULL
425         },
426         {
427                 {"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
428                         gettext_noop("Enables the planner's use of explicit sort steps."),
429                         NULL
430                 },
431                 &enable_sort,
432                 true, NULL, NULL
433         },
434         {
435                 {"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
436                         gettext_noop("Enables the planner's use of hashed aggregation plans."),
437                         NULL
438                 },
439                 &enable_hashagg,
440                 true, NULL, NULL
441         },
442         {
443                 {"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
444                         gettext_noop("Enables the planner's use of nested-loop join plans."),
445                         NULL
446                 },
447                 &enable_nestloop,
448                 true, NULL, NULL
449         },
450         {
451                 {"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
452                         gettext_noop("Enables the planner's use of merge join plans."),
453                         NULL
454                 },
455                 &enable_mergejoin,
456                 true, NULL, NULL
457         },
458         {
459                 {"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
460                         gettext_noop("Enables the planner's use of hash join plans."),
461                         NULL
462                 },
463                 &enable_hashjoin,
464                 true, NULL, NULL
465         },
466         {
467                 {"constraint_exclusion", PGC_USERSET, QUERY_TUNING_OTHER,
468                         gettext_noop("Enables the planner to use constraints to optimize queries."),
469                         gettext_noop("Child table scans will be skipped if their "
470                                            "constraints guarantee that no rows match the query.")
471                 },
472                 &constraint_exclusion,
473                 false, NULL, NULL
474         },
475         {
476                 {"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
477                         gettext_noop("Enables genetic query optimization."),
478                         gettext_noop("This algorithm attempts to do planning without "
479                                                  "exhaustive searching.")
480                 },
481                 &enable_geqo,
482                 true, NULL, NULL
483         },
484         {
485                 /* Not for general use --- used by SET SESSION AUTHORIZATION */
486                 {"is_superuser", PGC_INTERNAL, UNGROUPED,
487                         gettext_noop("Shows whether the current user is a superuser."),
488                         NULL,
489                         GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
490                 },
491                 &session_auth_is_superuser,
492                 false, NULL, NULL
493         },
494         {
495                 {"ssl", PGC_POSTMASTER, CONN_AUTH_SECURITY,
496                         gettext_noop("Enables SSL connections."),
497                         NULL
498                 },
499                 &EnableSSL,
500                 false, assign_ssl, NULL
501         },
502         {
503                 {"fsync", PGC_SIGHUP, WAL_SETTINGS,
504                         gettext_noop("Forces synchronization of updates to disk."),
505                         gettext_noop("The server will use the fsync() system call in several places to make "
506                         "sure that updates are physically written to disk. This insures "
507                                                  "that a database cluster will recover to a consistent state after "
508                                                  "an operating system or hardware crash.")
509                 },
510                 &enableFsync,
511                 true, NULL, NULL
512         },
513         {
514                 {"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
515                         gettext_noop("Continues processing past damaged page headers."),
516                         gettext_noop("Detection of a damaged page header normally causes PostgreSQL to "
517                                 "report an error, aborting the current transaction. Setting "
518                                                  "zero_damaged_pages to true causes the system to instead report a "
519                                                  "warning, zero out the damaged page, and continue processing. This "
520                                                  "behavior will destroy data, namely all the rows on the damaged page."),
521                         GUC_NOT_IN_SAMPLE
522                 },
523                 &zero_damaged_pages,
524                 false, NULL, NULL
525         },
526         {
527                 {"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
528                         gettext_noop("Writes full pages to WAL when first modified after a checkpoint."),
529                         gettext_noop("A page write in process during an operating system crash might be "
530                                                  "only partially written to disk.  During recovery, the row changes "
531                           "stored in WAL are not enough to recover.  This option writes "
532                                                  "pages when first modified after a checkpoint to WAL so full recovery "
533                                                  "is possible.")
534                 },
535                 &fullPageWrites,
536                 true, NULL, NULL
537         },
538         {
539                 {"silent_mode", PGC_POSTMASTER, LOGGING_WHEN,
540                         gettext_noop("Runs the server silently."),
541                         gettext_noop("If this parameter is set, the server will automatically run in the "
542                                  "background and any controlling terminals are dissociated.")
543                 },
544                 &SilentMode,
545                 false, NULL, NULL
546         },
547         {
548                 {"log_connections", PGC_BACKEND, LOGGING_WHAT,
549                         gettext_noop("Logs each successful connection."),
550                         NULL
551                 },
552                 &Log_connections,
553                 false, NULL, NULL
554         },
555         {
556                 {"log_disconnections", PGC_BACKEND, LOGGING_WHAT,
557                         gettext_noop("Logs end of a session, including duration."),
558                         NULL
559                 },
560                 &Log_disconnections,
561                 false, NULL, NULL
562         },
563
564 #ifdef USE_ASSERT_CHECKING
565         {
566                 {"debug_assertions", PGC_USERSET, DEVELOPER_OPTIONS,
567                         gettext_noop("Turns on various assertion checks."),
568                         gettext_noop("This is a debugging aid."),
569                         GUC_NOT_IN_SAMPLE
570                 },
571                 &assert_enabled,
572                 true, NULL, NULL
573         },
574 #endif
575
576         {
577                 /* currently undocumented, so don't show in SHOW ALL */
578                 {"exit_on_error", PGC_USERSET, UNGROUPED,
579                         gettext_noop("no description available"),
580                         NULL,
581                         GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
582                 },
583                 &ExitOnAnyError,
584                 false, NULL, NULL
585         },
586         {
587                 {"log_duration", PGC_SUSET, LOGGING_WHAT,
588                         gettext_noop("Logs the duration of each completed SQL statement."),
589                         NULL
590                 },
591                 &log_duration,
592                 false, NULL, NULL
593         },
594         {
595                 {"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
596                         gettext_noop("Prints the parse tree to the server log."),
597                         NULL
598                 },
599                 &Debug_print_parse,
600                 false, NULL, NULL
601         },
602         {
603                 {"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
604                         gettext_noop("Prints the parse tree after rewriting to server log."),
605                         NULL
606                 },
607                 &Debug_print_rewritten,
608                 false, NULL, NULL
609         },
610         {
611                 {"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
612                         gettext_noop("Prints the execution plan to server log."),
613                         NULL
614                 },
615                 &Debug_print_plan,
616                 false, NULL, NULL
617         },
618         {
619                 {"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
620                         gettext_noop("Indents parse and plan tree displays."),
621                         NULL
622                 },
623                 &Debug_pretty_print,
624                 false, NULL, NULL
625         },
626         {
627                 {"log_parser_stats", PGC_SUSET, STATS_MONITORING,
628                         gettext_noop("Writes parser performance statistics to the server log."),
629                         NULL
630                 },
631                 &log_parser_stats,
632                 false, assign_stage_log_stats, NULL
633         },
634         {
635                 {"log_planner_stats", PGC_SUSET, STATS_MONITORING,
636                         gettext_noop("Writes planner performance statistics to the server log."),
637                         NULL
638                 },
639                 &log_planner_stats,
640                 false, assign_stage_log_stats, NULL
641         },
642         {
643                 {"log_executor_stats", PGC_SUSET, STATS_MONITORING,
644                         gettext_noop("Writes executor performance statistics to the server log."),
645                         NULL
646                 },
647                 &log_executor_stats,
648                 false, assign_stage_log_stats, NULL
649         },
650         {
651                 {"log_statement_stats", PGC_SUSET, STATS_MONITORING,
652                         gettext_noop("Writes cumulative performance statistics to the server log."),
653                         NULL
654                 },
655                 &log_statement_stats,
656                 false, assign_log_stats, NULL
657         },
658 #ifdef BTREE_BUILD_STATS
659         {
660                 {"log_btree_build_stats", PGC_SUSET, DEVELOPER_OPTIONS,
661                         gettext_noop("no description available"),
662                         NULL,
663                         GUC_NOT_IN_SAMPLE
664                 },
665                 &log_btree_build_stats,
666                 false, NULL, NULL
667         },
668 #endif
669
670         {
671                 {"explain_pretty_print", PGC_USERSET, CLIENT_CONN_OTHER,
672                         gettext_noop("Uses the indented output format for EXPLAIN VERBOSE."),
673                         NULL
674                 },
675                 &Explain_pretty_print,
676                 true, NULL, NULL
677         },
678         {
679                 {"stats_start_collector", PGC_POSTMASTER, STATS_COLLECTOR,
680                         gettext_noop("Starts the server statistics-collection subprocess."),
681                         NULL
682                 },
683                 &pgstat_collect_startcollector,
684                 true, NULL, NULL
685         },
686         {
687                 {"stats_reset_on_server_start", PGC_POSTMASTER, STATS_COLLECTOR,
688                         gettext_noop("Zeroes collected statistics on server restart."),
689                         NULL
690                 },
691                 &pgstat_collect_resetonpmstart,
692                 false, NULL, NULL
693         },
694         {
695                 {"stats_command_string", PGC_SUSET, STATS_COLLECTOR,
696                         gettext_noop("Collects statistics about executing commands."),
697                         gettext_noop("Enables the collection of statistics on the currently "
698                                         "executing command of each session, along with the time "
699                                                  "at which that command began execution.")
700                 },
701                 &pgstat_collect_querystring,
702                 false, NULL, NULL
703         },
704         {
705                 {"stats_row_level", PGC_SUSET, STATS_COLLECTOR,
706                         gettext_noop("Collects row-level statistics on database activity."),
707                         NULL
708                 },
709                 &pgstat_collect_tuplelevel,
710                 false, NULL, NULL
711         },
712         {
713                 {"stats_block_level", PGC_SUSET, STATS_COLLECTOR,
714                         gettext_noop("Collects block-level statistics on database activity."),
715                         NULL
716                 },
717                 &pgstat_collect_blocklevel,
718                 false, NULL, NULL
719         },
720
721         {
722                 {"autovacuum", PGC_SIGHUP, AUTOVACUUM,
723                         gettext_noop("Starts the autovacuum subprocess."),
724                         NULL
725                 },
726                 &autovacuum_start_daemon,
727                 false, NULL, NULL
728         },
729
730         {
731                 {"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
732                         gettext_noop("Generates debugging output for LISTEN and NOTIFY."),
733                         NULL,
734                         GUC_NOT_IN_SAMPLE
735                 },
736                 &Trace_notify,
737                 false, NULL, NULL
738         },
739
740 #ifdef LOCK_DEBUG
741         {
742                 {"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
743                         gettext_noop("no description available"),
744                         NULL,
745                         GUC_NOT_IN_SAMPLE
746                 },
747                 &Trace_locks,
748                 false, NULL, NULL
749         },
750         {
751                 {"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
752                         gettext_noop("no description available"),
753                         NULL,
754                         GUC_NOT_IN_SAMPLE
755                 },
756                 &Trace_userlocks,
757                 false, NULL, NULL
758         },
759         {
760                 {"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
761                         gettext_noop("no description available"),
762                         NULL,
763                         GUC_NOT_IN_SAMPLE
764                 },
765                 &Trace_lwlocks,
766                 false, NULL, NULL
767         },
768         {
769                 {"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
770                         gettext_noop("no description available"),
771                         NULL,
772                         GUC_NOT_IN_SAMPLE
773                 },
774                 &Debug_deadlocks,
775                 false, NULL, NULL
776         },
777 #endif
778
779         {
780                 {"log_hostname", PGC_SIGHUP, LOGGING_WHAT,
781                         gettext_noop("Logs the host name in the connection logs."),
782                         gettext_noop("By default, connection logs only show the IP address "
783                                                  "of the connecting host. If you want them to show the host name you "
784                           "can turn this on, but depending on your host name resolution "
785                            "setup it might impose a non-negligible performance penalty.")
786                 },
787                 &log_hostname,
788                 false, NULL, NULL
789         },
790         {
791                 {"sql_inheritance", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
792                         gettext_noop("Causes subtables to be included by default in various commands."),
793                         NULL
794                 },
795                 &SQL_inheritance,
796                 true, NULL, NULL
797         },
798         {
799                 {"australian_timezones", PGC_USERSET, CLIENT_CONN_LOCALE,
800                         gettext_noop("Interprets ACST, CST, EST, and SAT as Australian time zones."),
801                         gettext_noop("Otherwise they are interpreted as North/South American "
802                                                  "time zones and Saturday.")
803                 },
804                 &Australian_timezones,
805                 false, ClearDateCache, NULL
806         },
807         {
808                 {"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
809                         gettext_noop("Encrypt passwords."),
810                         gettext_noop("When a password is specified in CREATE USER or "
811                            "ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
812                                                  "this parameter determines whether the password is to be encrypted.")
813                 },
814                 &Password_encryption,
815                 true, NULL, NULL
816         },
817         {
818                 {"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
819                         gettext_noop("Treats \"expr=NULL\" as \"expr IS NULL\"."),
820                         gettext_noop("When turned on, expressions of the form expr = NULL "
821                            "(or NULL = expr) are treated as expr IS NULL, that is, they "
822                                 "return true if expr evaluates to the null value, and false "
823                            "otherwise. The correct behavior of expr = NULL is to always "
824                                                  "return null (unknown).")
825                 },
826                 &Transform_null_equals,
827                 false, NULL, NULL
828         },
829         {
830                 {"db_user_namespace", PGC_SIGHUP, CONN_AUTH_SECURITY,
831                         gettext_noop("Enables per-database user names."),
832                         NULL
833                 },
834                 &Db_user_namespace,
835                 false, NULL, NULL
836         },
837         {
838                 /* only here for backwards compatibility */
839                 {"autocommit", PGC_USERSET, CLIENT_CONN_STATEMENT,
840                         gettext_noop("This parameter doesn't do anything."),
841                         gettext_noop("It's just here so that we won't choke on SET AUTOCOMMIT TO ON from 7.3-vintage clients."),
842                         GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
843                 },
844                 &phony_autocommit,
845                 true, assign_phony_autocommit, NULL
846         },
847         {
848                 {"default_transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
849                         gettext_noop("Sets the default read-only status of new transactions."),
850                         NULL
851                 },
852                 &DefaultXactReadOnly,
853                 false, NULL, NULL
854         },
855         {
856                 {"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
857                         gettext_noop("Sets the current transaction's read-only status."),
858                         NULL,
859                         GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
860                 },
861                 &XactReadOnly,
862                 false, assign_transaction_read_only, NULL
863         },
864         {
865                 {"add_missing_from", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
866                         gettext_noop("Automatically adds missing table references to FROM clauses."),
867                         NULL
868                 },
869                 &add_missing_from,
870                 false, NULL, NULL
871         },
872         {
873                 {"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
874                         gettext_noop("Check function bodies during CREATE FUNCTION."),
875                         NULL
876                 },
877                 &check_function_bodies,
878                 true, NULL, NULL
879         },
880         {
881                 {"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
882                         gettext_noop("Enable input of NULL elements in arrays."),
883                         gettext_noop("When turned on, unquoted NULL in an array input "
884                                                  "value means a NULL value; "
885                                                  "otherwise it is taken literally.")
886                 },
887                 &Array_nulls,
888                 true, NULL, NULL
889         },
890         {
891                 {"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
892                         gettext_noop("Create new tables with OIDs by default."),
893                         NULL
894                 },
895                 &default_with_oids,
896                 false, NULL, NULL
897         },
898         {
899                 {"redirect_stderr", PGC_POSTMASTER, LOGGING_WHERE,
900                         gettext_noop("Start a subprocess to capture stderr output into log files."),
901                         NULL
902                 },
903                 &Redirect_stderr,
904                 false, NULL, NULL
905         },
906         {
907                 {"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
908                         gettext_noop("Truncate existing log files of same name during log rotation."),
909                         NULL
910                 },
911                 &Log_truncate_on_rotation,
912                 false, NULL, NULL
913         },
914
915 #ifdef TRACE_SORT
916         {
917                 {"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
918                         gettext_noop("Emit information about resource usage in sorting."),
919                         NULL,
920                         GUC_NOT_IN_SAMPLE
921                 },
922                 &trace_sort,
923                 false, NULL, NULL
924         },
925 #endif
926
927 #ifdef WAL_DEBUG
928         {
929                 {"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
930                         gettext_noop("Emit WAL-related debugging output."),
931                         NULL,
932                         GUC_NOT_IN_SAMPLE
933                 },
934                 &XLOG_DEBUG,
935                 false, NULL, NULL
936         },
937 #endif
938
939         {
940                 {"integer_datetimes", PGC_INTERNAL, PRESET_OPTIONS,
941                         gettext_noop("Datetimes are integer based."),
942                         NULL,
943                         GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
944                 },
945                 &integer_datetimes,
946 #ifdef HAVE_INT64_TIMESTAMP
947                 true, NULL, NULL
948 #else
949                 false, NULL, NULL
950 #endif
951         },
952
953         {
954                 {"krb_caseins_users", PGC_POSTMASTER, CONN_AUTH_SECURITY,
955                         gettext_noop("Sets whether Kerberos user names should be treated as case-insensitive."),
956                         NULL
957                 },
958                 &pg_krb_caseins_users,
959                 false, NULL, NULL
960         },
961
962         {
963                 {"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
964                         gettext_noop("Warn about backslash escapes in ordinary string literals."),
965                         NULL
966                 },
967                 &escape_string_warning,
968                 false, NULL, NULL
969         },
970
971         {
972                 {"standard_conforming_strings", PGC_INTERNAL, PRESET_OPTIONS,
973                         gettext_noop("'...' strings treat backslashes literally."),
974                         NULL,
975                         GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
976                 },
977                 &standard_conforming_strings,
978                 false, NULL, NULL
979         },
980
981         /* End-of-list marker */
982         {
983                 {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL
984         }
985 };
986
987
988 static struct config_int ConfigureNamesInt[] =
989 {
990         {
991                 {"default_statistics_target", PGC_USERSET, QUERY_TUNING_OTHER,
992                         gettext_noop("Sets the default statistics target."),
993                         gettext_noop("This applies to table columns that have not had a "
994                                 "column-specific target set via ALTER TABLE SET STATISTICS.")
995                 },
996                 &default_statistics_target,
997                 10, 1, 1000, NULL, NULL
998         },
999         {
1000                 {"from_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
1001                         gettext_noop("Sets the FROM-list size beyond which subqueries are not "
1002                                                  "collapsed."),
1003                         gettext_noop("The planner will merge subqueries into upper "
1004                                 "queries if the resulting FROM list would have no more than "
1005                                                  "this many items.")
1006                 },
1007                 &from_collapse_limit,
1008                 8, 1, INT_MAX, NULL, NULL
1009         },
1010         {
1011                 {"join_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
1012                         gettext_noop("Sets the FROM-list size beyond which JOIN constructs are not "
1013                                                  "flattened."),
1014                         gettext_noop("The planner will flatten explicit JOIN "
1015                         "constructs into lists of FROM items whenever a list of no more "
1016                                                  "than this many items would result.")
1017                 },
1018                 &join_collapse_limit,
1019                 8, 1, INT_MAX, NULL, NULL
1020         },
1021         {
1022                 {"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
1023                         gettext_noop("Sets the threshold of FROM items beyond which GEQO is used."),
1024                         NULL
1025                 },
1026                 &geqo_threshold,
1027                 12, 2, INT_MAX, NULL, NULL
1028         },
1029         {
1030                 {"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
1031                         gettext_noop("GEQO: effort is used to set the default for other GEQO parameters."),
1032                         NULL
1033                 },
1034                 &Geqo_effort,
1035                 DEFAULT_GEQO_EFFORT, MIN_GEQO_EFFORT, MAX_GEQO_EFFORT, NULL, NULL
1036         },
1037         {
1038                 {"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
1039                         gettext_noop("GEQO: number of individuals in the population."),
1040                         gettext_noop("Zero selects a suitable default value.")
1041                 },
1042                 &Geqo_pool_size,
1043                 0, 0, INT_MAX, NULL, NULL
1044         },
1045         {
1046                 {"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
1047                         gettext_noop("GEQO: number of iterations of the algorithm."),
1048                         gettext_noop("Zero selects a suitable default value.")
1049                 },
1050                 &Geqo_generations,
1051                 0, 0, INT_MAX, NULL, NULL
1052         },
1053
1054         {
1055                 {"deadlock_timeout", PGC_SIGHUP, LOCK_MANAGEMENT,
1056                         gettext_noop("The time in milliseconds to wait on lock before checking for deadlock."),
1057                         NULL
1058                 },
1059                 &DeadlockTimeout,
1060                 1000, 0, INT_MAX, NULL, NULL
1061         },
1062
1063         /*
1064          * Note: There is some postprocessing done in PostmasterMain() to make
1065          * sure the buffers are at least twice the number of backends, so the
1066          * constraints here are partially unused. Similarly, the superuser
1067          * reserved number is checked to ensure it is less than the max backends
1068          * number.
1069          *
1070          * MaxBackends is limited to INT_MAX/4 because some places compute
1071          * 4*MaxBackends without any overflow check.  Likewise we have to limit
1072          * NBuffers to INT_MAX/2.
1073          */
1074         {
1075                 {"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1076                         gettext_noop("Sets the maximum number of concurrent connections."),
1077                         NULL
1078                 },
1079                 &MaxBackends,
1080                 100, 1, INT_MAX / 4, NULL, NULL
1081         },
1082
1083         {
1084                 {"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1085                         gettext_noop("Sets the number of connection slots reserved for superusers."),
1086                         NULL
1087                 },
1088                 &ReservedBackends,
1089                 2, 0, INT_MAX / 4, NULL, NULL
1090         },
1091
1092         {
1093                 {"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
1094                         gettext_noop("Sets the number of shared memory buffers used by the server."),
1095                         NULL
1096                 },
1097                 &NBuffers,
1098                 1000, 16, INT_MAX / 2, NULL, NULL
1099         },
1100
1101         {
1102                 {"temp_buffers", PGC_USERSET, RESOURCES_MEM,
1103                         gettext_noop("Sets the maximum number of temporary buffers used by each session."),
1104                         NULL
1105                 },
1106                 &num_temp_buffers,
1107                 1000, 100, INT_MAX / 2, NULL, show_num_temp_buffers
1108         },
1109
1110         {
1111                 {"port", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1112                         gettext_noop("Sets the TCP port the server listens on."),
1113                         NULL
1114                 },
1115                 &PostPortNumber,
1116                 DEF_PGPORT, 1, 65535, NULL, NULL
1117         },
1118
1119         {
1120                 {"unix_socket_permissions", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1121                         gettext_noop("Sets the access permissions of the Unix-domain socket."),
1122                         gettext_noop("Unix-domain sockets use the usual Unix file system "
1123                                                  "permission set. The parameter value is expected to be an numeric mode "
1124                                                  "specification in the form accepted by the chmod and umask system "
1125                                                  "calls. (To use the customary octal format the number must start with "
1126                                                  "a 0 (zero).)")
1127                 },
1128                 &Unix_socket_permissions,
1129                 0777, 0000, 0777, NULL, NULL
1130         },
1131
1132         {
1133                 {"work_mem", PGC_USERSET, RESOURCES_MEM,
1134                         gettext_noop("Sets the maximum memory to be used for query workspaces."),
1135                         gettext_noop("This much memory may be used by each internal "
1136                                                  "sort operation and hash table before switching to "
1137                                                  "temporary disk files.")
1138                 },
1139                 &work_mem,
1140                 1024, 8 * BLCKSZ / 1024, MAX_KILOBYTES, NULL, NULL
1141         },
1142
1143         {
1144                 {"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
1145                         gettext_noop("Sets the maximum memory to be used for maintenance operations."),
1146                         gettext_noop("This includes operations such as VACUUM and CREATE INDEX.")
1147                 },
1148                 &maintenance_work_mem,
1149                 16384, 1024, MAX_KILOBYTES, NULL, NULL
1150         },
1151
1152         {
1153                 {"max_stack_depth", PGC_SUSET, RESOURCES_MEM,
1154                         gettext_noop("Sets the maximum stack depth, in kilobytes."),
1155                         NULL
1156                 },
1157                 &max_stack_depth,
1158                 2048, 100, MAX_KILOBYTES, assign_max_stack_depth, NULL
1159         },
1160
1161         {
1162                 {"vacuum_cost_page_hit", PGC_USERSET, RESOURCES,
1163                         gettext_noop("Vacuum cost for a page found in the buffer cache."),
1164                         NULL
1165                 },
1166                 &VacuumCostPageHit,
1167                 1, 0, 10000, NULL, NULL
1168         },
1169
1170         {
1171                 {"vacuum_cost_page_miss", PGC_USERSET, RESOURCES,
1172                         gettext_noop("Vacuum cost for a page not found in the buffer cache."),
1173                         NULL
1174                 },
1175                 &VacuumCostPageMiss,
1176                 10, 0, 10000, NULL, NULL
1177         },
1178
1179         {
1180                 {"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES,
1181                         gettext_noop("Vacuum cost for a page dirtied by vacuum."),
1182                         NULL
1183                 },
1184                 &VacuumCostPageDirty,
1185                 20, 0, 10000, NULL, NULL
1186         },
1187
1188         {
1189                 {"vacuum_cost_limit", PGC_USERSET, RESOURCES,
1190                         gettext_noop("Vacuum cost amount available before napping."),
1191                         NULL
1192                 },
1193                 &VacuumCostLimit,
1194                 200, 1, 10000, NULL, NULL
1195         },
1196
1197         {
1198                 {"vacuum_cost_delay", PGC_USERSET, RESOURCES,
1199                         gettext_noop("Vacuum cost delay in milliseconds."),
1200                         NULL
1201                 },
1202                 &VacuumCostDelay,
1203                 0, 0, 1000, NULL, NULL
1204         },
1205
1206         {
1207                 {"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
1208                         gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
1209                         NULL
1210                 },
1211                 &autovacuum_vac_cost_delay,
1212                 -1, -1, 1000, NULL, NULL
1213         },
1214
1215         {
1216                 {"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
1217                         gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
1218                         NULL
1219                 },
1220                 &autovacuum_vac_cost_limit,
1221                 -1, -1, 10000, NULL, NULL
1222         },
1223
1224         {
1225                 {"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
1226                         gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
1227                         NULL
1228                 },
1229                 &max_files_per_process,
1230                 1000, 25, INT_MAX, NULL, NULL
1231         },
1232
1233         {
1234                 {"max_prepared_transactions", PGC_POSTMASTER, RESOURCES,
1235                         gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
1236                         NULL
1237                 },
1238                 &max_prepared_xacts,
1239                 5, 0, INT_MAX, NULL, NULL
1240         },
1241
1242 #ifdef LOCK_DEBUG
1243         {
1244                 {"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
1245                         gettext_noop("no description available"),
1246                         NULL,
1247                         GUC_NOT_IN_SAMPLE
1248                 },
1249                 &Trace_lock_oidmin,
1250                 FirstNormalObjectId, 0, INT_MAX, NULL, NULL
1251         },
1252         {
1253                 {"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
1254                         gettext_noop("no description available"),
1255                         NULL,
1256                         GUC_NOT_IN_SAMPLE
1257                 },
1258                 &Trace_lock_table,
1259                 0, 0, INT_MAX, NULL, NULL
1260         },
1261 #endif
1262
1263         {
1264                 {"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
1265                         gettext_noop("Sets the maximum allowed duration (in milliseconds) of any statement."),
1266                         gettext_noop("A value of 0 turns off the timeout.")
1267                 },
1268                 &StatementTimeout,
1269                 0, 0, INT_MAX, NULL, NULL
1270         },
1271
1272         {
1273                 {"max_fsm_relations", PGC_POSTMASTER, RESOURCES_FSM,
1274                         gettext_noop("Sets the maximum number of tables and indexes for which free space is tracked."),
1275                         NULL
1276                 },
1277                 &MaxFSMRelations,
1278                 1000, 100, INT_MAX, NULL, NULL
1279         },
1280         {
1281                 {"max_fsm_pages", PGC_POSTMASTER, RESOURCES_FSM,
1282                         gettext_noop("Sets the maximum number of disk pages for which free space is tracked."),
1283                         NULL
1284                 },
1285                 &MaxFSMPages,
1286                 20000, 1000, INT_MAX, NULL, NULL
1287         },
1288
1289         {
1290                 {"max_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
1291                         gettext_noop("Sets the maximum number of locks per transaction."),
1292                         gettext_noop("The shared lock table is sized on the assumption that "
1293                           "at most max_locks_per_transaction * max_connections distinct "
1294                                                  "objects will need to be locked at any one time.")
1295                 },
1296                 &max_locks_per_xact,
1297                 64, 10, INT_MAX, NULL, NULL
1298         },
1299
1300         {
1301                 {"authentication_timeout", PGC_SIGHUP, CONN_AUTH_SECURITY,
1302                         gettext_noop("Sets the maximum time in seconds to complete client authentication."),
1303                         NULL
1304                 },
1305                 &AuthenticationTimeout,
1306                 60, 1, 600, NULL, NULL
1307         },
1308
1309         {
1310                 /* Not for general use */
1311                 {"pre_auth_delay", PGC_SIGHUP, DEVELOPER_OPTIONS,
1312                         gettext_noop("no description available"),
1313                         NULL,
1314                         GUC_NOT_IN_SAMPLE
1315                 },
1316                 &PreAuthDelay,
1317                 0, 0, 60, NULL, NULL
1318         },
1319
1320         {
1321                 {"checkpoint_segments", PGC_SIGHUP, WAL_CHECKPOINTS,
1322                         gettext_noop("Sets the maximum distance in log segments between automatic WAL checkpoints."),
1323                         NULL
1324                 },
1325                 &CheckPointSegments,
1326                 3, 1, INT_MAX, NULL, NULL
1327         },
1328
1329         {
1330                 {"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS,
1331                         gettext_noop("Sets the maximum time in seconds between automatic WAL checkpoints."),
1332                         NULL
1333                 },
1334                 &CheckPointTimeout,
1335                 300, 30, 3600, NULL, NULL
1336         },
1337
1338         {
1339                 {"checkpoint_warning", PGC_SIGHUP, WAL_CHECKPOINTS,
1340                         gettext_noop("Logs if filling of checkpoint segments happens more "
1341                                                  "frequently than this (in seconds)."),
1342                         gettext_noop("Write a message to the server log if checkpoints "
1343                         "caused by the filling of checkpoint segment files happens more "
1344                                                  "frequently than this number of seconds. Zero turns off the warning.")
1345                 },
1346                 &CheckPointWarning,
1347                 30, 0, INT_MAX, NULL, NULL
1348         },
1349
1350         {
1351                 {"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
1352                         gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
1353                         NULL
1354                 },
1355                 &XLOGbuffers,
1356                 8, 4, INT_MAX, NULL, NULL
1357         },
1358
1359         {
1360                 {"commit_delay", PGC_USERSET, WAL_CHECKPOINTS,
1361                         gettext_noop("Sets the delay in microseconds between transaction commit and "
1362                                                  "flushing WAL to disk."),
1363                         NULL
1364                 },
1365                 &CommitDelay,
1366                 0, 0, 100000, NULL, NULL
1367         },
1368
1369         {
1370                 {"commit_siblings", PGC_USERSET, WAL_CHECKPOINTS,
1371                         gettext_noop("Sets the minimum concurrent open transactions before performing "
1372                                                  "commit_delay."),
1373                         NULL
1374                 },
1375                 &CommitSiblings,
1376                 5, 1, 1000, NULL, NULL
1377         },
1378
1379         {
1380                 {"extra_float_digits", PGC_USERSET, CLIENT_CONN_LOCALE,
1381                         gettext_noop("Sets the number of digits displayed for floating-point values."),
1382                         gettext_noop("This affects real, double precision, and geometric data types. "
1383                          "The parameter value is added to the standard number of digits "
1384                                                  "(FLT_DIG or DBL_DIG as appropriate).")
1385                 },
1386                 &extra_float_digits,
1387                 0, -15, 2, NULL, NULL
1388         },
1389
1390         {
1391                 {"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN,
1392                         gettext_noop("Sets the minimum execution time in milliseconds above which statements will "
1393                                                  "be logged."),
1394                         gettext_noop("Zero prints all queries. The default is -1 (turning this feature off).")
1395                 },
1396                 &log_min_duration_statement,
1397                 -1, -1, INT_MAX / 1000, NULL, NULL
1398         },
1399
1400         {
1401                 {"bgwriter_delay", PGC_SIGHUP, RESOURCES,
1402                         gettext_noop("Background writer sleep time between rounds in milliseconds"),
1403                         NULL
1404                 },
1405                 &BgWriterDelay,
1406                 200, 10, 10000, NULL, NULL
1407         },
1408
1409         {
1410                 {"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES,
1411                         gettext_noop("Background writer maximum number of LRU pages to flush per round"),
1412                         NULL
1413                 },
1414                 &bgwriter_lru_maxpages,
1415                 5, 0, 1000, NULL, NULL
1416         },
1417
1418         {
1419                 {"bgwriter_all_maxpages", PGC_SIGHUP, RESOURCES,
1420                         gettext_noop("Background writer maximum number of all pages to flush per round"),
1421                         NULL
1422                 },
1423                 &bgwriter_all_maxpages,
1424                 5, 0, 1000, NULL, NULL
1425         },
1426
1427         {
1428                 {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
1429                         gettext_noop("Automatic log file rotation will occur after N minutes"),
1430                         NULL
1431                 },
1432                 &Log_RotationAge,
1433                 HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / MINS_PER_HOUR, NULL, NULL
1434         },
1435
1436         {
1437                 {"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
1438                         gettext_noop("Automatic log file rotation will occur after N kilobytes"),
1439                         NULL
1440                 },
1441                 &Log_RotationSize,
1442                 10 * 1024, 0, INT_MAX / 1024, NULL, NULL
1443         },
1444
1445         {
1446                 {"max_function_args", PGC_INTERNAL, PRESET_OPTIONS,
1447                         gettext_noop("Shows the maximum number of function arguments."),
1448                         NULL,
1449                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1450                 },
1451                 &max_function_args,
1452                 FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS, NULL, NULL
1453         },
1454
1455         {
1456                 {"max_index_keys", PGC_INTERNAL, PRESET_OPTIONS,
1457                         gettext_noop("Shows the maximum number of index keys."),
1458                         NULL,
1459                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1460                 },
1461                 &max_index_keys,
1462                 INDEX_MAX_KEYS, INDEX_MAX_KEYS, INDEX_MAX_KEYS, NULL, NULL
1463         },
1464
1465         {
1466                 {"max_identifier_length", PGC_INTERNAL, PRESET_OPTIONS,
1467                         gettext_noop("Shows the maximum identifier length"),
1468                         NULL,
1469                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1470                 },
1471                 &max_identifier_length,
1472                 NAMEDATALEN - 1, NAMEDATALEN - 1, NAMEDATALEN - 1, NULL, NULL
1473         },
1474
1475         {
1476                 {"block_size", PGC_INTERNAL, PRESET_OPTIONS,
1477                         gettext_noop("Shows size of a disk block"),
1478                         NULL,
1479                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1480                 },
1481                 &block_size,
1482                 BLCKSZ, BLCKSZ, BLCKSZ, NULL, NULL
1483         },
1484
1485         {
1486                 {"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
1487                         gettext_noop("Time to sleep between autovacuum runs, in seconds."),
1488                         NULL
1489                 },
1490                 &autovacuum_naptime,
1491                 60, 1, INT_MAX, NULL, NULL
1492         },
1493         {
1494                 {"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
1495                         gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
1496                         NULL
1497                 },
1498                 &autovacuum_vac_thresh,
1499                 1000, 0, INT_MAX, NULL, NULL
1500         },
1501         {
1502                 {"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
1503                         gettext_noop("Minimum number of tuple inserts, updates or deletes prior to analyze."),
1504                         NULL
1505                 },
1506                 &autovacuum_anl_thresh,
1507                 500, 0, INT_MAX, NULL, NULL
1508         },
1509
1510         {
1511                 {"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER,
1512                         gettext_noop("Seconds between issuing TCP keepalives."),
1513                         gettext_noop("A value of 0 uses the system default."),
1514                 },
1515                 &tcp_keepalives_idle,
1516                 0, 0, INT_MAX, assign_tcp_keepalives_idle, show_tcp_keepalives_idle
1517         },
1518
1519         {
1520                 {"tcp_keepalives_interval", PGC_USERSET, CLIENT_CONN_OTHER,
1521                         gettext_noop("Seconds between TCP keepalive retransmits."),
1522                         gettext_noop("A value of 0 uses the system default."),
1523                 },
1524                 &tcp_keepalives_interval,
1525                 0, 0, INT_MAX, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
1526         },
1527
1528         {
1529                 {"tcp_keepalives_count", PGC_USERSET, CLIENT_CONN_OTHER,
1530                         gettext_noop("Maximum number of TCP keepalive retransmits."),
1531                         gettext_noop("This controls the number of consecutive keepalive retransmits that can be "
1532                                                  "lost before a connection is considered dead. A value of 0 uses the "
1533                                                  "system default."),
1534                 },
1535                 &tcp_keepalives_count,
1536                 0, 0, INT_MAX, assign_tcp_keepalives_count, show_tcp_keepalives_count
1537         },
1538
1539         /* End-of-list marker */
1540         {
1541                 {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
1542         }
1543 };
1544
1545
1546 static struct config_real ConfigureNamesReal[] =
1547 {
1548         {
1549                 {"effective_cache_size", PGC_USERSET, QUERY_TUNING_COST,
1550                         gettext_noop("Sets the planner's assumption about size of the disk cache."),
1551                         gettext_noop("That is, the portion of the kernel's disk cache that "
1552                                                  "will be used for PostgreSQL data files. This is measured in disk "
1553                                                  "pages, which are normally 8 kB each.")
1554                 },
1555                 &effective_cache_size,
1556                 DEFAULT_EFFECTIVE_CACHE_SIZE, 1, DBL_MAX, NULL, NULL
1557         },
1558         {
1559                 {"random_page_cost", PGC_USERSET, QUERY_TUNING_COST,
1560                         gettext_noop("Sets the planner's estimate of the cost of a nonsequentially "
1561                                                  "fetched disk page."),
1562                         gettext_noop("This is measured as a multiple of the cost of a "
1563                           "sequential page fetch. A higher value makes it more likely a "
1564                                                  "sequential scan will be used, a lower value makes it more likely an "
1565                                                  "index scan will be used.")
1566                 },
1567                 &random_page_cost,
1568                 DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX, NULL, NULL
1569         },
1570         {
1571                 {"cpu_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
1572                         gettext_noop("Sets the planner's estimate of the cost of processing each tuple (row)."),
1573                         gettext_noop("This is measured as a fraction of the cost of a "
1574                                                  "sequential page fetch.")
1575                 },
1576                 &cpu_tuple_cost,
1577                 DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX, NULL, NULL
1578         },
1579         {
1580                 {"cpu_index_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
1581                         gettext_noop("Sets the planner's estimate of processing cost for each "
1582                                                  "index tuple (row) during index scan."),
1583                         gettext_noop("This is measured as a fraction of the cost of a "
1584                                                  "sequential page fetch.")
1585                 },
1586                 &cpu_index_tuple_cost,
1587                 DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX, NULL, NULL
1588         },
1589         {
1590                 {"cpu_operator_cost", PGC_USERSET, QUERY_TUNING_COST,
1591                         gettext_noop("Sets the planner's estimate of processing cost of each operator in WHERE."),
1592                         gettext_noop("This is measured as a fraction of the cost of a sequential "
1593                                                  "page fetch.")
1594                 },
1595                 &cpu_operator_cost,
1596                 DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX, NULL, NULL
1597         },
1598
1599         {
1600                 {"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO,
1601                         gettext_noop("GEQO: selective pressure within the population."),
1602                         NULL
1603                 },
1604                 &Geqo_selection_bias,
1605                 DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS,
1606                 MAX_GEQO_SELECTION_BIAS, NULL, NULL
1607         },
1608
1609         {
1610                 {"bgwriter_lru_percent", PGC_SIGHUP, RESOURCES,
1611                         gettext_noop("Background writer percentage of LRU buffers to flush per round"),
1612                         NULL
1613                 },
1614                 &bgwriter_lru_percent,
1615                 1.0, 0.0, 100.0, NULL, NULL
1616         },
1617
1618         {
1619                 {"bgwriter_all_percent", PGC_SIGHUP, RESOURCES,
1620                         gettext_noop("Background writer percentage of all buffers to flush per round"),
1621                         NULL
1622                 },
1623                 &bgwriter_all_percent,
1624                 0.333, 0.0, 100.0, NULL, NULL
1625         },
1626
1627         {
1628                 {"seed", PGC_USERSET, UNGROUPED,
1629                         gettext_noop("Sets the seed for random-number generation."),
1630                         NULL,
1631                         GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1632                 },
1633                 &phony_random_seed,
1634                 0.5, 0.0, 1.0, assign_random_seed, show_random_seed
1635         },
1636
1637         {
1638                 {"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
1639                         gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
1640                         NULL
1641                 },
1642                 &autovacuum_vac_scale,
1643                 0.4, 0.0, 100.0, NULL, NULL
1644         },
1645         {
1646                 {"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
1647                         gettext_noop("Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples."),
1648                         NULL
1649                 },
1650                 &autovacuum_anl_scale,
1651                 0.2, 0.0, 100.0, NULL, NULL
1652         },
1653
1654         /* End-of-list marker */
1655         {
1656                 {NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL
1657         }
1658 };
1659
1660
1661 static struct config_string ConfigureNamesString[] =
1662 {
1663         {
1664                 {"archive_command", PGC_SIGHUP, WAL_SETTINGS,
1665                         gettext_noop("WAL archiving command."),
1666                         gettext_noop("The shell command that will be called to archive a WAL file.")
1667                 },
1668                 &XLogArchiveCommand,
1669                 "", NULL, NULL
1670         },
1671
1672         {
1673                 {"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
1674                         gettext_noop("Sets the client's character set encoding."),
1675                         NULL,
1676                         GUC_REPORT
1677                 },
1678                 &client_encoding_string,
1679                 "SQL_ASCII", assign_client_encoding, NULL
1680         },
1681
1682         {
1683                 {"client_min_messages", PGC_USERSET, LOGGING_WHEN,
1684                         gettext_noop("Sets the message levels that are sent to the client."),
1685                         gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, "
1686                                                  "DEBUG1, LOG, NOTICE, WARNING, and ERROR. Each level includes all the "
1687                                                  "levels that follow it. The later the level, the fewer messages are "
1688                                                  "sent.")
1689                 },
1690                 &client_min_messages_str,
1691                 "notice", assign_client_min_messages, NULL
1692         },
1693
1694         {
1695                 {"log_min_messages", PGC_SUSET, LOGGING_WHEN,
1696                         gettext_noop("Sets the message levels that are logged."),
1697                         gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, "
1698                         "INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. Each level "
1699                                                  "includes all the levels that follow it.")
1700                 },
1701                 &log_min_messages_str,
1702                 "notice", assign_log_min_messages, NULL
1703         },
1704
1705         {
1706                 {"log_error_verbosity", PGC_SUSET, LOGGING_WHEN,
1707                         gettext_noop("Sets the verbosity of logged messages."),
1708                         gettext_noop("Valid values are \"terse\", \"default\", and \"verbose\".")
1709                 },
1710                 &log_error_verbosity_str,
1711                 "default", assign_log_error_verbosity, NULL
1712         },
1713         {
1714                 {"log_statement", PGC_SUSET, LOGGING_WHAT,
1715                         gettext_noop("Sets the type of statements logged."),
1716                         gettext_noop("Valid values are \"none\", \"ddl\", \"mod\", and \"all\".")
1717                 },
1718                 &log_statement_str,
1719                 "none", assign_log_statement, NULL
1720         },
1721
1722         {
1723                 {"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
1724                         gettext_noop("Causes all statements generating error at or above this level to be logged."),
1725                         gettext_noop("All SQL statements that cause an error of the "
1726                                                  "specified level or a higher level are logged.")
1727                 },
1728                 &log_min_error_statement_str,
1729                 "panic", assign_min_error_statement, NULL
1730         },
1731
1732         {
1733                 {"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
1734                         gettext_noop("Controls information prefixed to each log line"),
1735                         gettext_noop("if blank no prefix is used")
1736                 },
1737                 &Log_line_prefix,
1738                 "", NULL, NULL
1739         },
1740
1741
1742         {
1743                 {"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
1744                         gettext_noop("Sets the display format for date and time values."),
1745                         gettext_noop("Also controls interpretation of ambiguous "
1746                                                  "date inputs."),
1747                         GUC_LIST_INPUT | GUC_REPORT
1748                 },
1749                 &datestyle_string,
1750                 "ISO, MDY", assign_datestyle, NULL
1751         },
1752
1753         {
1754                 {"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT,
1755                         gettext_noop("Sets the default tablespace to create tables and indexes in."),
1756                         gettext_noop("An empty string selects the database's default tablespace.")
1757                 },
1758                 &default_tablespace,
1759                 "", assign_default_tablespace, NULL
1760         },
1761
1762         {
1763                 {"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
1764                         gettext_noop("Sets the transaction isolation level of each new transaction."),
1765                         gettext_noop("Each SQL transaction has an isolation level, which "
1766                                                  "can be either \"read uncommitted\", \"read committed\", \"repeatable read\", or \"serializable\".")
1767                 },
1768                 &default_iso_level_string,
1769                 "read committed", assign_defaultxactisolevel, NULL
1770         },
1771
1772         {
1773                 {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
1774                         gettext_noop("Sets the path for dynamically loadable modules."),
1775                         gettext_noop("If a dynamically loadable module needs to be opened and "
1776                                                  "the specified name does not have a directory component (i.e., the "
1777                                                  "name does not contain a slash), the system will search this path for "
1778                                                  "the specified file."),
1779                         GUC_SUPERUSER_ONLY
1780                 },
1781                 &Dynamic_library_path,
1782                 "$libdir", NULL, NULL
1783         },
1784
1785         {
1786                 {"krb_server_keyfile", PGC_POSTMASTER, CONN_AUTH_SECURITY,
1787                         gettext_noop("Sets the location of the Kerberos server key file."),
1788                         NULL,
1789                         GUC_SUPERUSER_ONLY
1790                 },
1791                 &pg_krb_server_keyfile,
1792                 PG_KRB_SRVTAB, NULL, NULL
1793         },
1794
1795         {
1796                 {"krb_srvname", PGC_POSTMASTER, CONN_AUTH_SECURITY,
1797                         gettext_noop("Sets the name of the Kerberos service."),
1798                         NULL
1799                 },
1800                 &pg_krb_srvnam,
1801                 PG_KRB_SRVNAM, NULL, NULL
1802         },
1803
1804         {
1805                 {"krb_server_hostname", PGC_POSTMASTER, CONN_AUTH_SECURITY,
1806                         gettext_noop("Sets the hostname of the Kerberos server."),
1807                         NULL
1808                 },
1809                 &pg_krb_server_hostname,
1810                 NULL, NULL, NULL
1811         },
1812
1813         {
1814                 {"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1815                         gettext_noop("Sets the Bonjour broadcast service name."),
1816                         NULL
1817                 },
1818                 &bonjour_name,
1819                 "", NULL, NULL
1820         },
1821
1822         /* See main.c about why defaults for LC_foo are not all alike */
1823
1824         {
1825                 {"lc_collate", PGC_INTERNAL, CLIENT_CONN_LOCALE,
1826                         gettext_noop("Shows the collation order locale."),
1827                         NULL,
1828                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1829                 },
1830                 &locale_collate,
1831                 "C", NULL, NULL
1832         },
1833
1834         {
1835                 {"lc_ctype", PGC_INTERNAL, CLIENT_CONN_LOCALE,
1836                         gettext_noop("Shows the character classification and case conversion locale."),
1837                         NULL,
1838                         GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1839                 },
1840                 &locale_ctype,
1841                 "C", NULL, NULL
1842         },
1843
1844         {
1845                 {"lc_messages", PGC_SUSET, CLIENT_CONN_LOCALE,
1846                         gettext_noop("Sets the language in which messages are displayed."),
1847                         NULL
1848                 },
1849                 &locale_messages,
1850                 "", locale_messages_assign, NULL
1851         },
1852
1853         {
1854                 {"lc_monetary", PGC_USERSET, CLIENT_CONN_LOCALE,
1855                         gettext_noop("Sets the locale for formatting monetary amounts."),
1856                         NULL
1857                 },
1858                 &locale_monetary,
1859                 "C", locale_monetary_assign, NULL
1860         },
1861
1862         {
1863                 {"lc_numeric", PGC_USERSET, CLIENT_CONN_LOCALE,
1864                         gettext_noop("Sets the locale for formatting numbers."),
1865                         NULL
1866                 },
1867                 &locale_numeric,
1868                 "C", locale_numeric_assign, NULL
1869         },
1870
1871         {
1872                 {"lc_time", PGC_USERSET, CLIENT_CONN_LOCALE,
1873                         gettext_noop("Sets the locale for formatting date and time values."),
1874                         NULL
1875                 },
1876                 &locale_time,
1877                 "C", locale_time_assign, NULL
1878         },
1879
1880         {
1881                 {"preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
1882                         gettext_noop("Lists shared libraries to preload into server."),
1883                         NULL,
1884                         GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
1885                 },
1886                 &preload_libraries_string,
1887                 "", NULL, NULL
1888         },
1889
1890         {
1891                 {"regex_flavor", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1892                         gettext_noop("Sets the regular expression \"flavor\"."),
1893                         gettext_noop("This can be set to advanced, extended, or basic.")
1894                 },
1895                 &regex_flavor_string,
1896                 "advanced", assign_regex_flavor, NULL
1897         },
1898
1899         {
1900                 {"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT,
1901                         gettext_noop("Sets the schema search order for names that are not schema-qualified."),
1902                         NULL,
1903                         GUC_LIST_INPUT | GUC_LIST_QUOTE
1904                 },
1905                 &namespace_search_path,
1906                 "\"$user\",public", assign_search_path, NULL
1907         },
1908
1909         {
1910                 /* Can't be set in postgresql.conf */
1911                 {"server_encoding", PGC_INTERNAL, CLIENT_CONN_LOCALE,
1912                         gettext_noop("Sets the server (database) character set encoding."),
1913                         NULL,
1914                         GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1915                 },
1916                 &server_encoding_string,
1917                 "SQL_ASCII", NULL, NULL
1918         },
1919
1920         {
1921                 /* Can't be set in postgresql.conf */
1922                 {"server_version", PGC_INTERNAL, PRESET_OPTIONS,
1923                         gettext_noop("Shows the server version."),
1924                         NULL,
1925                         GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1926                 },
1927                 &server_version_string,
1928                 PG_VERSION, NULL, NULL
1929         },
1930
1931         {
1932                 /* Not for general use --- used by SET ROLE */
1933                 {"role", PGC_USERSET, UNGROUPED,
1934                         gettext_noop("Sets the current role."),
1935                         NULL,
1936                         GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1937                 },
1938                 &role_string,
1939                 "none", assign_role, show_role
1940         },
1941
1942         {
1943                 /* Not for general use --- used by SET SESSION AUTHORIZATION */
1944                 {"session_authorization", PGC_USERSET, UNGROUPED,
1945                         gettext_noop("Sets the session user name."),
1946                         NULL,
1947                         GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1948                 },
1949                 &session_authorization_string,
1950                 NULL, assign_session_authorization, show_session_authorization
1951         },
1952
1953         {
1954                 {"log_destination", PGC_SIGHUP, LOGGING_WHERE,
1955                         gettext_noop("Sets the destination for server log output."),
1956                         gettext_noop("Valid values are combinations of \"stderr\", \"syslog\", "
1957                                                  "and \"eventlog\", depending on the platform."),
1958                         GUC_LIST_INPUT
1959                 },
1960                 &log_destination_string,
1961                 "stderr", assign_log_destination, NULL
1962         },
1963         {
1964                 {"log_directory", PGC_SIGHUP, LOGGING_WHERE,
1965                         gettext_noop("Sets the destination directory for log files."),
1966                         gettext_noop("May be specified as relative to the data directory "
1967                                                  "or as absolute path."),
1968                         GUC_SUPERUSER_ONLY
1969                 },
1970                 &Log_directory,
1971                 "pg_log", assign_canonical_path, NULL
1972         },
1973         {
1974                 {"log_filename", PGC_SIGHUP, LOGGING_WHERE,
1975                         gettext_noop("Sets the file name pattern for log files."),
1976                         NULL,
1977                         GUC_SUPERUSER_ONLY
1978                 },
1979                 &Log_filename,
1980                 "postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL
1981         },
1982
1983 #ifdef HAVE_SYSLOG
1984         {
1985                 {"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
1986                         gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
1987                         gettext_noop("Valid values are LOCAL0, LOCAL1, LOCAL2, LOCAL3, "
1988                                                  "LOCAL4, LOCAL5, LOCAL6, LOCAL7.")
1989                 },
1990                 &syslog_facility_str,
1991                 "LOCAL0", assign_syslog_facility, NULL
1992         },
1993         {
1994                 {"syslog_ident", PGC_SIGHUP, LOGGING_WHERE,
1995                         gettext_noop("Sets the program name used to identify PostgreSQL "
1996                                                  "messages in syslog."),
1997                         NULL
1998                 },
1999                 &syslog_ident_str,
2000                 "postgres", assign_syslog_ident, NULL
2001         },
2002 #endif
2003
2004         {
2005                 {"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
2006                         gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
2007                         NULL,
2008                         GUC_REPORT
2009                 },
2010                 &timezone_string,
2011                 "UNKNOWN", assign_timezone, show_timezone
2012         },
2013
2014         {
2015                 {"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
2016                         gettext_noop("Sets the current transaction's isolation level."),
2017                         NULL,
2018                         GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2019                 },
2020                 &XactIsoLevel_string,
2021                 NULL, assign_XactIsoLevel, show_XactIsoLevel
2022         },
2023
2024         {
2025                 {"unix_socket_group", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2026                         gettext_noop("Sets the owning group of the Unix-domain socket."),
2027                         gettext_noop("(The owning user of the socket is always the user "
2028                                                  "that starts the server.)")
2029                 },
2030                 &Unix_socket_group,
2031                 "", NULL, NULL
2032         },
2033
2034         {
2035                 {"unix_socket_directory", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2036                         gettext_noop("Sets the directory where the Unix-domain socket will be created."),
2037                         NULL,
2038                         GUC_SUPERUSER_ONLY
2039                 },
2040                 &UnixSocketDir,
2041                 "", assign_canonical_path, NULL
2042         },
2043
2044         {
2045                 {"listen_addresses", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2046                         gettext_noop("Sets the host name or IP address(es) to listen to."),
2047                         NULL,
2048                         GUC_LIST_INPUT
2049                 },
2050                 &ListenAddresses,
2051                 "localhost", NULL, NULL
2052         },
2053
2054         {
2055                 {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
2056                         gettext_noop("Selects the method used for forcing WAL updates out to disk."),
2057                         NULL
2058                 },
2059                 &XLOG_sync_method,
2060                 XLOG_sync_method_default, assign_xlog_sync_method, NULL
2061         },
2062
2063         {
2064                 {"custom_variable_classes", PGC_SIGHUP, CUSTOM_OPTIONS,
2065                         gettext_noop("Sets the list of known custom variable classes."),
2066                         NULL,
2067                         GUC_LIST_INPUT | GUC_LIST_QUOTE
2068                 },
2069                 &custom_variable_classes,
2070                 NULL, assign_custom_variable_classes, NULL
2071         },
2072
2073         {
2074                 {"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
2075                         gettext_noop("Sets the server's data directory."),
2076                         NULL,
2077                         GUC_SUPERUSER_ONLY
2078                 },
2079                 &data_directory,
2080                 NULL, NULL, NULL
2081         },
2082
2083         {
2084                 {"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
2085                         gettext_noop("Sets the server's main configuration file."),
2086                         NULL,
2087                         GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
2088                 },
2089                 &ConfigFileName,
2090                 NULL, NULL, NULL
2091         },
2092
2093         {
2094                 {"hba_file", PGC_POSTMASTER, FILE_LOCATIONS,
2095                         gettext_noop("Sets the server's \"hba\" configuration file"),
2096                         NULL,
2097                         GUC_SUPERUSER_ONLY
2098                 },
2099                 &HbaFileName,
2100                 NULL, NULL, NULL
2101         },
2102
2103         {
2104                 {"ident_file", PGC_POSTMASTER, FILE_LOCATIONS,
2105                         gettext_noop("Sets the server's \"ident\" configuration file"),
2106                         NULL,
2107                         GUC_SUPERUSER_ONLY
2108                 },
2109                 &IdentFileName,
2110                 NULL, NULL, NULL
2111         },
2112
2113         {
2114                 {"external_pid_file", PGC_POSTMASTER, FILE_LOCATIONS,
2115                         gettext_noop("Writes the postmaster PID to the specified file."),
2116                         NULL,
2117                         GUC_SUPERUSER_ONLY
2118                 },
2119                 &external_pid_file,
2120                 NULL, assign_canonical_path, NULL
2121         },
2122
2123         /* End-of-list marker */
2124         {
2125                 {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
2126         }
2127 };
2128
2129
2130 /******** end of options list ********/
2131
2132
2133 /*
2134  * To allow continued support of obsolete names for GUC variables, we apply
2135  * the following mappings to any unrecognized name.  Note that an old name
2136  * should be mapped to a new one only if the new variable has very similar
2137  * semantics to the old.
2138  */
2139 static const char *const map_old_guc_names[] = {
2140         "sort_mem", "work_mem",
2141         "vacuum_mem", "maintenance_work_mem",
2142         NULL
2143 };
2144
2145
2146 /*
2147  * Actual lookup of variables is done through this single, sorted array.
2148  */
2149 static struct config_generic **guc_variables;
2150
2151 /* Current number of variables contained in the vector */
2152 static int      num_guc_variables;
2153
2154 /* Vector capacity */
2155 static int      size_guc_variables;
2156
2157
2158 static bool guc_dirty;                  /* TRUE if need to do commit/abort work */
2159
2160 static bool reporting_enabled;  /* TRUE to enable GUC_REPORT */
2161
2162
2163 static int      guc_var_compare(const void *a, const void *b);
2164 static int      guc_name_compare(const char *namea, const char *nameb);
2165 static void push_old_value(struct config_generic * gconf);
2166 static void ReportGUCOption(struct config_generic * record);
2167 static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
2168 static void ShowAllGUCConfig(DestReceiver *dest);
2169 static char *_ShowOption(struct config_generic * record);
2170
2171
2172 /*
2173  * Some infrastructure for checking malloc/strdup/realloc calls
2174  */
2175 static void *
2176 guc_malloc(int elevel, size_t size)
2177 {
2178         void       *data;
2179
2180         data = malloc(size);
2181         if (data == NULL)
2182                 ereport(elevel,
2183                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2184                                  errmsg("out of memory")));
2185         return data;
2186 }
2187
2188 static void *
2189 guc_realloc(int elevel, void *old, size_t size)
2190 {
2191         void       *data;
2192
2193         data = realloc(old, size);
2194         if (data == NULL)
2195                 ereport(elevel,
2196                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2197                                  errmsg("out of memory")));
2198         return data;
2199 }
2200
2201 static char *
2202 guc_strdup(int elevel, const char *src)
2203 {
2204         char       *data;
2205
2206         data = strdup(src);
2207         if (data == NULL)
2208                 ereport(elevel,
2209                                 (errcode(ERRCODE_OUT_OF_MEMORY),
2210                                  errmsg("out of memory")));
2211         return data;
2212 }
2213
2214
2215 /*
2216  * Support for assigning to a field of a string GUC item.  Free the prior
2217  * value if it's not referenced anywhere else in the item (including stacked
2218  * states).
2219  */
2220 static void
2221 set_string_field(struct config_string * conf, char **field, char *newval)
2222 {
2223         char       *oldval = *field;
2224         GucStack   *stack;
2225
2226         /* Do the assignment */
2227         *field = newval;
2228
2229         /* Exit if any duplicate references, or if old value was NULL anyway */
2230         if (oldval == NULL ||
2231                 oldval == *(conf->variable) ||
2232                 oldval == conf->reset_val ||
2233                 oldval == conf->tentative_val)
2234                 return;
2235         for (stack = conf->gen.stack; stack; stack = stack->prev)
2236         {
2237                 if (oldval == stack->tentative_val.stringval ||
2238                         oldval == stack->value.stringval)
2239                         return;
2240         }
2241
2242         /* Not used anymore, so free it */
2243         free(oldval);
2244 }
2245
2246 /*
2247  * Detect whether strval is referenced anywhere in a GUC string item
2248  */
2249 static bool
2250 string_field_used(struct config_string * conf, char *strval)
2251 {
2252         GucStack   *stack;
2253
2254         if (strval == *(conf->variable) ||
2255                 strval == conf->reset_val ||
2256                 strval == conf->tentative_val)
2257                 return true;
2258         for (stack = conf->gen.stack; stack; stack = stack->prev)
2259         {
2260                 if (strval == stack->tentative_val.stringval ||
2261                         strval == stack->value.stringval)
2262                         return true;
2263         }
2264         return false;
2265 }
2266
2267
2268 struct config_generic **
2269 get_guc_variables(void)
2270 {
2271         return guc_variables;
2272 }
2273
2274
2275 /*
2276  * Build the sorted array.      This is split out so that it could be
2277  * re-executed after startup (eg, we could allow loadable modules to
2278  * add vars, and then we'd need to re-sort).
2279  */
2280 void
2281 build_guc_variables(void)
2282 {
2283         int                     size_vars;
2284         int                     num_vars = 0;
2285         struct config_generic **guc_vars;
2286         int                     i;
2287
2288         for (i = 0; ConfigureNamesBool[i].gen.name; i++)
2289         {
2290                 struct config_bool *conf = &ConfigureNamesBool[i];
2291
2292                 /* Rather than requiring vartype to be filled in by hand, do this: */
2293                 conf->gen.vartype = PGC_BOOL;
2294                 num_vars++;
2295         }
2296
2297         for (i = 0; ConfigureNamesInt[i].gen.name; i++)
2298         {
2299                 struct config_int *conf = &ConfigureNamesInt[i];
2300
2301                 conf->gen.vartype = PGC_INT;
2302                 num_vars++;
2303         }
2304
2305         for (i = 0; ConfigureNamesReal[i].gen.name; i++)
2306         {
2307                 struct config_real *conf = &ConfigureNamesReal[i];
2308
2309                 conf->gen.vartype = PGC_REAL;
2310                 num_vars++;
2311         }
2312
2313         for (i = 0; ConfigureNamesString[i].gen.name; i++)
2314         {
2315                 struct config_string *conf = &ConfigureNamesString[i];
2316
2317                 conf->gen.vartype = PGC_STRING;
2318                 num_vars++;
2319         }
2320
2321         /*
2322          * Create table with 20% slack
2323          */
2324         size_vars = num_vars + num_vars / 4;
2325
2326         guc_vars = (struct config_generic **)
2327                 guc_malloc(FATAL, size_vars * sizeof(struct config_generic *));
2328
2329         num_vars = 0;
2330
2331         for (i = 0; ConfigureNamesBool[i].gen.name; i++)
2332                 guc_vars[num_vars++] = &ConfigureNamesBool[i].gen;
2333
2334         for (i = 0; ConfigureNamesInt[i].gen.name; i++)
2335                 guc_vars[num_vars++] = &ConfigureNamesInt[i].gen;
2336
2337         for (i = 0; ConfigureNamesReal[i].gen.name; i++)
2338                 guc_vars[num_vars++] = &ConfigureNamesReal[i].gen;
2339
2340         for (i = 0; ConfigureNamesString[i].gen.name; i++)
2341                 guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
2342
2343         if (guc_variables)
2344                 free(guc_variables);
2345         guc_variables = guc_vars;
2346         num_guc_variables = num_vars;
2347         size_guc_variables = size_vars;
2348         qsort((void *) guc_variables, num_guc_variables,
2349                   sizeof(struct config_generic *), guc_var_compare);
2350 }
2351
2352 static bool
2353 is_custom_class(const char *name, int dotPos)
2354 {
2355         /*
2356          * assign_custom_variable_classes() has made sure no empty identifiers or
2357          * whitespace exists in the variable
2358          */
2359         bool            result = false;
2360         const char *ccs = GetConfigOption("custom_variable_classes");
2361
2362         if (ccs != NULL)
2363         {
2364                 const char *start = ccs;
2365
2366                 for (;; ++ccs)
2367                 {
2368                         int                     c = *ccs;
2369
2370                         if (c == 0 || c == ',')
2371                         {
2372                                 if (dotPos == ccs - start && strncmp(start, name, dotPos) == 0)
2373                                 {
2374                                         result = true;
2375                                         break;
2376                                 }
2377                                 if (c == 0)
2378                                         break;
2379                                 start = ccs + 1;
2380                         }
2381                 }
2382         }
2383         return result;
2384 }
2385
2386 /*
2387  * Add a new GUC variable to the list of known variables. The
2388  * list is expanded if needed.
2389  */
2390 static bool
2391 add_guc_variable(struct config_generic * var, int elevel)
2392 {
2393         if (num_guc_variables + 1 >= size_guc_variables)
2394         {
2395                 /*
2396                  * Increase the vector by 25%
2397                  */
2398                 int                     size_vars = size_guc_variables + size_guc_variables / 4;
2399                 struct config_generic **guc_vars;
2400
2401                 if (size_vars == 0)
2402                 {
2403                         size_vars = 100;
2404                         guc_vars = (struct config_generic **)
2405                                 guc_malloc(elevel, size_vars * sizeof(struct config_generic *));
2406                 }
2407                 else
2408                 {
2409                         guc_vars = (struct config_generic **)
2410                                 guc_realloc(elevel, guc_variables, size_vars * sizeof(struct config_generic *));
2411                 }
2412
2413                 if (guc_vars == NULL)
2414                         return false;           /* out of memory */
2415
2416                 guc_variables = guc_vars;
2417                 size_guc_variables = size_vars;
2418         }
2419         guc_variables[num_guc_variables++] = var;
2420         qsort((void *) guc_variables, num_guc_variables,
2421                   sizeof(struct config_generic *), guc_var_compare);
2422         return true;
2423 }
2424
2425 /*
2426  * Create and add a placeholder variable. It's presumed to belong
2427  * to a valid custom variable class at this point.
2428  */
2429 static struct config_string *
2430 add_placeholder_variable(const char *name, int elevel)
2431 {
2432         size_t          sz = sizeof(struct config_string) + sizeof(char *);
2433         struct config_string *var;
2434         struct config_generic *gen;
2435
2436         var = (struct config_string *) guc_malloc(elevel, sz);
2437         if (var == NULL)
2438                 return NULL;
2439
2440         gen = &var->gen;
2441         memset(var, 0, sz);
2442
2443         gen->name = guc_strdup(elevel, name);
2444         if (gen->name == NULL)
2445         {
2446                 free(var);
2447                 return NULL;
2448         }
2449
2450         gen->context = PGC_USERSET;
2451         gen->group = CUSTOM_OPTIONS;
2452         gen->short_desc = "GUC placeholder variable";
2453         gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER;
2454         gen->vartype = PGC_STRING;
2455
2456         /*
2457          * The char* is allocated at the end of the struct since we have no
2458          * 'static' place to point to.
2459          */
2460         var->variable = (char **) (var + 1);
2461
2462         if (!add_guc_variable((struct config_generic *) var, elevel))
2463         {
2464                 free((void *) gen->name);
2465                 free(var);
2466                 return NULL;
2467         }
2468
2469         return var;
2470 }
2471
2472 /*
2473  * Look up option NAME. If it exists, return a pointer to its record,
2474  * else return NULL.
2475  */
2476 static struct config_generic *
2477 find_option(const char *name, int elevel)
2478 {
2479         const char *dot;
2480         const char **key = &name;
2481         struct config_generic **res;
2482         int                     i;
2483
2484         Assert(name);
2485
2486         /*
2487          * By equating const char ** with struct config_generic *, we are assuming
2488          * the name field is first in config_generic.
2489          */
2490         res = (struct config_generic **) bsearch((void *) &key,
2491                                                                                          (void *) guc_variables,
2492                                                                                          num_guc_variables,
2493                                                                                          sizeof(struct config_generic *),
2494                                                                                          guc_var_compare);
2495         if (res)
2496                 return *res;
2497
2498         /*
2499          * See if the name is an obsolete name for a variable.  We assume that the
2500          * set of supported old names is short enough that a brute-force search is
2501          * the best way.
2502          */
2503         for (i = 0; map_old_guc_names[i] != NULL; i += 2)
2504         {
2505                 if (guc_name_compare(name, map_old_guc_names[i]) == 0)
2506                         return find_option(map_old_guc_names[i + 1], elevel);
2507         }
2508
2509         /*
2510          * Check if the name is qualified, and if so, check if the qualifier maps
2511          * to a custom variable class.
2512          */
2513         dot = strchr(name, GUC_QUALIFIER_SEPARATOR);
2514         if (dot != NULL && is_custom_class(name, dot - name))
2515                 /* Add a placeholder variable for this name */
2516                 return (struct config_generic *) add_placeholder_variable(name, elevel);
2517
2518         /* Unknown name */
2519         return NULL;
2520 }
2521
2522
2523 /*
2524  * comparator for qsorting and bsearching guc_variables array
2525  */
2526 static int
2527 guc_var_compare(const void *a, const void *b)
2528 {
2529         struct config_generic *confa = *(struct config_generic **) a;
2530         struct config_generic *confb = *(struct config_generic **) b;
2531
2532         return guc_name_compare(confa->name, confb->name);
2533 }
2534
2535
2536 static int
2537 guc_name_compare(const char *namea, const char *nameb)
2538 {
2539         /*
2540          * The temptation to use strcasecmp() here must be resisted, because the
2541          * array ordering has to remain stable across setlocale() calls. So, build
2542          * our own with a simple ASCII-only downcasing.
2543          */
2544         while (*namea && *nameb)
2545         {
2546                 char            cha = *namea++;
2547                 char            chb = *nameb++;
2548
2549                 if (cha >= 'A' && cha <= 'Z')
2550                         cha += 'a' - 'A';
2551                 if (chb >= 'A' && chb <= 'Z')
2552                         chb += 'a' - 'A';
2553                 if (cha != chb)
2554                         return cha - chb;
2555         }
2556         if (*namea)
2557                 return 1;                               /* a is longer */
2558         if (*nameb)
2559                 return -1;                              /* b is longer */
2560         return 0;
2561 }
2562
2563
2564 /*
2565  * Initialize GUC options during program startup.
2566  *
2567  * Note that we cannot read the config file yet, since we have not yet
2568  * processed command-line switches.
2569  */
2570 void
2571 InitializeGUCOptions(void)
2572 {
2573         int                     i;
2574         char       *env;
2575
2576         /*
2577          * Build sorted array of all GUC variables.
2578          */
2579         build_guc_variables();
2580
2581         /*
2582          * Load all variables with their compiled-in defaults, and initialize
2583          * status fields as needed.
2584          */
2585         for (i = 0; i < num_guc_variables; i++)
2586         {
2587                 struct config_generic *gconf = guc_variables[i];
2588
2589                 gconf->status = 0;
2590                 gconf->reset_source = PGC_S_DEFAULT;
2591                 gconf->tentative_source = PGC_S_DEFAULT;
2592                 gconf->source = PGC_S_DEFAULT;
2593                 gconf->stack = NULL;
2594
2595                 switch (gconf->vartype)
2596                 {
2597                         case PGC_BOOL:
2598                                 {
2599                                         struct config_bool *conf = (struct config_bool *) gconf;
2600
2601                                         if (conf->assign_hook)
2602                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
2603                                                                                                    PGC_S_DEFAULT))
2604                                                         elog(FATAL, "failed to initialize %s to %d",
2605                                                                  conf->gen.name, (int) conf->reset_val);
2606                                         *conf->variable = conf->reset_val;
2607                                         break;
2608                                 }
2609                         case PGC_INT:
2610                                 {
2611                                         struct config_int *conf = (struct config_int *) gconf;
2612
2613                                         Assert(conf->reset_val >= conf->min);
2614                                         Assert(conf->reset_val <= conf->max);
2615                                         if (conf->assign_hook)
2616                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
2617                                                                                                    PGC_S_DEFAULT))
2618                                                         elog(FATAL, "failed to initialize %s to %d",
2619                                                                  conf->gen.name, conf->reset_val);
2620                                         *conf->variable = conf->reset_val;
2621                                         break;
2622                                 }
2623                         case PGC_REAL:
2624                                 {
2625                                         struct config_real *conf = (struct config_real *) gconf;
2626
2627                                         Assert(conf->reset_val >= conf->min);
2628                                         Assert(conf->reset_val <= conf->max);
2629                                         if (conf->assign_hook)
2630                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
2631                                                                                                    PGC_S_DEFAULT))
2632                                                         elog(FATAL, "failed to initialize %s to %g",
2633                                                                  conf->gen.name, conf->reset_val);
2634                                         *conf->variable = conf->reset_val;
2635                                         break;
2636                                 }
2637                         case PGC_STRING:
2638                                 {
2639                                         struct config_string *conf = (struct config_string *) gconf;
2640                                         char       *str;
2641
2642                                         *conf->variable = NULL;
2643                                         conf->reset_val = NULL;
2644                                         conf->tentative_val = NULL;
2645
2646                                         if (conf->boot_val == NULL)
2647                                         {
2648                                                 /* Cannot set value yet */
2649                                                 break;
2650                                         }
2651
2652                                         str = guc_strdup(FATAL, conf->boot_val);
2653                                         conf->reset_val = str;
2654
2655                                         if (conf->assign_hook)
2656                                         {
2657                                                 const char *newstr;
2658
2659                                                 newstr = (*conf->assign_hook) (str, true,
2660                                                                                                            PGC_S_DEFAULT);
2661                                                 if (newstr == NULL)
2662                                                 {
2663                                                         elog(FATAL, "failed to initialize %s to \"%s\"",
2664                                                                  conf->gen.name, str);
2665                                                 }
2666                                                 else if (newstr != str)
2667                                                 {
2668                                                         free(str);
2669
2670                                                         /*
2671                                                          * See notes in set_config_option about casting
2672                                                          */
2673                                                         str = (char *) newstr;
2674                                                         conf->reset_val = str;
2675                                                 }
2676                                         }
2677                                         *conf->variable = str;
2678                                         break;
2679                                 }
2680                 }
2681         }
2682
2683         guc_dirty = false;
2684
2685         reporting_enabled = false;
2686
2687         /*
2688          * Prevent any attempt to override the transaction modes from
2689          * non-interactive sources.
2690          */
2691         SetConfigOption("transaction_isolation", "default",
2692                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
2693         SetConfigOption("transaction_read_only", "no",
2694                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
2695
2696         /*
2697          * For historical reasons, some GUC parameters can receive defaults from
2698          * environment variables.  Process those settings.
2699          */
2700
2701         env = getenv("PGPORT");
2702         if (env != NULL)
2703                 SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
2704
2705         env = getenv("PGDATESTYLE");
2706         if (env != NULL)
2707                 SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
2708
2709         env = getenv("PGCLIENTENCODING");
2710         if (env != NULL)
2711                 SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
2712 }
2713
2714
2715 /*
2716  * Select the configuration files and data directory to be used, and
2717  * do the initial read of postgresql.conf.
2718  *
2719  * This is called after processing command-line switches.
2720  *              userDoption is the -D switch value if any (NULL if unspecified).
2721  *              progname is just for use in error messages.
2722  *
2723  * Returns true on success; on failure, prints a suitable error message
2724  * to stderr and returns false.
2725  */
2726 bool
2727 SelectConfigFiles(const char *userDoption, const char *progname)
2728 {
2729         char       *configdir;
2730         char       *fname;
2731         struct stat stat_buf;
2732
2733         /* configdir is -D option, or $PGDATA if no -D */
2734         if (userDoption)
2735                 configdir = make_absolute_path(userDoption);
2736         else
2737                 configdir = make_absolute_path(getenv("PGDATA"));
2738
2739         /*
2740          * Find the configuration file: if config_file was specified on the
2741          * command line, use it, else use configdir/postgresql.conf.  In any case
2742          * ensure the result is an absolute path, so that it will be interpreted
2743          * the same way by future backends.
2744          */
2745         if (ConfigFileName)
2746                 fname = make_absolute_path(ConfigFileName);
2747         else if (configdir)
2748         {
2749                 fname = guc_malloc(FATAL,
2750                                                    strlen(configdir) + strlen(CONFIG_FILENAME) + 2);
2751                 sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);
2752         }
2753         else
2754         {
2755                 write_stderr("%s does not know where to find the server configuration file.\n"
2756                                          "You must specify the --config-file or -D invocation "
2757                                          "option or set the PGDATA environment variable.\n",
2758                                          progname);
2759                 return false;
2760         }
2761
2762         /*
2763          * Set the ConfigFileName GUC variable to its final value, ensuring that
2764          * it can't be overridden later.
2765          */
2766         SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
2767         free(fname);
2768
2769         /*
2770          * Now read the config file for the first time.
2771          */
2772         if (stat(ConfigFileName, &stat_buf) != 0)
2773         {
2774                 write_stderr("%s cannot access the server configuration file \"%s\": %s\n",
2775                                          progname, ConfigFileName, strerror(errno));
2776                 return false;
2777         }
2778
2779         ProcessConfigFile(PGC_POSTMASTER);
2780
2781         /*
2782          * If the data_directory GUC variable has been set, use that as DataDir;
2783          * otherwise use configdir if set; else punt.
2784          *
2785          * Note: SetDataDir will copy and absolute-ize its argument, so we don't
2786          * have to.
2787          */
2788         if (data_directory)
2789                 SetDataDir(data_directory);
2790         else if (configdir)
2791                 SetDataDir(configdir);
2792         else
2793         {
2794                 write_stderr("%s does not know where to find the database system data.\n"
2795                                          "This can be specified as \"data_directory\" in \"%s\", "
2796                                          "or by the -D invocation option, or by the "
2797                                          "PGDATA environment variable.\n",
2798                                          progname, ConfigFileName);
2799                 return false;
2800         }
2801
2802         /*
2803          * Reflect the final DataDir value back into the data_directory GUC var.
2804          * (If you are wondering why we don't just make them a single variable,
2805          * it's because the EXEC_BACKEND case needs DataDir to be transmitted to
2806          * child backends specially.  XXX is that still true?  Given that we now
2807          * chdir to DataDir, EXEC_BACKEND can read the config file without knowing
2808          * DataDir in advance.)
2809          */
2810         SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
2811
2812         /*
2813          * Figure out where pg_hba.conf is, and make sure the path is absolute.
2814          */
2815         if (HbaFileName)
2816                 fname = make_absolute_path(HbaFileName);
2817         else if (configdir)
2818         {
2819                 fname = guc_malloc(FATAL,
2820                                                    strlen(configdir) + strlen(HBA_FILENAME) + 2);
2821                 sprintf(fname, "%s/%s", configdir, HBA_FILENAME);
2822         }
2823         else
2824         {
2825                 write_stderr("%s does not know where to find the \"hba\" configuration file.\n"
2826                                          "This can be specified as \"hba_file\" in \"%s\", "
2827                                          "or by the -D invocation option, or by the "
2828                                          "PGDATA environment variable.\n",
2829                                          progname, ConfigFileName);
2830                 return false;
2831         }
2832         SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
2833         free(fname);
2834
2835         /*
2836          * Likewise for pg_ident.conf.
2837          */
2838         if (IdentFileName)
2839                 fname = make_absolute_path(IdentFileName);
2840         else if (configdir)
2841         {
2842                 fname = guc_malloc(FATAL,
2843                                                    strlen(configdir) + strlen(IDENT_FILENAME) + 2);
2844                 sprintf(fname, "%s/%s", configdir, IDENT_FILENAME);
2845         }
2846         else
2847         {
2848                 write_stderr("%s does not know where to find the \"ident\" configuration file.\n"
2849                                          "This can be specified as \"ident_file\" in \"%s\", "
2850                                          "or by the -D invocation option, or by the "
2851                                          "PGDATA environment variable.\n",
2852                                          progname, ConfigFileName);
2853                 return false;
2854         }
2855         SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
2856         free(fname);
2857
2858         free(configdir);
2859
2860         return true;
2861 }
2862
2863
2864 /*
2865  * Reset all options to their saved default values (implements RESET ALL)
2866  */
2867 void
2868 ResetAllOptions(void)
2869 {
2870         int                     i;
2871
2872         for (i = 0; i < num_guc_variables; i++)
2873         {
2874                 struct config_generic *gconf = guc_variables[i];
2875
2876                 /* Don't reset non-SET-able values */
2877                 if (gconf->context != PGC_SUSET &&
2878                         gconf->context != PGC_USERSET)
2879                         continue;
2880                 /* Don't reset if special exclusion from RESET ALL */
2881                 if (gconf->flags & GUC_NO_RESET_ALL)
2882                         continue;
2883                 /* No need to reset if wasn't SET */
2884                 if (gconf->source <= PGC_S_OVERRIDE)
2885                         continue;
2886
2887                 /* Save old value to support transaction abort */
2888                 push_old_value(gconf);
2889
2890                 switch (gconf->vartype)
2891                 {
2892                         case PGC_BOOL:
2893                                 {
2894                                         struct config_bool *conf = (struct config_bool *) gconf;
2895
2896                                         if (conf->assign_hook)
2897                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
2898                                                                                                    PGC_S_SESSION))
2899                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
2900                                         *conf->variable = conf->reset_val;
2901                                         conf->tentative_val = conf->reset_val;
2902                                         conf->gen.source = conf->gen.reset_source;
2903                                         conf->gen.tentative_source = conf->gen.reset_source;
2904                                         conf->gen.status |= GUC_HAVE_TENTATIVE;
2905                                         guc_dirty = true;
2906                                         break;
2907                                 }
2908                         case PGC_INT:
2909                                 {
2910                                         struct config_int *conf = (struct config_int *) gconf;
2911
2912                                         if (conf->assign_hook)
2913                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
2914                                                                                                    PGC_S_SESSION))
2915                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
2916                                         *conf->variable = conf->reset_val;
2917                                         conf->tentative_val = conf->reset_val;
2918                                         conf->gen.source = conf->gen.reset_source;
2919                                         conf->gen.tentative_source = conf->gen.reset_source;
2920                                         conf->gen.status |= GUC_HAVE_TENTATIVE;
2921                                         guc_dirty = true;
2922                                         break;
2923                                 }
2924                         case PGC_REAL:
2925                                 {
2926                                         struct config_real *conf = (struct config_real *) gconf;
2927
2928                                         if (conf->assign_hook)
2929                                                 if (!(*conf->assign_hook) (conf->reset_val, true,
2930                                                                                                    PGC_S_SESSION))
2931                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
2932                                         *conf->variable = conf->reset_val;
2933                                         conf->tentative_val = conf->reset_val;
2934                                         conf->gen.source = conf->gen.reset_source;
2935                                         conf->gen.tentative_source = conf->gen.reset_source;
2936                                         conf->gen.status |= GUC_HAVE_TENTATIVE;
2937                                         guc_dirty = true;
2938                                         break;
2939                                 }
2940                         case PGC_STRING:
2941                                 {
2942                                         struct config_string *conf = (struct config_string *) gconf;
2943                                         char       *str;
2944
2945                                         if (conf->reset_val == NULL)
2946                                         {
2947                                                 /* Nothing to reset to, as yet; so do nothing */
2948                                                 break;
2949                                         }
2950
2951                                         /* We need not strdup here */
2952                                         str = conf->reset_val;
2953
2954                                         if (conf->assign_hook)
2955                                         {
2956                                                 const char *newstr;
2957
2958                                                 newstr = (*conf->assign_hook) (str, true,
2959                                                                                                            PGC_S_SESSION);
2960                                                 if (newstr == NULL)
2961                                                         elog(ERROR, "failed to reset %s", conf->gen.name);
2962                                                 else if (newstr != str)
2963                                                 {
2964                                                         /*
2965                                                          * See notes in set_config_option about casting
2966                                                          */
2967                                                         str = (char *) newstr;
2968                                                 }
2969                                         }
2970
2971                                         set_string_field(conf, conf->variable, str);
2972                                         set_string_field(conf, &conf->tentative_val, str);
2973                                         conf->gen.source = conf->gen.reset_source;
2974                                         conf->gen.tentative_source = conf->gen.reset_source;
2975                                         conf->gen.status |= GUC_HAVE_TENTATIVE;
2976                                         guc_dirty = true;
2977                                         break;
2978                                 }
2979                 }
2980
2981                 if (gconf->flags & GUC_REPORT)
2982                         ReportGUCOption(gconf);
2983         }
2984 }
2985
2986
2987 /*
2988  * push_old_value
2989  *              Push previous state during first assignment to a GUC variable
2990  *              within a particular transaction.
2991  *
2992  * We have to be willing to "back-fill" the state stack if the first
2993  * assignment occurs within a subtransaction nested several levels deep.
2994  * This ensures that if an intermediate transaction aborts, it will have
2995  * the proper value available to restore the setting to.
2996  */
2997 static void
2998 push_old_value(struct config_generic * gconf)
2999 {
3000         int                     my_level = GetCurrentTransactionNestLevel();
3001         GucStack   *stack;
3002
3003         /* If we're not inside a transaction, do nothing */
3004         if (my_level == 0)
3005                 return;
3006
3007         for (;;)
3008         {
3009                 /* Done if we already pushed it at this nesting depth */
3010                 if (gconf->stack && gconf->stack->nest_level >= my_level)
3011                         return;
3012
3013                 /*
3014                  * We keep all the stack entries in TopTransactionContext so as to
3015                  * avoid allocation problems when a subtransaction back-fills stack
3016                  * entries for upper transaction levels.
3017                  */
3018                 stack = (GucStack *) MemoryContextAlloc(TopTransactionContext,
3019                                                                                                 sizeof(GucStack));
3020
3021                 stack->prev = gconf->stack;
3022                 stack->nest_level = stack->prev ? stack->prev->nest_level + 1 : 1;
3023                 stack->status = gconf->status;
3024                 stack->tentative_source = gconf->tentative_source;
3025                 stack->source = gconf->source;
3026
3027                 switch (gconf->vartype)
3028                 {
3029                         case PGC_BOOL:
3030                                 stack->tentative_val.boolval =
3031                                         ((struct config_bool *) gconf)->tentative_val;
3032                                 stack->value.boolval =
3033                                         *((struct config_bool *) gconf)->variable;
3034                                 break;
3035
3036                         case PGC_INT:
3037                                 stack->tentative_val.intval =
3038                                         ((struct config_int *) gconf)->tentative_val;
3039                                 stack->value.intval =
3040                                         *((struct config_int *) gconf)->variable;
3041                                 break;
3042
3043                         case PGC_REAL:
3044                                 stack->tentative_val.realval =
3045                                         ((struct config_real *) gconf)->tentative_val;
3046                                 stack->value.realval =
3047                                         *((struct config_real *) gconf)->variable;
3048                                 break;
3049
3050                         case PGC_STRING:
3051                                 stack->tentative_val.stringval =
3052                                         ((struct config_string *) gconf)->tentative_val;
3053                                 stack->value.stringval =
3054                                         *((struct config_string *) gconf)->variable;
3055                                 break;
3056                 }
3057
3058                 gconf->stack = stack;
3059
3060                 /* Set state to indicate nothing happened yet within this level */
3061                 gconf->status = GUC_HAVE_STACK;
3062
3063                 /* Ensure we remember to pop at end of xact */
3064                 guc_dirty = true;
3065         }
3066 }
3067
3068 /*
3069  * Do GUC processing at transaction or subtransaction commit or abort.
3070  */
3071 void
3072 AtEOXact_GUC(bool isCommit, bool isSubXact)
3073 {
3074         int                     my_level;
3075         int                     i;
3076
3077         /* Quick exit if nothing's changed in this transaction */
3078         if (!guc_dirty)
3079                 return;
3080
3081         my_level = GetCurrentTransactionNestLevel();
3082         Assert(isSubXact ? (my_level > 1) : (my_level == 1));
3083
3084         for (i = 0; i < num_guc_variables; i++)
3085         {
3086                 struct config_generic *gconf = guc_variables[i];
3087                 int                     my_status = gconf->status;
3088                 GucStack   *stack = gconf->stack;
3089                 bool            useTentative;
3090                 bool            changed;
3091
3092                 /*
3093                  * Skip if nothing's happened to this var in this transaction
3094                  */
3095                 if (my_status == 0)
3096                 {
3097                         Assert(stack == NULL);
3098                         continue;
3099                 }
3100                 /* Assert that we stacked old value before changing it */
3101                 Assert(stack != NULL && (my_status & GUC_HAVE_STACK));
3102                 /* However, the last change may have been at an outer xact level */
3103                 if (stack->nest_level < my_level)
3104                         continue;
3105                 Assert(stack->nest_level == my_level);
3106
3107                 /*
3108                  * We will pop the stack entry.  Start by restoring outer xact status
3109                  * (since we may want to modify it below).      Be careful to use
3110                  * my_status to reference the inner xact status below this point...
3111                  */
3112                 gconf->status = stack->status;
3113
3114                 /*
3115                  * We have two cases:
3116                  *
3117                  * If commit and HAVE_TENTATIVE, set actual value to tentative (this
3118                  * is to override a SET LOCAL if one occurred later than SET). We keep
3119                  * the tentative value and propagate HAVE_TENTATIVE to the parent
3120                  * status, allowing the SET's effect to percolate up. (But if we're
3121                  * exiting the outermost transaction, we'll drop the HAVE_TENTATIVE
3122                  * bit below.)
3123                  *
3124                  * Otherwise, we have a transaction that aborted or executed only SET
3125                  * LOCAL (or no SET at all).  In either case it should have no further
3126                  * effect, so restore both tentative and actual values from the stack
3127                  * entry.
3128                  */
3129
3130                 useTentative = isCommit && (my_status & GUC_HAVE_TENTATIVE) != 0;
3131                 changed = false;
3132
3133                 switch (gconf->vartype)
3134                 {
3135                         case PGC_BOOL:
3136                                 {
3137                                         struct config_bool *conf = (struct config_bool *) gconf;
3138                                         bool            newval;
3139                                         GucSource       newsource;
3140
3141                                         if (useTentative)
3142                                         {
3143                                                 newval = conf->tentative_val;
3144                                                 newsource = conf->gen.tentative_source;
3145                                                 conf->gen.status |= GUC_HAVE_TENTATIVE;
3146                                         }
3147                                         else
3148                                         {
3149                                                 newval = stack->value.boolval;
3150                                                 newsource = stack->source;
3151                                                 conf->tentative_val = stack->tentative_val.boolval;
3152                                                 conf->gen.tentative_source = stack->tentative_source;
3153                                         }
3154
3155                                         if (*conf->variable != newval)
3156                                         {
3157                                                 if (conf->assign_hook)
3158                                                         if (!(*conf->assign_hook) (newval,
3159                                                                                                            true, PGC_S_OVERRIDE))
3160                                                                 elog(LOG, "failed to commit %s",
3161                                                                          conf->gen.name);
3162                                                 *conf->variable = newval;
3163                                                 changed = true;
3164                                         }
3165                                         conf->gen.source = newsource;
3166                                         break;
3167                                 }
3168                         case PGC_INT:
3169                                 {
3170                                         struct config_int *conf = (struct config_int *) gconf;
3171                                         int                     newval;
3172                                         GucSource       newsource;
3173
3174                                         if (useTentative)
3175                                         {
3176                                                 newval = conf->tentative_val;
3177                                                 newsource = conf->gen.tentative_source;
3178                                                 conf->gen.status |= GUC_HAVE_TENTATIVE;
3179                                         }
3180                                         else
3181                                         {
3182                                                 newval = stack->value.intval;
3183                                                 newsource = stack->source;
3184                                                 conf->tentative_val = stack->tentative_val.intval;
3185                                                 conf->gen.tentative_source = stack->tentative_source;
3186                                         }
3187
3188                                         if (*conf->variable != newval)
3189                                         {
3190                                                 if (conf->assign_hook)
3191                                                         if (!(*conf->assign_hook) (newval,
3192                                                                                                            true, PGC_S_OVERRIDE))
3193                                                                 elog(LOG, "failed to commit %s",
3194                                                                          conf->gen.name);
3195                                                 *conf->variable = newval;
3196                                                 changed = true;
3197                                         }
3198                                         conf->gen.source = newsource;
3199                                         break;
3200                                 }
3201                         case PGC_REAL:
3202                                 {
3203                                         struct config_real *conf = (struct config_real *) gconf;
3204                                         double          newval;
3205                                         GucSource       newsource;
3206
3207                                         if (useTentative)
3208                                         {
3209                                                 newval = conf->tentative_val;
3210                                                 newsource = conf->gen.tentative_source;
3211                                                 conf->gen.status |= GUC_HAVE_TENTATIVE;
3212                                         }
3213                                         else
3214                                         {
3215                                                 newval = stack->value.realval;
3216                                                 newsource = stack->source;
3217                                                 conf->tentative_val = stack->tentative_val.realval;
3218                                                 conf->gen.tentative_source = stack->tentative_source;
3219                                         }
3220
3221                                         if (*conf->variable != newval)
3222                                         {
3223                                                 if (conf->assign_hook)
3224                                                         if (!(*conf->assign_hook) (newval,
3225                                                                                                            true, PGC_S_OVERRIDE))
3226                                                                 elog(LOG, "failed to commit %s",
3227                                                                          conf->gen.name);
3228                                                 *conf->variable = newval;
3229                                                 changed = true;
3230                                         }
3231                                         conf->gen.source = newsource;
3232                                         break;
3233                                 }
3234                         case PGC_STRING:
3235                                 {
3236                                         struct config_string *conf = (struct config_string *) gconf;
3237                                         char       *newval;
3238                                         GucSource       newsource;
3239
3240                                         if (useTentative)
3241                                         {
3242                                                 newval = conf->tentative_val;
3243                                                 newsource = conf->gen.tentative_source;
3244                                                 conf->gen.status |= GUC_HAVE_TENTATIVE;
3245                                         }
3246                                         else
3247                                         {
3248                                                 newval = stack->value.stringval;
3249                                                 newsource = stack->source;
3250                                                 set_string_field(conf, &conf->tentative_val,
3251                                                                                  stack->tentative_val.stringval);
3252                                                 conf->gen.tentative_source = stack->tentative_source;
3253                                         }
3254
3255                                         if (*conf->variable != newval)
3256                                         {
3257                                                 if (conf->assign_hook)
3258                                                 {
3259                                                         const char *newstr;
3260
3261                                                         newstr = (*conf->assign_hook) (newval, true,
3262                                                                                                                    PGC_S_OVERRIDE);
3263                                                         if (newstr == NULL)
3264                                                                 elog(LOG, "failed to commit %s",
3265                                                                          conf->gen.name);
3266                                                         else if (newstr != newval)
3267                                                         {
3268                                                                 /*
3269                                                                  * If newval should now be freed, it'll be
3270                                                                  * taken care of below.
3271                                                                  *
3272                                                                  * See notes in set_config_option about
3273                                                                  * casting
3274                                                                  */
3275                                                                 newval = (char *) newstr;
3276                                                         }
3277                                                 }
3278
3279                                                 set_string_field(conf, conf->variable, newval);
3280                                                 changed = true;
3281                                         }
3282                                         conf->gen.source = newsource;
3283                                         /* Release stacked values if not used anymore */
3284                                         set_string_field(conf, &stack->value.stringval,
3285                                                                          NULL);
3286                                         set_string_field(conf, &stack->tentative_val.stringval,
3287                                                                          NULL);
3288                                         /* Don't store tentative value separately after commit */
3289                                         if (!isSubXact)
3290                                                 set_string_field(conf, &conf->tentative_val, NULL);
3291                                         break;
3292                                 }
3293                 }
3294
3295                 /* Finish popping the state stack */
3296                 gconf->stack = stack->prev;
3297                 pfree(stack);
3298
3299                 /*
3300                  * If we're now out of all xact levels, forget TENTATIVE status bit;
3301                  * there's nothing tentative about the value anymore.
3302                  */
3303                 if (!isSubXact)
3304                 {
3305                         Assert(gconf->stack == NULL);
3306                         gconf->status = 0;
3307                 }
3308
3309                 /* Report new value if we changed it */
3310                 if (changed && (gconf->flags & GUC_REPORT))
3311                         ReportGUCOption(gconf);
3312         }
3313
3314         /*
3315          * If we're now out of all xact levels, we can clear guc_dirty. (Note: we
3316          * cannot reset guc_dirty when exiting a subtransaction, because we know
3317          * that all outer transaction levels will have stacked values to deal
3318          * with.)
3319          */
3320         if (!isSubXact)
3321                 guc_dirty = false;
3322 }
3323
3324
3325 /*
3326  * Start up automatic reporting of changes to variables marked GUC_REPORT.
3327  * This is executed at completion of backend startup.
3328  */
3329 void
3330 BeginReportingGUCOptions(void)
3331 {
3332         int                     i;
3333
3334         /*
3335          * Don't do anything unless talking to an interactive frontend of protocol
3336          * 3.0 or later.
3337          */
3338         if (whereToSendOutput != DestRemote ||
3339                 PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
3340                 return;
3341
3342         reporting_enabled = true;
3343
3344         /* Transmit initial values of interesting variables */
3345         for (i = 0; i < num_guc_variables; i++)
3346         {
3347                 struct config_generic *conf = guc_variables[i];
3348
3349                 if (conf->flags & GUC_REPORT)
3350                         ReportGUCOption(conf);
3351         }
3352 }
3353
3354 /*
3355  * ReportGUCOption: if appropriate, transmit option value to frontend
3356  */
3357 static void
3358 ReportGUCOption(struct config_generic * record)
3359 {
3360         if (reporting_enabled && (record->flags & GUC_REPORT))
3361         {
3362                 char       *val = _ShowOption(record);
3363                 StringInfoData msgbuf;
3364
3365                 pq_beginmessage(&msgbuf, 'S');
3366                 pq_sendstring(&msgbuf, record->name);
3367                 pq_sendstring(&msgbuf, val);
3368                 pq_endmessage(&msgbuf);
3369
3370                 pfree(val);
3371         }
3372 }
3373
3374
3375 /*
3376  * Try to interpret value as boolean value.  Valid values are: true,
3377  * false, yes, no, on, off, 1, 0.  If the string parses okay, return
3378  * true, else false.  If result is not NULL, return the parsing result
3379  * there.
3380  */
3381 static bool
3382 parse_bool(const char *value, bool *result)
3383 {
3384         size_t          len = strlen(value);
3385
3386         if (pg_strncasecmp(value, "true", len) == 0)
3387         {
3388                 if (result)
3389                         *result = true;
3390         }
3391         else if (pg_strncasecmp(value, "false", len) == 0)
3392         {
3393                 if (result)
3394                         *result = false;
3395         }
3396
3397         else if (pg_strncasecmp(value, "yes", len) == 0)
3398         {
3399                 if (result)
3400                         *result = true;
3401         }
3402         else if (pg_strncasecmp(value, "no", len) == 0)
3403         {
3404                 if (result)
3405                         *result = false;
3406         }
3407
3408         else if (pg_strcasecmp(value, "on") == 0)
3409         {
3410                 if (result)
3411                         *result = true;
3412         }
3413         else if (pg_strcasecmp(value, "off") == 0)
3414         {
3415                 if (result)
3416                         *result = false;
3417         }
3418
3419         else if (pg_strcasecmp(value, "1") == 0)
3420         {
3421                 if (result)
3422                         *result = true;
3423         }
3424         else if (pg_strcasecmp(value, "0") == 0)
3425         {
3426                 if (result)
3427                         *result = false;
3428         }
3429
3430         else
3431         {
3432                 if (result)
3433                         *result = false;        /* suppress compiler warning */
3434                 return false;
3435         }
3436         return true;
3437 }
3438
3439
3440
3441 /*
3442  * Try to parse value as an integer.  The accepted formats are the
3443  * usual decimal, octal, or hexadecimal formats.  If the string parses
3444  * okay, return true, else false.  If result is not NULL, return the
3445  * value there.
3446  */
3447 static bool
3448 parse_int(const char *value, int *result)
3449 {
3450         long            val;
3451         char       *endptr;
3452
3453         errno = 0;
3454         val = strtol(value, &endptr, 0);
3455         if (endptr == value || *endptr != '\0' || errno == ERANGE
3456 #ifdef HAVE_LONG_INT_64
3457         /* if long > 32 bits, check for overflow of int4 */
3458                 || val != (long) ((int32) val)
3459 #endif
3460                 )
3461         {
3462                 if (result)
3463                         *result = 0;            /* suppress compiler warning */
3464                 return false;
3465         }
3466         if (result)
3467                 *result = (int) val;
3468         return true;
3469 }
3470
3471
3472
3473 /*
3474  * Try to parse value as a floating point constant in the usual
3475  * format.      If the value parsed okay return true, else false.  If
3476  * result is not NULL, return the semantic value there.
3477  */
3478 static bool
3479 parse_real(const char *value, double *result)
3480 {
3481         double          val;
3482         char       *endptr;
3483
3484         errno = 0;
3485         val = strtod(value, &endptr);
3486         if (endptr == value || *endptr != '\0' || errno == ERANGE)
3487         {
3488                 if (result)
3489                         *result = 0;            /* suppress compiler warning */
3490                 return false;
3491         }
3492         if (result)
3493                 *result = val;
3494         return true;
3495 }
3496
3497
3498 /*
3499  * Call a GucStringAssignHook function, being careful to free the
3500  * "newval" string if the hook ereports.
3501  *
3502  * This is split out of set_config_option just to avoid the "volatile"
3503  * qualifiers that would otherwise have to be plastered all over.
3504  */
3505 static const char *
3506 call_string_assign_hook(GucStringAssignHook assign_hook,
3507                                                 char *newval, bool doit, GucSource source)
3508 {
3509         const char *result;
3510
3511         PG_TRY();
3512         {
3513                 result = (*assign_hook) (newval, doit, source);
3514         }
3515         PG_CATCH();
3516         {
3517                 free(newval);
3518                 PG_RE_THROW();
3519         }
3520         PG_END_TRY();
3521
3522         return result;
3523 }
3524
3525
3526 /*
3527  * Sets option `name' to given value. The value should be a string
3528  * which is going to be parsed and converted to the appropriate data
3529  * type.  The context and source parameters indicate in which context this
3530  * function is being called so it can apply the access restrictions
3531  * properly.
3532  *
3533  * If value is NULL, set the option to its default value. If the
3534  * parameter changeVal is false then don't really set the option but do all
3535  * the checks to see if it would work.
3536  *
3537  * If there is an error (non-existing option, invalid value) then an
3538  * ereport(ERROR) is thrown *unless* this is called in a context where we
3539  * don't want to ereport (currently, startup or SIGHUP config file reread).
3540  * In that case we write a suitable error message via ereport(DEBUG) and
3541  * return false. This is working around the deficiencies in the ereport
3542  * mechanism, so don't blame me.  In all other cases, the function
3543  * returns true, including cases where the input is valid but we chose
3544  * not to apply it because of context or source-priority considerations.
3545  *
3546  * See also SetConfigOption for an external interface.
3547  */
3548 bool
3549 set_config_option(const char *name, const char *value,
3550                                   GucContext context, GucSource source,
3551                                   bool isLocal, bool changeVal)
3552 {
3553         struct config_generic *record;
3554         int                     elevel;
3555         bool            makeDefault;
3556
3557         if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
3558         {
3559                 /*
3560                  * To avoid cluttering the log, only the postmaster bleats loudly
3561                  * about problems with the config file.
3562                  */
3563                 elevel = IsUnderPostmaster ? DEBUG2 : LOG;
3564         }
3565         else if (source == PGC_S_DATABASE || source == PGC_S_USER)
3566                 elevel = INFO;
3567         else
3568                 elevel = ERROR;
3569
3570         record = find_option(name, elevel);
3571         if (record == NULL)
3572         {
3573                 ereport(elevel,
3574                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
3575                            errmsg("unrecognized configuration parameter \"%s\"", name)));
3576                 return false;
3577         }
3578
3579         /*
3580          * Check if the option can be set at this time. See guc.h for the precise
3581          * rules. Note that we don't want to throw errors if we're in the SIGHUP
3582          * context. In that case we just ignore the attempt and return true.
3583          */
3584         switch (record->context)
3585         {
3586                 case PGC_INTERNAL:
3587                         if (context == PGC_SIGHUP)
3588                                 return true;
3589                         if (context != PGC_INTERNAL)
3590                         {
3591                                 ereport(elevel,
3592                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
3593                                                  errmsg("parameter \"%s\" cannot be changed",
3594                                                                 name)));
3595                                 return false;
3596                         }
3597                         break;
3598                 case PGC_POSTMASTER:
3599                         if (context == PGC_SIGHUP)
3600                                 return true;
3601                         if (context != PGC_POSTMASTER)
3602                         {
3603                                 ereport(elevel,
3604                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
3605                                                  errmsg("parameter \"%s\" cannot be changed after server start",
3606                                                                 name)));
3607                                 return false;
3608                         }
3609                         break;
3610                 case PGC_SIGHUP:
3611                         if (context != PGC_SIGHUP && context != PGC_POSTMASTER)
3612                         {
3613                                 ereport(elevel,
3614                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
3615                                                  errmsg("parameter \"%s\" cannot be changed now",
3616                                                                 name)));
3617                                 return false;
3618                         }
3619
3620                         /*
3621                          * Hmm, the idea of the SIGHUP context is "ought to be global, but
3622                          * can be changed after postmaster start". But there's nothing
3623                          * that prevents a crafty administrator from sending SIGHUP
3624                          * signals to individual backends only.
3625                          */
3626                         break;
3627                 case PGC_BACKEND:
3628                         if (context == PGC_SIGHUP)
3629                         {
3630                                 /*
3631                                  * If a PGC_BACKEND parameter is changed in the config file,
3632                                  * we want to accept the new value in the postmaster (whence
3633                                  * it will propagate to subsequently-started backends), but
3634                                  * ignore it in existing backends.      This is a tad klugy, but
3635                                  * necessary because we don't re-read the config file during
3636                                  * backend start.
3637                                  */
3638                                 if (IsUnderPostmaster)
3639                                         return true;
3640                         }
3641                         else if (context != PGC_BACKEND && context != PGC_POSTMASTER)
3642                         {
3643                                 ereport(elevel,
3644                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
3645                                                  errmsg("parameter \"%s\" cannot be set after connection start",
3646                                                                 name)));
3647                                 return false;
3648                         }
3649                         break;
3650                 case PGC_SUSET:
3651                         if (context == PGC_USERSET || context == PGC_BACKEND)
3652                         {
3653                                 ereport(elevel,
3654                                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3655                                                  errmsg("permission denied to set parameter \"%s\"",
3656                                                                 name)));
3657                                 return false;
3658                         }
3659                         break;
3660                 case PGC_USERSET:
3661                         /* always okay */
3662                         break;
3663         }
3664
3665         /*
3666          * Should we set reset/stacked values?  (If so, the behavior is not
3667          * transactional.)
3668          */
3669         makeDefault = changeVal && (source <= PGC_S_OVERRIDE) && (value != NULL);
3670
3671         /*
3672          * Ignore attempted set if overridden by previously processed setting.
3673          * However, if changeVal is false then plow ahead anyway since we are
3674          * trying to find out if the value is potentially good, not actually use
3675          * it. Also keep going if makeDefault is true, since we may want to set
3676          * the reset/stacked values even if we can't set the variable itself.
3677          */
3678         if (record->source > source)
3679         {
3680                 if (changeVal && !makeDefault)
3681                 {
3682                         elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
3683                                  name);
3684                         return true;
3685                 }
3686                 changeVal = false;
3687         }
3688
3689         /*
3690          * Evaluate value and set variable.
3691          */
3692         switch (record->vartype)
3693         {
3694                 case PGC_BOOL:
3695                         {
3696                                 struct config_bool *conf = (struct config_bool *) record;
3697                                 bool            newval;
3698
3699                                 if (value)
3700                                 {
3701                                         if (!parse_bool(value, &newval))
3702                                         {
3703                                                 ereport(elevel,
3704                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3705                                                   errmsg("parameter \"%s\" requires a Boolean value",
3706                                                                  name)));
3707                                                 return false;
3708                                         }
3709                                 }
3710                                 else
3711                                 {
3712                                         newval = conf->reset_val;
3713                                         source = conf->gen.reset_source;
3714                                 }
3715
3716                                 if (conf->assign_hook)
3717                                         if (!(*conf->assign_hook) (newval, changeVal, source))
3718                                         {
3719                                                 ereport(elevel,
3720                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3721                                                          errmsg("invalid value for parameter \"%s\": %d",
3722                                                                         name, (int) newval)));
3723                                                 return false;
3724                                         }
3725
3726                                 if (changeVal || makeDefault)
3727                                 {
3728                                         /* Save old value to support transaction abort */
3729                                         if (!makeDefault)
3730                                                 push_old_value(&conf->gen);
3731                                         if (changeVal)
3732                                         {
3733                                                 *conf->variable = newval;
3734                                                 conf->gen.source = source;
3735                                         }
3736                                         if (makeDefault)
3737                                         {
3738                                                 GucStack   *stack;
3739
3740                                                 if (conf->gen.reset_source <= source)
3741                                                 {
3742                                                         conf->reset_val = newval;
3743                                                         conf->gen.reset_source = source;
3744                                                 }
3745                                                 for (stack = conf->gen.stack; stack; stack = stack->prev)
3746                                                 {
3747                                                         if (stack->source <= source)
3748                                                         {
3749                                                                 stack->value.boolval = newval;
3750                                                                 stack->source = source;
3751                                                         }
3752                                                 }
3753                                         }
3754                                         else if (isLocal)
3755                                         {
3756                                                 conf->gen.status |= GUC_HAVE_LOCAL;
3757                                                 guc_dirty = true;
3758                                         }
3759                                         else
3760                                         {
3761                                                 conf->tentative_val = newval;
3762                                                 conf->gen.tentative_source = source;
3763                                                 conf->gen.status |= GUC_HAVE_TENTATIVE;
3764                                                 guc_dirty = true;
3765                                         }
3766                                 }
3767                                 break;
3768                         }
3769
3770                 case PGC_INT:
3771                         {
3772                                 struct config_int *conf = (struct config_int *) record;
3773                                 int                     newval;
3774
3775                                 if (value)
3776                                 {
3777                                         if (!parse_int(value, &newval))
3778                                         {
3779                                                 ereport(elevel,
3780                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3781                                                  errmsg("parameter \"%s\" requires an integer value",
3782                                                                 name)));
3783                                                 return false;
3784                                         }
3785                                         if (newval < conf->min || newval > conf->max)
3786                                         {
3787                                                 ereport(elevel,
3788                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3789                                                                  errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
3790                                                                                 newval, name, conf->min, conf->max)));
3791                                                 return false;
3792                                         }
3793                                 }
3794                                 else
3795                                 {
3796                                         newval = conf->reset_val;
3797                                         source = conf->gen.reset_source;
3798                                 }
3799
3800                                 if (conf->assign_hook)
3801                                         if (!(*conf->assign_hook) (newval, changeVal, source))
3802                                         {
3803                                                 ereport(elevel,
3804                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3805                                                          errmsg("invalid value for parameter \"%s\": %d",
3806                                                                         name, newval)));
3807                                                 return false;
3808                                         }
3809
3810                                 if (changeVal || makeDefault)
3811                                 {
3812                                         /* Save old value to support transaction abort */
3813                                         if (!makeDefault)
3814                                                 push_old_value(&conf->gen);
3815                                         if (changeVal)
3816                                         {
3817                                                 *conf->variable = newval;
3818                                                 conf->gen.source = source;
3819                                         }
3820                                         if (makeDefault)
3821                                         {
3822                                                 GucStack   *stack;
3823
3824                                                 if (conf->gen.reset_source <= source)
3825                                                 {
3826                                                         conf->reset_val = newval;
3827                                                         conf->gen.reset_source = source;
3828                                                 }
3829                                                 for (stack = conf->gen.stack; stack; stack = stack->prev)
3830                                                 {
3831                                                         if (stack->source <= source)
3832                                                         {
3833                                                                 stack->value.intval = newval;
3834                                                                 stack->source = source;
3835                                                         }
3836                                                 }
3837                                         }
3838                                         else if (isLocal)
3839                                         {
3840                                                 conf->gen.status |= GUC_HAVE_LOCAL;
3841                                                 guc_dirty = true;
3842                                         }
3843                                         else
3844                                         {
3845                                                 conf->tentative_val = newval;
3846                                                 conf->gen.tentative_source = source;
3847                                                 conf->gen.status |= GUC_HAVE_TENTATIVE;
3848                                                 guc_dirty = true;
3849                                         }
3850                                 }
3851                                 break;
3852                         }
3853
3854                 case PGC_REAL:
3855                         {
3856                                 struct config_real *conf = (struct config_real *) record;
3857                                 double          newval;
3858
3859                                 if (value)
3860                                 {
3861                                         if (!parse_real(value, &newval))
3862                                         {
3863                                                 ereport(elevel,
3864                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3865                                                   errmsg("parameter \"%s\" requires a numeric value",
3866                                                                  name)));
3867                                                 return false;
3868                                         }
3869                                         if (newval < conf->min || newval > conf->max)
3870                                         {
3871                                                 ereport(elevel,
3872                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3873                                                                  errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
3874                                                                                 newval, name, conf->min, conf->max)));
3875                                                 return false;
3876                                         }
3877                                 }
3878                                 else
3879                                 {
3880                                         newval = conf->reset_val;
3881                                         source = conf->gen.reset_source;
3882                                 }
3883
3884                                 if (conf->assign_hook)
3885                                         if (!(*conf->assign_hook) (newval, changeVal, source))
3886                                         {
3887                                                 ereport(elevel,
3888                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3889                                                          errmsg("invalid value for parameter \"%s\": %g",
3890                                                                         name, newval)));
3891                                                 return false;
3892                                         }
3893
3894                                 if (changeVal || makeDefault)
3895                                 {
3896                                         /* Save old value to support transaction abort */
3897                                         if (!makeDefault)
3898                                                 push_old_value(&conf->gen);
3899                                         if (changeVal)
3900                                         {
3901                                                 *conf->variable = newval;
3902                                                 conf->gen.source = source;
3903                                         }
3904                                         if (makeDefault)
3905                                         {
3906                                                 GucStack   *stack;
3907
3908                                                 if (conf->gen.reset_source <= source)
3909                                                 {
3910                                                         conf->reset_val = newval;
3911                                                         conf->gen.reset_source = source;
3912                                                 }
3913                                                 for (stack = conf->gen.stack; stack; stack = stack->prev)
3914                                                 {
3915                                                         if (stack->source <= source)
3916                                                         {
3917                                                                 stack->value.realval = newval;
3918                                                                 stack->source = source;
3919                                                         }
3920                                                 }
3921                                         }
3922                                         else if (isLocal)
3923                                         {
3924                                                 conf->gen.status |= GUC_HAVE_LOCAL;
3925                                                 guc_dirty = true;
3926                                         }
3927                                         else
3928                                         {
3929                                                 conf->tentative_val = newval;
3930                                                 conf->gen.tentative_source = source;
3931                                                 conf->gen.status |= GUC_HAVE_TENTATIVE;
3932                                                 guc_dirty = true;
3933                                         }
3934                                 }
3935                                 break;
3936                         }
3937
3938                 case PGC_STRING:
3939                         {
3940                                 struct config_string *conf = (struct config_string *) record;
3941                                 char       *newval;
3942
3943                                 if (value)
3944                                 {
3945                                         newval = guc_strdup(elevel, value);
3946                                         if (newval == NULL)
3947                                                 return false;
3948                                 }
3949                                 else if (conf->reset_val)
3950                                 {
3951                                         /*
3952                                          * We could possibly avoid strdup here, but easier to make
3953                                          * this case work the same as the normal assignment case.
3954                                          */
3955                                         newval = guc_strdup(elevel, conf->reset_val);
3956                                         if (newval == NULL)
3957                                                 return false;
3958                                         source = conf->gen.reset_source;
3959                                 }
3960                                 else
3961                                 {
3962                                         /* Nothing to reset to, as yet; so do nothing */
3963                                         break;
3964                                 }
3965
3966                                 if (conf->assign_hook)
3967                                 {
3968                                         const char *hookresult;
3969
3970                                         /*
3971                                          * If the hook ereports, we have to make sure we free
3972                                          * newval, else it will be a permanent memory leak.
3973                                          */
3974                                         hookresult = call_string_assign_hook(conf->assign_hook,
3975                                                                                                                  newval,
3976                                                                                                                  changeVal,
3977                                                                                                                  source);
3978                                         if (hookresult == NULL)
3979                                         {
3980                                                 free(newval);
3981                                                 ereport(elevel,
3982                                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3983                                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
3984                                                                 name, value ? value : "")));
3985                                                 return false;
3986                                         }
3987                                         else if (hookresult != newval)
3988                                         {
3989                                                 free(newval);
3990
3991                                                 /*
3992                                                  * Having to cast away const here is annoying, but the
3993                                                  * alternative is to declare assign_hooks as returning
3994                                                  * char*, which would mean they'd have to cast away
3995                                                  * const, or as both taking and returning char*, which
3996                                                  * doesn't seem attractive either --- we don't want
3997                                                  * them to scribble on the passed str.
3998                                                  */
3999                                                 newval = (char *) hookresult;
4000                                         }
4001                                 }
4002
4003                                 if (changeVal || makeDefault)
4004                                 {
4005                                         /* Save old value to support transaction abort */
4006                                         if (!makeDefault)
4007                                                 push_old_value(&conf->gen);
4008                                         if (changeVal)
4009                                         {
4010                                                 set_string_field(conf, conf->variable, newval);
4011                                                 conf->gen.source = source;
4012                                         }
4013                                         if (makeDefault)
4014                                         {
4015                                                 GucStack   *stack;
4016
4017                                                 if (conf->gen.reset_source <= source)
4018                                                 {
4019                                                         set_string_field(conf, &conf->reset_val, newval);
4020                                                         conf->gen.reset_source = source;
4021                                                 }
4022                                                 for (stack = conf->gen.stack; stack; stack = stack->prev)
4023                                                 {
4024                                                         if (stack->source <= source)
4025                                                         {
4026                                                                 set_string_field(conf, &stack->value.stringval,
4027                                                                                                  newval);
4028                                                                 stack->source = source;
4029                                                         }
4030                                                 }
4031                                                 /* Perhaps we didn't install newval anywhere */
4032                                                 if (!string_field_used(conf, newval))
4033                                                         free(newval);
4034                                         }
4035                                         else if (isLocal)
4036                                         {
4037                                                 conf->gen.status |= GUC_HAVE_LOCAL;
4038                                                 guc_dirty = true;
4039                                         }
4040                                         else
4041                                         {
4042                                                 set_string_field(conf, &conf->tentative_val, newval);
4043                                                 conf->gen.tentative_source = source;
4044                                                 conf->gen.status |= GUC_HAVE_TENTATIVE;
4045                                                 guc_dirty = true;
4046                                         }
4047                                 }
4048                                 else
4049                                         free(newval);
4050                                 break;
4051                         }
4052         }
4053
4054         if (changeVal && (record->flags & GUC_REPORT))
4055                 ReportGUCOption(record);
4056
4057         return true;
4058 }
4059
4060
4061 /*
4062  * Set a config option to the given value. See also set_config_option,
4063  * this is just the wrapper to be called from outside GUC.      NB: this
4064  * is used only for non-transactional operations.
4065  */
4066 void
4067 SetConfigOption(const char *name, const char *value,
4068                                 GucContext context, GucSource source)
4069 {
4070         (void) set_config_option(name, value, context, source, false, true);
4071 }
4072
4073
4074
4075 /*
4076  * Fetch the current value of the option `name'. If the option doesn't exist,
4077  * throw an ereport and don't return.
4078  *
4079  * The string is *not* allocated for modification and is really only
4080  * valid until the next call to configuration related functions.
4081  */
4082 const char *
4083 GetConfigOption(const char *name)
4084 {
4085         struct config_generic *record;
4086         static char buffer[256];
4087
4088         record = find_option(name, ERROR);
4089         if (record == NULL)
4090                 ereport(ERROR,
4091                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
4092                            errmsg("unrecognized configuration parameter \"%s\"", name)));
4093         if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
4094                 ereport(ERROR,
4095                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4096                                  errmsg("must be superuser to examine \"%s\"", name)));
4097
4098         switch (record->vartype)
4099         {
4100                 case PGC_BOOL:
4101                         return *((struct config_bool *) record)->variable ? "on" : "off";
4102
4103                 case PGC_INT:
4104                         snprintf(buffer, sizeof(buffer), "%d",
4105                                          *((struct config_int *) record)->variable);
4106                         return buffer;
4107
4108                 case PGC_REAL:
4109                         snprintf(buffer, sizeof(buffer), "%g",
4110                                          *((struct config_real *) record)->variable);
4111                         return buffer;
4112
4113                 case PGC_STRING:
4114                         return *((struct config_string *) record)->variable;
4115         }
4116         return NULL;
4117 }
4118
4119 /*
4120  * Get the RESET value associated with the given option.
4121  */
4122 const char *
4123 GetConfigOptionResetString(const char *name)
4124 {
4125         struct config_generic *record;
4126         static char buffer[256];
4127
4128         record = find_option(name, ERROR);
4129         if (record == NULL)
4130                 ereport(ERROR,
4131                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
4132                            errmsg("unrecognized configuration parameter \"%s\"", name)));
4133         if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
4134                 ereport(ERROR,
4135                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4136                                  errmsg("must be superuser to examine \"%s\"", name)));
4137
4138         switch (record->vartype)
4139         {
4140                 case PGC_BOOL:
4141                         return ((struct config_bool *) record)->reset_val ? "on" : "off";
4142
4143                 case PGC_INT:
4144                         snprintf(buffer, sizeof(buffer), "%d",
4145                                          ((struct config_int *) record)->reset_val);
4146                         return buffer;
4147
4148                 case PGC_REAL:
4149                         snprintf(buffer, sizeof(buffer), "%g",
4150                                          ((struct config_real *) record)->reset_val);
4151                         return buffer;
4152
4153                 case PGC_STRING:
4154                         return ((struct config_string *) record)->reset_val;
4155         }
4156         return NULL;
4157 }
4158
4159 /*
4160  * Detect whether the given configuration option can only be set by
4161  * a superuser.
4162  */
4163 bool
4164 IsSuperuserConfigOption(const char *name)
4165 {
4166         struct config_generic *record;
4167
4168         record = find_option(name, ERROR);
4169         /* On an unrecognized name, don't error, just return false. */
4170         if (record == NULL)
4171                 return false;
4172         return (record->context == PGC_SUSET);
4173 }
4174
4175
4176 /*
4177  * flatten_set_variable_args
4178  *              Given a parsenode List as emitted by the grammar for SET,
4179  *              convert to the flat string representation used by GUC.
4180  *
4181  * We need to be told the name of the variable the args are for, because
4182  * the flattening rules vary (ugh).
4183  *
4184  * The result is NULL if input is NIL (ie, SET ... TO DEFAULT), otherwise
4185  * a palloc'd string.
4186  */
4187 char *
4188 flatten_set_variable_args(const char *name, List *args)
4189 {
4190         struct config_generic *record;
4191         int                     flags;
4192         StringInfoData buf;
4193         ListCell   *l;
4194
4195         /*
4196          * Fast path if just DEFAULT.  We do not check the variable name in this
4197          * case --- necessary for RESET ALL to work correctly.
4198          */
4199         if (args == NIL)
4200                 return NULL;
4201
4202         /* Else get flags for the variable */
4203         record = find_option(name, ERROR);
4204         if (record == NULL)
4205                 ereport(ERROR,
4206                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
4207                            errmsg("unrecognized configuration parameter \"%s\"", name)));
4208
4209         flags = record->flags;
4210
4211         /* Complain if list input and non-list variable */
4212         if ((flags & GUC_LIST_INPUT) == 0 &&
4213                 list_length(args) != 1)
4214                 ereport(ERROR,
4215                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4216                                  errmsg("SET %s takes only one argument", name)));
4217
4218         initStringInfo(&buf);
4219
4220         foreach(l, args)
4221         {
4222                 A_Const    *arg = (A_Const *) lfirst(l);
4223                 char       *val;
4224
4225                 if (l != list_head(args))
4226                         appendStringInfo(&buf, ", ");
4227
4228                 if (!IsA(arg, A_Const))
4229                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
4230
4231                 switch (nodeTag(&arg->val))
4232                 {
4233                         case T_Integer:
4234                                 appendStringInfo(&buf, "%ld", intVal(&arg->val));
4235                                 break;
4236                         case T_Float:
4237                                 /* represented as a string, so just copy it */
4238                                 appendStringInfoString(&buf, strVal(&arg->val));
4239                                 break;
4240                         case T_String:
4241                                 val = strVal(&arg->val);
4242                                 if (arg->typename != NULL)
4243                                 {
4244                                         /*
4245                                          * Must be a ConstInterval argument for TIME ZONE. Coerce
4246                                          * to interval and back to normalize the value and account
4247                                          * for any typmod.
4248                                          */
4249                                         Datum           interval;
4250                                         char       *intervalout;
4251
4252                                         interval =
4253                                                 DirectFunctionCall3(interval_in,
4254                                                                                         CStringGetDatum(val),
4255                                                                                         ObjectIdGetDatum(InvalidOid),
4256                                                                            Int32GetDatum(arg->typename->typmod));
4257
4258                                         intervalout =
4259                                                 DatumGetCString(DirectFunctionCall1(interval_out,
4260                                                                                                                         interval));
4261                                         appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
4262                                 }
4263                                 else
4264                                 {
4265                                         /*
4266                                          * Plain string literal or identifier.  For quote mode,
4267                                          * quote it if it's not a vanilla identifier.
4268                                          */
4269                                         if (flags & GUC_LIST_QUOTE)
4270                                                 appendStringInfoString(&buf, quote_identifier(val));
4271                                         else
4272                                                 appendStringInfoString(&buf, val);
4273                                 }
4274                                 break;
4275                         default:
4276                                 elog(ERROR, "unrecognized node type: %d",
4277                                          (int) nodeTag(&arg->val));
4278                                 break;
4279                 }
4280         }
4281
4282         return buf.data;
4283 }
4284
4285
4286 /*
4287  * SET command
4288  */
4289 void
4290 SetPGVariable(const char *name, List *args, bool is_local)
4291 {
4292         char       *argstring = flatten_set_variable_args(name, args);
4293
4294         /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
4295         set_config_option(name,
4296                                           argstring,
4297                                           (superuser() ? PGC_SUSET : PGC_USERSET),
4298                                           PGC_S_SESSION,
4299                                           is_local,
4300                                           true);
4301 }
4302
4303 /*
4304  * SET command wrapped as a SQL callable function.
4305  */
4306 Datum
4307 set_config_by_name(PG_FUNCTION_ARGS)
4308 {
4309         char       *name;
4310         char       *value;
4311         char       *new_value;
4312         bool            is_local;
4313         text       *result_text;
4314
4315         if (PG_ARGISNULL(0))
4316                 ereport(ERROR,
4317                                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4318                                  errmsg("SET requires parameter name")));
4319
4320         /* Get the GUC variable name */
4321         name = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(0)));
4322
4323         /* Get the desired value or set to NULL for a reset request */
4324         if (PG_ARGISNULL(1))
4325                 value = NULL;
4326         else
4327                 value = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(1)));
4328
4329         /*
4330          * Get the desired state of is_local. Default to false if provided value
4331          * is NULL
4332          */
4333         if (PG_ARGISNULL(2))
4334                 is_local = false;
4335         else
4336                 is_local = PG_GETARG_BOOL(2);
4337
4338         /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
4339         set_config_option(name,
4340                                           value,
4341                                           (superuser() ? PGC_SUSET : PGC_USERSET),
4342                                           PGC_S_SESSION,
4343                                           is_local,
4344                                           true);
4345
4346         /* get the new current value */
4347         new_value = GetConfigOptionByName(name, NULL);
4348
4349         /* Convert return string to text */
4350         result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(new_value)));
4351
4352         /* return it */
4353         PG_RETURN_TEXT_P(result_text);
4354 }
4355
4356 static void
4357 define_custom_variable(struct config_generic * variable)
4358 {
4359         const char *name = variable->name;
4360         const char **nameAddr = &name;
4361         const char *value;
4362         struct config_string *pHolder;
4363         struct config_generic **res = (struct config_generic **) bsearch(
4364                                                                                                                   (void *) &nameAddr,
4365                                                                                                           (void *) guc_variables,
4366                                                                                                                    num_guc_variables,
4367                                                                                          sizeof(struct config_generic *),
4368                                                                                                                         guc_var_compare);
4369
4370         if (res == NULL)
4371         {
4372                 add_guc_variable(variable, ERROR);
4373                 return;
4374         }
4375
4376         /*
4377          * This better be a placeholder
4378          */
4379         if (((*res)->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
4380                 ereport(ERROR,
4381                                 (errcode(ERRCODE_INTERNAL_ERROR),
4382                                  errmsg("attempt to redefine parameter \"%s\"", name)));
4383
4384         Assert((*res)->vartype == PGC_STRING);
4385         pHolder = (struct config_string *) * res;
4386
4387         /* We have the same name, no sorting is necessary */
4388         *res = variable;
4389
4390         value = *pHolder->variable;
4391
4392         /*
4393          * Assign the string value stored in the placeholder to the real variable.
4394          *
4395          * XXX this is not really good enough --- it should be a nontransactional
4396          * assignment, since we don't want it to roll back if the current xact
4397          * fails later.
4398          */
4399         set_config_option(name, value,
4400                                           pHolder->gen.context, pHolder->gen.source,
4401                                           false, true);
4402
4403         /*
4404          * Free up as much as we conveniently can of the placeholder structure
4405          * (this neglects any stack items...)
4406          */
4407         set_string_field(pHolder, pHolder->variable, NULL);
4408         set_string_field(pHolder, &pHolder->reset_val, NULL);
4409         set_string_field(pHolder, &pHolder->tentative_val, NULL);
4410
4411         free(pHolder);
4412 }
4413
4414 static void
4415 init_custom_variable(struct config_generic * gen,
4416                                          const char *name,
4417                                          const char *short_desc,
4418                                          const char *long_desc,
4419                                          GucContext context,
4420                                          enum config_type type)
4421 {
4422         gen->name = guc_strdup(ERROR, name);
4423         gen->context = context;
4424         gen->group = CUSTOM_OPTIONS;
4425         gen->short_desc = short_desc;
4426         gen->long_desc = long_desc;
4427         gen->vartype = type;
4428 }
4429
4430 void
4431 DefineCustomBoolVariable(const char *name,
4432                                                  const char *short_desc,
4433                                                  const char *long_desc,
4434                                                  bool *valueAddr,
4435                                                  GucContext context,
4436                                                  GucBoolAssignHook assign_hook,
4437                                                  GucShowHook show_hook)
4438 {
4439         size_t          sz = sizeof(struct config_bool);
4440         struct config_bool *var = (struct config_bool *) guc_malloc(ERROR, sz);
4441
4442         memset(var, 0, sz);
4443         init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_BOOL);
4444
4445         var->variable = valueAddr;
4446         var->reset_val = *valueAddr;
4447         var->assign_hook = assign_hook;
4448         var->show_hook = show_hook;
4449         define_custom_variable(&var->gen);
4450 }
4451
4452 void
4453 DefineCustomIntVariable(const char *name,
4454                                                 const char *short_desc,
4455                                                 const char *long_desc,
4456                                                 int *valueAddr,
4457                                                 int minValue,
4458                                                 int maxValue,
4459                                                 GucContext context,
4460                                                 GucIntAssignHook assign_hook,
4461                                                 GucShowHook show_hook)
4462 {
4463         size_t          sz = sizeof(struct config_int);
4464         struct config_int *var = (struct config_int *) guc_malloc(ERROR, sz);
4465
4466         memset(var, 0, sz);
4467         init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_INT);
4468
4469         var->variable = valueAddr;
4470         var->reset_val = *valueAddr;
4471         var->min = minValue;
4472         var->max = maxValue;
4473         var->assign_hook = assign_hook;
4474         var->show_hook = show_hook;
4475         define_custom_variable(&var->gen);
4476 }
4477
4478 void
4479 DefineCustomRealVariable(const char *name,
4480                                                  const char *short_desc,
4481                                                  const char *long_desc,
4482                                                  double *valueAddr,
4483                                                  double minValue,
4484                                                  double maxValue,
4485                                                  GucContext context,
4486                                                  GucRealAssignHook assign_hook,
4487                                                  GucShowHook show_hook)
4488 {
4489         size_t          sz = sizeof(struct config_real);
4490         struct config_real *var = (struct config_real *) guc_malloc(ERROR, sz);
4491
4492         memset(var, 0, sz);
4493         init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_REAL);
4494
4495         var->variable = valueAddr;
4496         var->reset_val = *valueAddr;
4497         var->min = minValue;
4498         var->max = maxValue;
4499         var->assign_hook = assign_hook;
4500         var->show_hook = show_hook;
4501         define_custom_variable(&var->gen);
4502 }
4503
4504 void
4505 DefineCustomStringVariable(const char *name,
4506                                                    const char *short_desc,
4507                                                    const char *long_desc,
4508                                                    char **valueAddr,
4509                                                    GucContext context,
4510                                                    GucStringAssignHook assign_hook,
4511                                                    GucShowHook show_hook)
4512 {
4513         size_t          sz = sizeof(struct config_string);
4514         struct config_string *var = (struct config_string *) guc_malloc(ERROR, sz);
4515
4516         memset(var, 0, sz);
4517         init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_STRING);
4518
4519         var->variable = valueAddr;
4520         var->reset_val = *valueAddr;
4521         var->assign_hook = assign_hook;
4522         var->show_hook = show_hook;
4523         define_custom_variable(&var->gen);
4524 }
4525
4526 void
4527 EmitWarningsOnPlaceholders(const char *className)
4528 {
4529         struct config_generic **vars = guc_variables;
4530         struct config_generic **last = vars + num_guc_variables;
4531
4532         int                     nameLen = strlen(className);
4533
4534         while (vars < last)
4535         {
4536                 struct config_generic *var = *vars++;
4537
4538                 if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
4539                         strncmp(className, var->name, nameLen) == 0 &&
4540                         var->name[nameLen] == GUC_QUALIFIER_SEPARATOR)
4541                 {
4542                         ereport(INFO,
4543                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
4544                                          errmsg("unrecognized configuration parameter \"%s\"", var->name)));
4545                 }
4546         }
4547 }
4548
4549
4550 /*
4551  * SHOW command
4552  */
4553 void
4554 GetPGVariable(const char *name, DestReceiver *dest)
4555 {
4556         if (pg_strcasecmp(name, "all") == 0)
4557                 ShowAllGUCConfig(dest);
4558         else
4559                 ShowGUCConfigOption(name, dest);
4560 }
4561
4562 TupleDesc
4563 GetPGVariableResultDesc(const char *name)
4564 {
4565         TupleDesc       tupdesc;
4566
4567         if (pg_strcasecmp(name, "all") == 0)
4568         {
4569                 /* need a tuple descriptor representing three TEXT columns */
4570                 tupdesc = CreateTemplateTupleDesc(3, false);
4571                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
4572                                                    TEXTOID, -1, 0);
4573                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
4574                                                    TEXTOID, -1, 0);
4575                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
4576                                                    TEXTOID, -1, 0);
4577
4578         }
4579         else
4580         {
4581                 const char *varname;
4582
4583                 /* Get the canonical spelling of name */
4584                 (void) GetConfigOptionByName(name, &varname);
4585
4586                 /* need a tuple descriptor representing a single TEXT column */
4587                 tupdesc = CreateTemplateTupleDesc(1, false);
4588                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
4589                                                    TEXTOID, -1, 0);
4590         }
4591         return tupdesc;
4592 }
4593
4594 /*
4595  * RESET command
4596  */
4597 void
4598 ResetPGVariable(const char *name)
4599 {
4600         if (pg_strcasecmp(name, "all") == 0)
4601                 ResetAllOptions();
4602         else
4603                 set_config_option(name,
4604                                                   NULL,
4605                                                   (superuser() ? PGC_SUSET : PGC_USERSET),
4606                                                   PGC_S_SESSION,
4607                                                   false,
4608                                                   true);
4609 }
4610
4611
4612 /*
4613  * SHOW command
4614  */
4615 static void
4616 ShowGUCConfigOption(const char *name, DestReceiver *dest)
4617 {
4618         TupOutputState *tstate;
4619         TupleDesc       tupdesc;
4620         const char *varname;
4621         char       *value;
4622
4623         /* Get the value and canonical spelling of name */
4624         value = GetConfigOptionByName(name, &varname);
4625
4626         /* need a tuple descriptor representing a single TEXT column */
4627         tupdesc = CreateTemplateTupleDesc(1, false);
4628         TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
4629                                            TEXTOID, -1, 0);
4630
4631         /* prepare for projection of tuples */
4632         tstate = begin_tup_output_tupdesc(dest, tupdesc);
4633
4634         /* Send it */
4635         do_text_output_oneline(tstate, value);
4636
4637         end_tup_output(tstate);
4638 }
4639
4640 /*
4641  * SHOW ALL command
4642  */
4643 static void
4644 ShowAllGUCConfig(DestReceiver *dest)
4645 {
4646         bool            am_superuser = superuser();
4647         int                     i;
4648         TupOutputState *tstate;
4649         TupleDesc       tupdesc;
4650         char       *values[3];
4651
4652         /* need a tuple descriptor representing three TEXT columns */
4653         tupdesc = CreateTemplateTupleDesc(3, false);
4654         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
4655                                            TEXTOID, -1, 0);
4656         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
4657                                            TEXTOID, -1, 0);
4658         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
4659                                            TEXTOID, -1, 0);
4660
4661
4662         /* prepare for projection of tuples */
4663         tstate = begin_tup_output_tupdesc(dest, tupdesc);
4664
4665         for (i = 0; i < num_guc_variables; i++)
4666         {
4667                 struct config_generic *conf = guc_variables[i];
4668
4669                 if ((conf->flags & GUC_NO_SHOW_ALL) ||
4670                         ((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser))
4671                         continue;
4672
4673                 /* assign to the values array */
4674                 values[0] = (char *) conf->name;
4675                 values[1] = _ShowOption(conf);
4676                 values[2] = (char *) conf->short_desc;
4677
4678                 /* send it to dest */
4679                 do_tup_output(tstate, values);
4680
4681                 /* clean up */
4682                 if (values[1] != NULL)
4683                         pfree(values[1]);
4684         }
4685
4686         end_tup_output(tstate);
4687 }
4688
4689 /*
4690  * Return GUC variable value by name; optionally return canonical
4691  * form of name.  Return value is palloc'd.
4692  */
4693 char *
4694 GetConfigOptionByName(const char *name, const char **varname)
4695 {
4696         struct config_generic *record;
4697
4698         record = find_option(name, ERROR);
4699         if (record == NULL)
4700                 ereport(ERROR,
4701                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
4702                            errmsg("unrecognized configuration parameter \"%s\"", name)));
4703         if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
4704                 ereport(ERROR,
4705                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4706                                  errmsg("must be superuser to examine \"%s\"", name)));
4707
4708         if (varname)
4709                 *varname = record->name;
4710
4711         return _ShowOption(record);
4712 }
4713
4714 /*
4715  * Return GUC variable value by variable number; optionally return canonical
4716  * form of name.  Return value is palloc'd.
4717  */
4718 void
4719 GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
4720 {
4721         char            buffer[256];
4722         struct config_generic *conf;
4723
4724         /* check requested variable number valid */
4725         Assert((varnum >= 0) && (varnum < num_guc_variables));
4726
4727         conf = guc_variables[varnum];
4728
4729         if (noshow)
4730         {
4731                 if ((conf->flags & GUC_NO_SHOW_ALL) ||
4732                         ((conf->flags & GUC_SUPERUSER_ONLY) && !superuser()))
4733                         *noshow = true;
4734                 else
4735                         *noshow = false;
4736         }
4737
4738         /* first get the generic attributes */
4739
4740         /* name */
4741         values[0] = conf->name;
4742
4743         /* setting : use _ShowOption in order to avoid duplicating the logic */
4744         values[1] = _ShowOption(conf);
4745
4746         /* group */
4747         values[2] = config_group_names[conf->group];
4748
4749         /* short_desc */
4750         values[3] = conf->short_desc;
4751
4752         /* extra_desc */
4753         values[4] = conf->long_desc;
4754
4755         /* context */
4756         values[5] = GucContext_Names[conf->context];
4757
4758         /* vartype */
4759         values[6] = config_type_names[conf->vartype];
4760
4761         /* source */
4762         values[7] = GucSource_Names[conf->source];
4763
4764         /* now get the type specifc attributes */
4765         switch (conf->vartype)
4766         {
4767                 case PGC_BOOL:
4768                         {
4769                                 /* min_val */
4770                                 values[8] = NULL;
4771
4772                                 /* max_val */
4773                                 values[9] = NULL;
4774                         }
4775                         break;
4776
4777                 case PGC_INT:
4778                         {
4779                                 struct config_int *lconf = (struct config_int *) conf;
4780
4781                                 /* min_val */
4782                                 snprintf(buffer, sizeof(buffer), "%d", lconf->min);
4783                                 values[8] = pstrdup(buffer);
4784
4785                                 /* max_val */
4786                                 snprintf(buffer, sizeof(buffer), "%d", lconf->max);
4787                                 values[9] = pstrdup(buffer);
4788                         }
4789                         break;
4790
4791                 case PGC_REAL:
4792                         {
4793                                 struct config_real *lconf = (struct config_real *) conf;
4794
4795                                 /* min_val */
4796                                 snprintf(buffer, sizeof(buffer), "%g", lconf->min);
4797                                 values[8] = pstrdup(buffer);
4798
4799                                 /* max_val */
4800                                 snprintf(buffer, sizeof(buffer), "%g", lconf->max);
4801                                 values[9] = pstrdup(buffer);
4802                         }
4803                         break;
4804
4805                 case PGC_STRING:
4806                         {
4807                                 /* min_val */
4808                                 values[8] = NULL;
4809
4810                                 /* max_val */
4811                                 values[9] = NULL;
4812                         }
4813                         break;
4814
4815                 default:
4816                         {
4817                                 /*
4818                                  * should never get here, but in case we do, set 'em to NULL
4819                                  */
4820
4821                                 /* min_val */
4822                                 values[8] = NULL;
4823
4824                                 /* max_val */
4825                                 values[9] = NULL;
4826                         }
4827                         break;
4828         }
4829 }
4830
4831 /*
4832  * Return the total number of GUC variables
4833  */
4834 int
4835 GetNumConfigOptions(void)
4836 {
4837         return num_guc_variables;
4838 }
4839
4840 /*
4841  * show_config_by_name - equiv to SHOW X command but implemented as
4842  * a function.
4843  */
4844 Datum
4845 show_config_by_name(PG_FUNCTION_ARGS)
4846 {
4847         char       *varname;
4848         char       *varval;
4849         text       *result_text;
4850
4851         /* Get the GUC variable name */
4852         varname = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(0)));
4853
4854         /* Get the value */
4855         varval = GetConfigOptionByName(varname, NULL);
4856
4857         /* Convert to text */
4858         result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(varval)));
4859
4860         /* return it */
4861         PG_RETURN_TEXT_P(result_text);
4862 }
4863
4864 /*
4865  * show_all_settings - equiv to SHOW ALL command but implemented as
4866  * a Table Function.
4867  */
4868 #define NUM_PG_SETTINGS_ATTS    10
4869
4870 Datum
4871 show_all_settings(PG_FUNCTION_ARGS)
4872 {
4873         FuncCallContext *funcctx;
4874         TupleDesc       tupdesc;
4875         int                     call_cntr;
4876         int                     max_calls;
4877         AttInMetadata *attinmeta;
4878         MemoryContext oldcontext;
4879
4880         /* stuff done only on the first call of the function */
4881         if (SRF_IS_FIRSTCALL())
4882         {
4883                 /* create a function context for cross-call persistence */
4884                 funcctx = SRF_FIRSTCALL_INIT();
4885
4886                 /*
4887                  * switch to memory context appropriate for multiple function calls
4888                  */
4889                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
4890
4891                 /*
4892                  * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
4893                  * of the appropriate types
4894                  */
4895                 tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS, false);
4896                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
4897                                                    TEXTOID, -1, 0);
4898                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
4899                                                    TEXTOID, -1, 0);
4900                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "category",
4901                                                    TEXTOID, -1, 0);
4902                 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "short_desc",
4903                                                    TEXTOID, -1, 0);
4904                 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "extra_desc",
4905                                                    TEXTOID, -1, 0);
4906                 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "context",
4907                                                    TEXTOID, -1, 0);
4908                 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "vartype",
4909                                                    TEXTOID, -1, 0);
4910                 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "source",
4911                                                    TEXTOID, -1, 0);
4912                 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "min_val",
4913                                                    TEXTOID, -1, 0);
4914                 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "max_val",
4915                                                    TEXTOID, -1, 0);
4916
4917                 /*
4918                  * Generate attribute metadata needed later to produce tuples from raw
4919                  * C strings
4920                  */
4921                 attinmeta = TupleDescGetAttInMetadata(tupdesc);
4922                 funcctx->attinmeta = attinmeta;
4923
4924                 /* total number of tuples to be returned */
4925                 funcctx->max_calls = GetNumConfigOptions();
4926
4927                 MemoryContextSwitchTo(oldcontext);
4928         }
4929
4930         /* stuff done on every call of the function */
4931         funcctx = SRF_PERCALL_SETUP();
4932
4933         call_cntr = funcctx->call_cntr;
4934         max_calls = funcctx->max_calls;
4935         attinmeta = funcctx->attinmeta;
4936
4937         if (call_cntr < max_calls)      /* do when there is more left to send */
4938         {
4939                 char       *values[NUM_PG_SETTINGS_ATTS];
4940                 bool            noshow;
4941                 HeapTuple       tuple;
4942                 Datum           result;
4943
4944                 /*
4945                  * Get the next visible GUC variable name and value
4946                  */
4947                 do
4948                 {
4949                         GetConfigOptionByNum(call_cntr, (const char **) values, &noshow);
4950                         if (noshow)
4951                         {
4952                                 /* bump the counter and get the next config setting */
4953                                 call_cntr = ++funcctx->call_cntr;
4954
4955                                 /* make sure we haven't gone too far now */
4956                                 if (call_cntr >= max_calls)
4957                                         SRF_RETURN_DONE(funcctx);
4958                         }
4959                 } while (noshow);
4960
4961                 /* build a tuple */
4962                 tuple = BuildTupleFromCStrings(attinmeta, values);
4963
4964                 /* make the tuple into a datum */
4965                 result = HeapTupleGetDatum(tuple);
4966
4967                 SRF_RETURN_NEXT(funcctx, result);
4968         }
4969         else
4970         {
4971                 /* do when there is no more left */
4972                 SRF_RETURN_DONE(funcctx);
4973         }
4974 }
4975
4976 static char *
4977 _ShowOption(struct config_generic * record)
4978 {
4979         char            buffer[256];
4980         const char *val;
4981
4982         switch (record->vartype)
4983         {
4984                 case PGC_BOOL:
4985                         {
4986                                 struct config_bool *conf = (struct config_bool *) record;
4987
4988                                 if (conf->show_hook)
4989                                         val = (*conf->show_hook) ();
4990                                 else
4991                                         val = *conf->variable ? "on" : "off";
4992                         }
4993                         break;
4994
4995                 case PGC_INT:
4996                         {
4997                                 struct config_int *conf = (struct config_int *) record;
4998
4999                                 if (conf->show_hook)
5000                                         val = (*conf->show_hook) ();
5001                                 else
5002                                 {
5003                                         snprintf(buffer, sizeof(buffer), "%d",
5004                                                          *conf->variable);
5005                                         val = buffer;
5006                                 }
5007                         }
5008                         break;
5009
5010                 case PGC_REAL:
5011                         {
5012                                 struct config_real *conf = (struct config_real *) record;
5013
5014                                 if (conf->show_hook)
5015                                         val = (*conf->show_hook) ();
5016                                 else
5017                                 {
5018                                         snprintf(buffer, sizeof(buffer), "%g",
5019                                                          *conf->variable);
5020                                         val = buffer;
5021                                 }
5022                         }
5023                         break;
5024
5025                 case PGC_STRING:
5026                         {
5027                                 struct config_string *conf = (struct config_string *) record;
5028
5029                                 if (conf->show_hook)
5030                                         val = (*conf->show_hook) ();
5031                                 else if (*conf->variable && **conf->variable)
5032                                         val = *conf->variable;
5033                                 else
5034                                         val = "unset";
5035                         }
5036                         break;
5037
5038                 default:
5039                         /* just to keep compiler quiet */
5040                         val = "???";
5041                         break;
5042         }
5043
5044         return pstrdup(val);
5045 }
5046
5047
5048 #ifdef EXEC_BACKEND
5049
5050 /*
5051  *      This routine dumps out all non-default GUC options into a binary
5052  *      file that is read by all exec'ed backends.  The format is:
5053  *
5054  *              variable name, string, null terminated
5055  *              variable value, string, null terminated
5056  *              variable source, integer
5057  */
5058 void
5059 write_nondefault_variables(GucContext context)
5060 {
5061         int                     i;
5062         int                     elevel;
5063         FILE       *fp;
5064
5065         Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
5066
5067         elevel = (context == PGC_SIGHUP) ? LOG : ERROR;
5068
5069         /*
5070          * Open file
5071          */
5072         fp = AllocateFile(CONFIG_EXEC_PARAMS_NEW, "w");
5073         if (!fp)
5074         {
5075                 ereport(elevel,
5076                                 (errcode_for_file_access(),
5077                                  errmsg("could not write to file \"%s\": %m",
5078                                                 CONFIG_EXEC_PARAMS_NEW)));
5079                 return;
5080         }
5081
5082         for (i = 0; i < num_guc_variables; i++)
5083         {
5084                 struct config_generic *gconf = guc_variables[i];
5085
5086                 if (gconf->source != PGC_S_DEFAULT)
5087                 {
5088                         fprintf(fp, "%s", gconf->name);
5089                         fputc(0, fp);
5090
5091                         switch (gconf->vartype)
5092                         {
5093                                 case PGC_BOOL:
5094                                         {
5095                                                 struct config_bool *conf = (struct config_bool *) gconf;
5096
5097                                                 if (*conf->variable == 0)
5098                                                         fprintf(fp, "false");
5099                                                 else
5100                                                         fprintf(fp, "true");
5101                                         }
5102                                         break;
5103
5104                                 case PGC_INT:
5105                                         {
5106                                                 struct config_int *conf = (struct config_int *) gconf;
5107
5108                                                 fprintf(fp, "%d", *conf->variable);
5109                                         }
5110                                         break;
5111
5112                                 case PGC_REAL:
5113                                         {
5114                                                 struct config_real *conf = (struct config_real *) gconf;
5115
5116                                                 /* Could lose precision here? */
5117                                                 fprintf(fp, "%f", *conf->variable);
5118                                         }
5119                                         break;
5120
5121                                 case PGC_STRING:
5122                                         {
5123                                                 struct config_string *conf = (struct config_string *) gconf;
5124
5125                                                 fprintf(fp, "%s", *conf->variable);
5126                                         }
5127                                         break;
5128                         }
5129
5130                         fputc(0, fp);
5131
5132                         fwrite(&gconf->source, sizeof(gconf->source), 1, fp);
5133                 }
5134         }
5135
5136         if (FreeFile(fp))
5137         {
5138                 ereport(elevel,
5139                                 (errcode_for_file_access(),
5140                                  errmsg("could not write to file \"%s\": %m",
5141                                                 CONFIG_EXEC_PARAMS_NEW)));
5142                 return;
5143         }
5144
5145         /*
5146          * Put new file in place.  This could delay on Win32, but we don't hold
5147          * any exclusive locks.
5148          */
5149         rename(CONFIG_EXEC_PARAMS_NEW, CONFIG_EXEC_PARAMS);
5150 }
5151
5152
5153 /*
5154  *      Read string, including null byte from file
5155  *
5156  *      Return NULL on EOF and nothing read
5157  */
5158 static char *
5159 read_string_with_null(FILE *fp)
5160 {
5161         int                     i = 0,
5162                                 ch,
5163                                 maxlen = 256;
5164         char       *str = NULL;
5165
5166         do
5167         {
5168                 if ((ch = fgetc(fp)) == EOF)
5169                 {
5170                         if (i == 0)
5171                                 return NULL;
5172                         else
5173                                 elog(FATAL, "invalid format of exec config params file");
5174                 }
5175                 if (i == 0)
5176                         str = guc_malloc(FATAL, maxlen);
5177                 else if (i == maxlen)
5178                         str = guc_realloc(FATAL, str, maxlen *= 2);
5179                 str[i++] = ch;
5180         } while (ch != 0);
5181
5182         return str;
5183 }
5184
5185
5186 /*
5187  *      This routine loads a previous postmaster dump of its non-default
5188  *      settings.
5189  */
5190 void
5191 read_nondefault_variables(void)
5192 {
5193         FILE       *fp;
5194         char       *varname,
5195                            *varvalue;
5196         int                     varsource;
5197
5198         /*
5199          * Open file
5200          */
5201         fp = AllocateFile(CONFIG_EXEC_PARAMS, "r");
5202         if (!fp)
5203         {
5204                 /* File not found is fine */
5205                 if (errno != ENOENT)
5206                         ereport(FATAL,
5207                                         (errcode_for_file_access(),
5208                                          errmsg("could not read from file \"%s\": %m",
5209                                                         CONFIG_EXEC_PARAMS)));
5210                 return;
5211         }
5212
5213         for (;;)
5214         {
5215                 struct config_generic *record;
5216
5217                 if ((varname = read_string_with_null(fp)) == NULL)
5218                         break;
5219
5220                 if ((record = find_option(varname, FATAL)) == NULL)
5221                         elog(FATAL, "failed to locate variable %s in exec config params file", varname);
5222                 if ((varvalue = read_string_with_null(fp)) == NULL)
5223                         elog(FATAL, "invalid format of exec config params file");
5224                 if (fread(&varsource, sizeof(varsource), 1, fp) == 0)
5225                         elog(FATAL, "invalid format of exec config params file");
5226
5227                 (void) set_config_option(varname, varvalue, record->context,
5228                                                                  varsource, false, true);
5229                 free(varname);
5230                 free(varvalue);
5231         }
5232
5233         FreeFile(fp);
5234 }
5235 #endif   /* EXEC_BACKEND */
5236
5237
5238 /*
5239  * A little "long argument" simulation, although not quite GNU
5240  * compliant. Takes a string of the form "some-option=some value" and
5241  * returns name = "some_option" and value = "some value" in malloc'ed
5242  * storage. Note that '-' is converted to '_' in the option name. If
5243  * there is no '=' in the input string then value will be NULL.
5244  */
5245 void
5246 ParseLongOption(const char *string, char **name, char **value)
5247 {
5248         size_t          equal_pos;
5249         char       *cp;
5250
5251         AssertArg(string);
5252         AssertArg(name);
5253         AssertArg(value);
5254
5255         equal_pos = strcspn(string, "=");
5256
5257         if (string[equal_pos] == '=')
5258         {
5259                 *name = guc_malloc(FATAL, equal_pos + 1);
5260                 strncpy(*name, string, equal_pos);
5261                 (*name)[equal_pos] = '\0';
5262
5263                 *value = guc_strdup(FATAL, &string[equal_pos + 1]);
5264         }
5265         else
5266         {
5267                 /* no equal sign in string */
5268                 *name = guc_strdup(FATAL, string);
5269                 *value = NULL;
5270         }
5271
5272         for (cp = *name; *cp; cp++)
5273                 if (*cp == '-')
5274                         *cp = '_';
5275 }
5276
5277
5278 /*
5279  * Handle options fetched from pg_database.datconfig or pg_authid.rolconfig.
5280  * The array parameter must be an array of TEXT (it must not be NULL).
5281  */
5282 void
5283 ProcessGUCArray(ArrayType *array, GucSource source)
5284 {
5285         int                     i;
5286
5287         Assert(array != NULL);
5288         Assert(ARR_ELEMTYPE(array) == TEXTOID);
5289         Assert(ARR_NDIM(array) == 1);
5290         Assert(ARR_LBOUND(array)[0] == 1);
5291         Assert(source == PGC_S_DATABASE || source == PGC_S_USER);
5292
5293         for (i = 1; i <= ARR_DIMS(array)[0]; i++)
5294         {
5295                 Datum           d;
5296                 bool            isnull;
5297                 char       *s;
5298                 char       *name;
5299                 char       *value;
5300
5301                 d = array_ref(array, 1, &i,
5302                                           -1 /* varlenarray */ ,
5303                                           -1 /* TEXT's typlen */ ,
5304                                           false /* TEXT's typbyval */ ,
5305                                           'i' /* TEXT's typalign */ ,
5306                                           &isnull);
5307
5308                 if (isnull)
5309                         continue;
5310
5311                 s = DatumGetCString(DirectFunctionCall1(textout, d));
5312
5313                 ParseLongOption(s, &name, &value);
5314                 if (!value)
5315                 {
5316                         ereport(WARNING,
5317                                         (errcode(ERRCODE_SYNTAX_ERROR),
5318                           errmsg("could not parse setting for parameter \"%s\"", name)));
5319                         free(name);
5320                         continue;
5321                 }
5322
5323                 /*
5324                  * We process all these options at SUSET level.  We assume that the
5325                  * right to insert an option into pg_database or pg_authid was checked
5326                  * when it was inserted.
5327                  */
5328                 SetConfigOption(name, value, PGC_SUSET, source);
5329
5330                 free(name);
5331                 if (value)
5332                         free(value);
5333         }
5334 }
5335
5336
5337 /*
5338  * Add an entry to an option array.  The array parameter may be NULL
5339  * to indicate the current table entry is NULL.
5340  */
5341 ArrayType *
5342 GUCArrayAdd(ArrayType *array, const char *name, const char *value)
5343 {
5344         const char *varname;
5345         Datum           datum;
5346         char       *newval;
5347         ArrayType  *a;
5348
5349         Assert(name);
5350         Assert(value);
5351
5352         /* test if the option is valid */
5353         set_config_option(name, value,
5354                                           superuser() ? PGC_SUSET : PGC_USERSET,
5355                                           PGC_S_TEST, false, false);
5356
5357         /* convert name to canonical spelling, so we can use plain strcmp */
5358         (void) GetConfigOptionByName(name, &varname);
5359         name = varname;
5360
5361         newval = palloc(strlen(name) + 1 + strlen(value) + 1);
5362         sprintf(newval, "%s=%s", name, value);
5363         datum = DirectFunctionCall1(textin, CStringGetDatum(newval));
5364
5365         if (array)
5366         {
5367                 int                     index;
5368                 bool            isnull;
5369                 int                     i;
5370
5371                 Assert(ARR_ELEMTYPE(array) == TEXTOID);
5372                 Assert(ARR_NDIM(array) == 1);
5373                 Assert(ARR_LBOUND(array)[0] == 1);
5374
5375                 index = ARR_DIMS(array)[0] + 1; /* add after end */
5376
5377                 for (i = 1; i <= ARR_DIMS(array)[0]; i++)
5378                 {
5379                         Datum           d;
5380                         char       *current;
5381
5382                         d = array_ref(array, 1, &i,
5383                                                   -1 /* varlenarray */ ,
5384                                                   -1 /* TEXT's typlen */ ,
5385                                                   false /* TEXT's typbyval */ ,
5386                                                   'i' /* TEXT's typalign */ ,
5387                                                   &isnull);
5388                         if (isnull)
5389                                 continue;
5390                         current = DatumGetCString(DirectFunctionCall1(textout, d));
5391                         if (strncmp(current, newval, strlen(name) + 1) == 0)
5392                         {
5393                                 index = i;
5394                                 break;
5395                         }
5396                 }
5397
5398                 a = array_set(array, 1, &index,
5399                                           datum,
5400                                           false,
5401                                           -1 /* varlena array */ ,
5402                                           -1 /* TEXT's typlen */ ,
5403                                           false /* TEXT's typbyval */ ,
5404                                           'i' /* TEXT's typalign */ );
5405         }
5406         else
5407                 a = construct_array(&datum, 1,
5408                                                         TEXTOID,
5409                                                         -1, false, 'i');
5410
5411         return a;
5412 }
5413
5414
5415 /*
5416  * Delete an entry from an option array.  The array parameter may be NULL
5417  * to indicate the current table entry is NULL.  Also, if the return value
5418  * is NULL then a null should be stored.
5419  */
5420 ArrayType *
5421 GUCArrayDelete(ArrayType *array, const char *name)
5422 {
5423         const char *varname;
5424         ArrayType  *newarray;
5425         int                     i;
5426         int                     index;
5427
5428         Assert(name);
5429
5430         /* test if the option is valid */
5431         set_config_option(name, NULL,
5432                                           superuser() ? PGC_SUSET : PGC_USERSET,
5433                                           PGC_S_TEST, false, false);
5434
5435         /* convert name to canonical spelling, so we can use plain strcmp */
5436         (void) GetConfigOptionByName(name, &varname);
5437         name = varname;
5438
5439         /* if array is currently null, then surely nothing to delete */
5440         if (!array)
5441                 return NULL;
5442
5443         newarray = NULL;
5444         index = 1;
5445
5446         for (i = 1; i <= ARR_DIMS(array)[0]; i++)
5447         {
5448                 Datum           d;
5449                 char       *val;
5450                 bool            isnull;
5451
5452                 d = array_ref(array, 1, &i,
5453                                           -1 /* varlenarray */ ,
5454                                           -1 /* TEXT's typlen */ ,
5455                                           false /* TEXT's typbyval */ ,
5456                                           'i' /* TEXT's typalign */ ,
5457                                           &isnull);
5458                 if (isnull)
5459                         continue;
5460                 val = DatumGetCString(DirectFunctionCall1(textout, d));
5461
5462                 /* ignore entry if it's what we want to delete */
5463                 if (strncmp(val, name, strlen(name)) == 0
5464                         && val[strlen(name)] == '=')
5465                         continue;
5466
5467                 /* else add it to the output array */
5468                 if (newarray)
5469                 {
5470                         newarray = array_set(newarray, 1, &index,
5471                                                                  d,
5472                                                                  false,
5473                                                                  -1 /* varlenarray */ ,
5474                                                                  -1 /* TEXT's typlen */ ,
5475                                                                  false /* TEXT's typbyval */ ,
5476                                                                  'i' /* TEXT's typalign */ );
5477                 }
5478                 else
5479                         newarray = construct_array(&d, 1,
5480                                                                            TEXTOID,
5481                                                                            -1, false, 'i');
5482
5483                 index++;
5484         }
5485
5486         return newarray;
5487 }
5488
5489
5490 /*
5491  * assign_hook subroutines
5492  */
5493
5494 static const char *
5495 assign_log_destination(const char *value, bool doit, GucSource source)
5496 {
5497         char       *rawstring;
5498         List       *elemlist;
5499         ListCell   *l;
5500         int                     newlogdest = 0;
5501
5502         /* Need a modifiable copy of string */
5503         rawstring = pstrdup(value);
5504
5505         /* Parse string into list of identifiers */
5506         if (!SplitIdentifierString(rawstring, ',', &elemlist))
5507         {
5508                 /* syntax error in list */
5509                 pfree(rawstring);
5510                 list_free(elemlist);
5511                 if (source >= PGC_S_INTERACTIVE)
5512                         ereport(ERROR,
5513                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5514                         errmsg("invalid list syntax for parameter \"log_destination\"")));
5515                 return NULL;
5516         }
5517
5518         foreach(l, elemlist)
5519         {
5520                 char       *tok = (char *) lfirst(l);
5521
5522                 if (pg_strcasecmp(tok, "stderr") == 0)
5523                         newlogdest |= LOG_DESTINATION_STDERR;
5524 #ifdef HAVE_SYSLOG
5525                 else if (pg_strcasecmp(tok, "syslog") == 0)
5526                         newlogdest |= LOG_DESTINATION_SYSLOG;
5527 #endif
5528 #ifdef WIN32
5529                 else if (pg_strcasecmp(tok, "eventlog") == 0)
5530                         newlogdest |= LOG_DESTINATION_EVENTLOG;
5531 #endif
5532                 else
5533                 {
5534                         if (source >= PGC_S_INTERACTIVE)
5535                                 ereport(ERROR,
5536                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5537                                   errmsg("unrecognized \"log_destination\" key word: \"%s\"",
5538                                                  tok)));
5539                         pfree(rawstring);
5540                         list_free(elemlist);
5541                         return NULL;
5542                 }
5543         }
5544
5545         if (doit)
5546                 Log_destination = newlogdest;
5547
5548         pfree(rawstring);
5549         list_free(elemlist);
5550
5551         return value;
5552 }
5553
5554 #ifdef HAVE_SYSLOG
5555
5556 static const char *
5557 assign_syslog_facility(const char *facility, bool doit, GucSource source)
5558 {
5559         int                     syslog_fac;
5560
5561         if (pg_strcasecmp(facility, "LOCAL0") == 0)
5562                 syslog_fac = LOG_LOCAL0;
5563         else if (pg_strcasecmp(facility, "LOCAL1") == 0)
5564                 syslog_fac = LOG_LOCAL1;
5565         else if (pg_strcasecmp(facility, "LOCAL2") == 0)
5566                 syslog_fac = LOG_LOCAL2;
5567         else if (pg_strcasecmp(facility, "LOCAL3") == 0)
5568                 syslog_fac = LOG_LOCAL3;
5569         else if (pg_strcasecmp(facility, "LOCAL4") == 0)
5570                 syslog_fac = LOG_LOCAL4;
5571         else if (pg_strcasecmp(facility, "LOCAL5") == 0)
5572                 syslog_fac = LOG_LOCAL5;
5573         else if (pg_strcasecmp(facility, "LOCAL6") == 0)
5574                 syslog_fac = LOG_LOCAL6;
5575         else if (pg_strcasecmp(facility, "LOCAL7") == 0)
5576                 syslog_fac = LOG_LOCAL7;
5577         else
5578                 return NULL;                    /* reject */
5579
5580         if (doit)
5581         {
5582                 syslog_facility = syslog_fac;
5583                 set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
5584                                                           syslog_facility);
5585         }
5586
5587         return facility;
5588 }
5589
5590 static const char *
5591 assign_syslog_ident(const char *ident, bool doit, GucSource source)
5592 {
5593         if (doit)
5594                 set_syslog_parameters(ident, syslog_facility);
5595
5596         return ident;
5597 }
5598 #endif   /* HAVE_SYSLOG */
5599
5600
5601 static const char *
5602 assign_defaultxactisolevel(const char *newval, bool doit, GucSource source)
5603 {
5604         if (pg_strcasecmp(newval, "serializable") == 0)
5605         {
5606                 if (doit)
5607                         DefaultXactIsoLevel = XACT_SERIALIZABLE;
5608         }
5609         else if (pg_strcasecmp(newval, "repeatable read") == 0)
5610         {
5611                 if (doit)
5612                         DefaultXactIsoLevel = XACT_REPEATABLE_READ;
5613         }
5614         else if (pg_strcasecmp(newval, "read committed") == 0)
5615         {
5616                 if (doit)
5617                         DefaultXactIsoLevel = XACT_READ_COMMITTED;
5618         }
5619         else if (pg_strcasecmp(newval, "read uncommitted") == 0)
5620         {
5621                 if (doit)
5622                         DefaultXactIsoLevel = XACT_READ_UNCOMMITTED;
5623         }
5624         else
5625                 return NULL;
5626         return newval;
5627 }
5628
5629 static const char *
5630 assign_log_min_messages(const char *newval,
5631                                                 bool doit, GucSource source)
5632 {
5633         return (assign_msglvl(&log_min_messages, newval, doit, source));
5634 }
5635
5636 static const char *
5637 assign_client_min_messages(const char *newval, bool doit, GucSource source)
5638 {
5639         return (assign_msglvl(&client_min_messages, newval, doit, source));
5640 }
5641
5642 static const char *
5643 assign_min_error_statement(const char *newval, bool doit, GucSource source)
5644 {
5645         return (assign_msglvl(&log_min_error_statement, newval, doit, source));
5646 }
5647
5648 static const char *
5649 assign_msglvl(int *var, const char *newval, bool doit, GucSource source)
5650 {
5651         if (pg_strcasecmp(newval, "debug") == 0)
5652         {
5653                 if (doit)
5654                         (*var) = DEBUG2;
5655         }
5656         else if (pg_strcasecmp(newval, "debug5") == 0)
5657         {
5658                 if (doit)
5659                         (*var) = DEBUG5;
5660         }
5661         else if (pg_strcasecmp(newval, "debug4") == 0)
5662         {
5663                 if (doit)
5664                         (*var) = DEBUG4;
5665         }
5666         else if (pg_strcasecmp(newval, "debug3") == 0)
5667         {
5668                 if (doit)
5669                         (*var) = DEBUG3;
5670         }
5671         else if (pg_strcasecmp(newval, "debug2") == 0)
5672         {
5673                 if (doit)
5674                         (*var) = DEBUG2;
5675         }
5676         else if (pg_strcasecmp(newval, "debug1") == 0)
5677         {
5678                 if (doit)
5679                         (*var) = DEBUG1;
5680         }
5681         else if (pg_strcasecmp(newval, "log") == 0)
5682         {
5683                 if (doit)
5684                         (*var) = LOG;
5685         }
5686
5687         /*
5688          * Client_min_messages always prints 'info', but we allow it as a value
5689          * anyway.
5690          */
5691         else if (pg_strcasecmp(newval, "info") == 0)
5692         {
5693                 if (doit)
5694                         (*var) = INFO;
5695         }
5696         else if (pg_strcasecmp(newval, "notice") == 0)
5697         {
5698                 if (doit)
5699                         (*var) = NOTICE;
5700         }
5701         else if (pg_strcasecmp(newval, "warning") == 0)
5702         {
5703                 if (doit)
5704                         (*var) = WARNING;
5705         }
5706         else if (pg_strcasecmp(newval, "error") == 0)
5707         {
5708                 if (doit)
5709                         (*var) = ERROR;
5710         }
5711         /* We allow FATAL/PANIC for client-side messages too. */
5712         else if (pg_strcasecmp(newval, "fatal") == 0)
5713         {
5714                 if (doit)
5715                         (*var) = FATAL;
5716         }
5717         else if (pg_strcasecmp(newval, "panic") == 0)
5718         {
5719                 if (doit)
5720                         (*var) = PANIC;
5721         }
5722         else
5723                 return NULL;                    /* fail */
5724         return newval;                          /* OK */
5725 }
5726
5727 static const char *
5728 assign_log_error_verbosity(const char *newval, bool doit, GucSource source)
5729 {
5730         if (pg_strcasecmp(newval, "terse") == 0)
5731         {
5732                 if (doit)
5733                         Log_error_verbosity = PGERROR_TERSE;
5734         }
5735         else if (pg_strcasecmp(newval, "default") == 0)
5736         {
5737                 if (doit)
5738                         Log_error_verbosity = PGERROR_DEFAULT;
5739         }
5740         else if (pg_strcasecmp(newval, "verbose") == 0)
5741         {
5742                 if (doit)
5743                         Log_error_verbosity = PGERROR_VERBOSE;
5744         }
5745         else
5746                 return NULL;                    /* fail */
5747         return newval;                          /* OK */
5748 }
5749
5750 static const char *
5751 assign_log_statement(const char *newval, bool doit, GucSource source)
5752 {
5753         if (pg_strcasecmp(newval, "none") == 0)
5754         {
5755                 if (doit)
5756                         log_statement = LOGSTMT_NONE;
5757         }
5758         else if (pg_strcasecmp(newval, "ddl") == 0)
5759         {
5760                 if (doit)
5761                         log_statement = LOGSTMT_DDL;
5762         }
5763         else if (pg_strcasecmp(newval, "mod") == 0)
5764         {
5765                 if (doit)
5766                         log_statement = LOGSTMT_MOD;
5767         }
5768         else if (pg_strcasecmp(newval, "all") == 0)
5769         {
5770                 if (doit)
5771                         log_statement = LOGSTMT_ALL;
5772         }
5773         else
5774                 return NULL;                    /* fail */
5775         return newval;                          /* OK */
5776 }
5777
5778 static const char *
5779 show_num_temp_buffers(void)
5780 {
5781         /*
5782          * We show the GUC var until local buffers have been initialized, and
5783          * NLocBuffer afterwards.
5784          */
5785         static char nbuf[32];
5786
5787         sprintf(nbuf, "%d", NLocBuffer ? NLocBuffer : num_temp_buffers);
5788         return nbuf;
5789 }
5790
5791 static bool
5792 assign_phony_autocommit(bool newval, bool doit, GucSource source)
5793 {
5794         if (!newval)
5795         {
5796                 if (doit && source >= PGC_S_INTERACTIVE)
5797                         ereport(ERROR,
5798                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5799                                          errmsg("SET AUTOCOMMIT TO OFF is no longer supported")));
5800                 return false;
5801         }
5802         return true;
5803 }
5804
5805 static const char *
5806 assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
5807 {
5808         /*
5809          * Check syntax. newval must be a comma separated list of identifiers.
5810          * Whitespace is allowed but skipped.
5811          */
5812         bool            hasSpaceAfterToken = false;
5813         const char *cp = newval;
5814         int                     symLen = 0;
5815         int                     c;
5816         StringInfoData buf;
5817
5818         initStringInfo(&buf);
5819         while ((c = *cp++) != 0)
5820         {
5821                 if (isspace(c))
5822                 {
5823                         if (symLen > 0)
5824                                 hasSpaceAfterToken = true;
5825                         continue;
5826                 }
5827
5828                 if (c == ',')
5829                 {
5830                         hasSpaceAfterToken = false;
5831                         if (symLen > 0)
5832                         {
5833                                 symLen = 0;
5834                                 appendStringInfoChar(&buf, ',');
5835                         }
5836                         continue;
5837                 }
5838
5839                 if (hasSpaceAfterToken || !isalnum(c))
5840                 {
5841                         /*
5842                          * Syntax error due to token following space after token or non
5843                          * alpha numeric character
5844                          */
5845                         ereport(LOG,
5846                                         (errcode(ERRCODE_SYNTAX_ERROR),
5847                                          errmsg("invalid syntax for \"custom_variable_classes\": \"%s\"", newval)));
5848                         pfree(buf.data);
5849                         return NULL;
5850                 }
5851                 symLen++;
5852                 appendStringInfoChar(&buf, (char) c);
5853         }
5854
5855         /* Remove stray ',' at end */
5856         if (symLen == 0 && buf.len > 0)
5857                 buf.data[--buf.len] = '\0';
5858
5859         if (buf.len == 0)
5860                 newval = NULL;
5861         else if (doit)
5862                 newval = strdup(buf.data);
5863
5864         pfree(buf.data);
5865         return newval;
5866 }
5867
5868 static bool
5869 assign_ssl(bool newval, bool doit, GucSource source)
5870 {
5871 #ifndef USE_SSL
5872         if (newval)
5873                 ereport(ERROR,
5874                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5875                                  errmsg("SSL is not supported by this build")));
5876 #endif
5877         return true;
5878 }
5879
5880 static bool
5881 assign_stage_log_stats(bool newval, bool doit, GucSource source)
5882 {
5883         if (newval && log_statement_stats)
5884         {
5885                 if (source >= PGC_S_INTERACTIVE)
5886                         ereport(ERROR,
5887                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5888                                          errmsg("cannot enable parameter when \"log_statement_stats\" is true")));
5889                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
5890                 else if (source != PGC_S_OVERRIDE)
5891                         return false;
5892         }
5893         return true;
5894 }
5895
5896 static bool
5897 assign_log_stats(bool newval, bool doit, GucSource source)
5898 {
5899         if (newval &&
5900                 (log_parser_stats || log_planner_stats || log_executor_stats))
5901         {
5902                 if (source >= PGC_S_INTERACTIVE)
5903                         ereport(ERROR,
5904                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5905                                          errmsg("cannot enable \"log_statement_stats\" when "
5906                                                         "\"log_parser_stats\", \"log_planner_stats\", "
5907                                                         "or \"log_executor_stats\" is true")));
5908                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
5909                 else if (source != PGC_S_OVERRIDE)
5910                         return false;
5911         }
5912         return true;
5913 }
5914
5915 static bool
5916 assign_transaction_read_only(bool newval, bool doit, GucSource source)
5917 {
5918         /* Can't go to r/w mode inside a r/o transaction */
5919         if (newval == false && XactReadOnly && IsSubTransaction())
5920         {
5921                 if (source >= PGC_S_INTERACTIVE)
5922                         ereport(ERROR,
5923                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5924                                          errmsg("cannot set transaction read-write mode inside a read-only transaction")));
5925                 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
5926                 else if (source != PGC_S_OVERRIDE)
5927                         return false;
5928         }
5929         return true;
5930 }
5931
5932 static const char *
5933 assign_canonical_path(const char *newval, bool doit, GucSource source)
5934 {
5935         if (doit)
5936         {
5937                 char       *canon_val = guc_strdup(ERROR, newval);
5938
5939                 canonicalize_path(canon_val);
5940                 return canon_val;
5941         }
5942         else
5943                 return newval;
5944 }
5945
5946 static bool
5947 assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
5948 {
5949         if (doit)
5950                 return (pq_setkeepalivesidle(newval, MyProcPort) == STATUS_OK);
5951
5952         return true;
5953 }
5954
5955 static const char *
5956 show_tcp_keepalives_idle(void)
5957 {
5958         static char nbuf[16];
5959
5960         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
5961         return nbuf;
5962 }
5963
5964 static bool
5965 assign_tcp_keepalives_interval(int newval, bool doit, GucSource source)
5966 {
5967         if (doit)
5968                 return (pq_setkeepalivesinterval(newval, MyProcPort) == STATUS_OK);
5969
5970         return true;
5971 }
5972
5973 static const char *
5974 show_tcp_keepalives_interval(void)
5975 {
5976         static char nbuf[16];
5977
5978         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
5979         return nbuf;
5980 }
5981
5982 static bool
5983 assign_tcp_keepalives_count(int newval, bool doit, GucSource source)
5984 {
5985         if (doit)
5986                 return (pq_setkeepalivescount(newval, MyProcPort) == STATUS_OK);
5987
5988         return true;
5989 }
5990
5991 static const char *
5992 show_tcp_keepalives_count(void)
5993 {
5994         static char nbuf[16];
5995
5996         snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
5997         return nbuf;
5998 }
5999
6000
6001 #include "guc-file.c"