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