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