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