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-2019, PostgreSQL Global Development Group
10 * Written by Peter Eisentraut <peter_e@gmx.net>.
11 *
12 * IDENTIFICATION
13 * src/backend/utils/misc/guc.c
14 *
15 *--------------------------------------------------------------------
16 */
17#include "postgres.h"
18
19#include <ctype.h>
20#include <float.h>
21#include <math.h>
22#include <limits.h>
23#include <unistd.h>
24#include <sys/stat.h>
25#ifdef HAVE_SYSLOG
26#include <syslog.h>
27#endif
28
29#include "access/commit_ts.h"
30#include "access/gin.h"
31#include "access/rmgr.h"
32#include "access/tableam.h"
33#include "access/transam.h"
34#include "access/twophase.h"
35#include "access/xact.h"
36#include "access/xlog_internal.h"
37#include "catalog/namespace.h"
38#include "catalog/pg_authid.h"
39#include "commands/async.h"
40#include "commands/prepare.h"
41#include "commands/user.h"
42#include "commands/vacuum.h"
43#include "commands/variable.h"
44#include "commands/trigger.h"
45#include "common/string.h"
46#include "funcapi.h"
47#include "jit/jit.h"
48#include "libpq/auth.h"
49#include "libpq/libpq.h"
50#include "libpq/pqformat.h"
51#include "miscadmin.h"
52#include "optimizer/cost.h"
53#include "optimizer/geqo.h"
54#include "optimizer/optimizer.h"
55#include "optimizer/paths.h"
56#include "optimizer/planmain.h"
57#include "parser/parse_expr.h"
58#include "parser/parse_type.h"
59#include "parser/parser.h"
60#include "parser/scansup.h"
61#include "pgstat.h"
62#include "postmaster/autovacuum.h"
63#include "postmaster/bgworker_internals.h"
64#include "postmaster/bgwriter.h"
65#include "postmaster/postmaster.h"
66#include "postmaster/syslogger.h"
67#include "postmaster/walwriter.h"
68#include "replication/logicallauncher.h"
69#include "replication/slot.h"
70#include "replication/syncrep.h"
71#include "replication/walreceiver.h"
72#include "replication/walsender.h"
73#include "storage/bufmgr.h"
74#include "storage/dsm_impl.h"
75#include "storage/standby.h"
76#include "storage/fd.h"
77#include "storage/large_object.h"
78#include "storage/pg_shmem.h"
79#include "storage/proc.h"
80#include "storage/predicate.h"
81#include "tcop/tcopprot.h"
82#include "tsearch/ts_cache.h"
83#include "utils/builtins.h"
84#include "utils/bytea.h"
85#include "utils/guc_tables.h"
86#include "utils/float.h"
87#include "utils/memutils.h"
88#include "utils/pg_locale.h"
89#include "utils/pg_lsn.h"
90#include "utils/plancache.h"
91#include "utils/portal.h"
92#include "utils/ps_status.h"
93#include "utils/rls.h"
94#include "utils/snapmgr.h"
95#include "utils/tzparser.h"
96#include "utils/varlena.h"
97#include "utils/xml.h"
98
99#ifndef PG_KRB_SRVTAB
100#define PG_KRB_SRVTAB ""
101#endif
102
103#define CONFIG_FILENAME "postgresql.conf"
104#define HBA_FILENAME "pg_hba.conf"
105#define IDENT_FILENAME "pg_ident.conf"
106
107#ifdef EXEC_BACKEND
108#define CONFIG_EXEC_PARAMS "global/config_exec_params"
109#define CONFIG_EXEC_PARAMS_NEW "global/config_exec_params.new"
110#endif
111
112/*
113 * Precision with which REAL type guc values are to be printed for GUC
114 * serialization.
115 */
116#define REALTYPE_PRECISION 17
117
118/* XXX these should appear in other modules' header files */
119extern bool Log_disconnections;
120extern int CommitDelay;
121extern int CommitSiblings;
122extern char *default_tablespace;
123extern char *temp_tablespaces;
124extern bool ignore_checksum_failure;
125extern bool synchronize_seqscans;
126
127#ifdef TRACE_SYNCSCAN
128extern bool trace_syncscan;
129#endif
130#ifdef DEBUG_BOUNDED_SORT
131extern bool optimize_bounded_sort;
132#endif
133
134static int GUC_check_errcode_value;
135
136/* global variables for check hook support */
137char *GUC_check_errmsg_string;
138char *GUC_check_errdetail_string;
139char *GUC_check_errhint_string;
140
141static void do_serialize(char **destptr, Size *maxbytes, const char *fmt,...) pg_attribute_printf(3, 4);
142
143static void set_config_sourcefile(const char *name, char *sourcefile,
144 int sourceline);
145static bool call_bool_check_hook(struct config_bool *conf, bool *newval,
146 void **extra, GucSource source, int elevel);
147static bool call_int_check_hook(struct config_int *conf, int *newval,
148 void **extra, GucSource source, int elevel);
149static bool call_real_check_hook(struct config_real *conf, double *newval,
150 void **extra, GucSource source, int elevel);
151static bool call_string_check_hook(struct config_string *conf, char **newval,
152 void **extra, GucSource source, int elevel);
153static bool call_enum_check_hook(struct config_enum *conf, int *newval,
154 void **extra, GucSource source, int elevel);
155
156static bool check_log_destination(char **newval, void **extra, GucSource source);
157static void assign_log_destination(const char *newval, void *extra);
158
159static bool check_wal_consistency_checking(char **newval, void **extra,
160 GucSource source);
161static void assign_wal_consistency_checking(const char *newval, void *extra);
162
163#ifdef HAVE_SYSLOG
164static int syslog_facility = LOG_LOCAL0;
165#else
166static int syslog_facility = 0;
167#endif
168
169static void assign_syslog_facility(int newval, void *extra);
170static void assign_syslog_ident(const char *newval, void *extra);
171static void assign_session_replication_role(int newval, void *extra);
172static bool check_temp_buffers(int *newval, void **extra, GucSource source);
173static bool check_bonjour(bool *newval, void **extra, GucSource source);
174static bool check_ssl(bool *newval, void **extra, GucSource source);
175static bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
176static bool check_log_stats(bool *newval, void **extra, GucSource source);
177static bool check_canonical_path(char **newval, void **extra, GucSource source);
178static bool check_timezone_abbreviations(char **newval, void **extra, GucSource source);
179static void assign_timezone_abbreviations(const char *newval, void *extra);
180static void pg_timezone_abbrev_initialize(void);
181static const char *show_archive_command(void);
182static void assign_tcp_keepalives_idle(int newval, void *extra);
183static void assign_tcp_keepalives_interval(int newval, void *extra);
184static void assign_tcp_keepalives_count(int newval, void *extra);
185static void assign_tcp_user_timeout(int newval, void *extra);
186static const char *show_tcp_keepalives_idle(void);
187static const char *show_tcp_keepalives_interval(void);
188static const char *show_tcp_keepalives_count(void);
189static const char *show_tcp_user_timeout(void);
190static bool check_maxconnections(int *newval, void **extra, GucSource source);
191static bool check_max_worker_processes(int *newval, void **extra, GucSource source);
192static bool check_autovacuum_max_workers(int *newval, void **extra, GucSource source);
193static bool check_max_wal_senders(int *newval, void **extra, GucSource source);
194static bool check_autovacuum_work_mem(int *newval, void **extra, GucSource source);
195static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
196static void assign_effective_io_concurrency(int newval, void *extra);
197static void assign_pgstat_temp_directory(const char *newval, void *extra);
198static bool check_application_name(char **newval, void **extra, GucSource source);
199static void assign_application_name(const char *newval, void *extra);
200static bool check_cluster_name(char **newval, void **extra, GucSource source);
201static const char *show_unix_socket_permissions(void);
202static const char *show_log_file_mode(void);
203static const char *show_data_directory_mode(void);
204static bool check_recovery_target_timeline(char **newval, void **extra, GucSource source);
205static void assign_recovery_target_timeline(const char *newval, void *extra);
206static bool check_recovery_target(char **newval, void **extra, GucSource source);
207static void assign_recovery_target(const char *newval, void *extra);
208static bool check_recovery_target_xid(char **newval, void **extra, GucSource source);
209static void assign_recovery_target_xid(const char *newval, void *extra);
210static bool check_recovery_target_time(char **newval, void **extra, GucSource source);
211static void assign_recovery_target_time(const char *newval, void *extra);
212static bool check_recovery_target_name(char **newval, void **extra, GucSource source);
213static void assign_recovery_target_name(const char *newval, void *extra);
214static bool check_recovery_target_lsn(char **newval, void **extra, GucSource source);
215static void assign_recovery_target_lsn(const char *newval, void *extra);
216static bool check_primary_slot_name(char **newval, void **extra, GucSource source);
217static bool check_default_with_oids(bool *newval, void **extra, GucSource source);
218
219/* Private functions in guc-file.l that need to be called from guc.c */
220static ConfigVariable *ProcessConfigFileInternal(GucContext context,
221 bool applySettings, int elevel);
222
223
224/*
225 * Options for enum values defined in this module.
226 *
227 * NOTE! Option values may not contain double quotes!
228 */
229
230static const struct config_enum_entry bytea_output_options[] = {
231 {"escape", BYTEA_OUTPUT_ESCAPE, false},
232 {"hex", BYTEA_OUTPUT_HEX, false},
233 {NULL, 0, false}
234};
235
236/*
237 * We have different sets for client and server message level options because
238 * they sort slightly different (see "log" level), and because "fatal"/"panic"
239 * aren't sensible for client_min_messages.
240 */
241static const struct config_enum_entry client_message_level_options[] = {
242 {"debug5", DEBUG5, false},
243 {"debug4", DEBUG4, false},
244 {"debug3", DEBUG3, false},
245 {"debug2", DEBUG2, false},
246 {"debug1", DEBUG1, false},
247 {"debug", DEBUG2, true},
248 {"log", LOG, false},
249 {"info", INFO, true},
250 {"notice", NOTICE, false},
251 {"warning", WARNING, false},
252 {"error", ERROR, false},
253 {NULL, 0, false}
254};
255
256static const struct config_enum_entry server_message_level_options[] = {
257 {"debug5", DEBUG5, false},
258 {"debug4", DEBUG4, false},
259 {"debug3", DEBUG3, false},
260 {"debug2", DEBUG2, false},
261 {"debug1", DEBUG1, false},
262 {"debug", DEBUG2, true},
263 {"info", INFO, false},
264 {"notice", NOTICE, false},
265 {"warning", WARNING, false},
266 {"error", ERROR, false},
267 {"log", LOG, false},
268 {"fatal", FATAL, false},
269 {"panic", PANIC, false},
270 {NULL, 0, false}
271};
272
273static const struct config_enum_entry intervalstyle_options[] = {
274 {"postgres", INTSTYLE_POSTGRES, false},
275 {"postgres_verbose", INTSTYLE_POSTGRES_VERBOSE, false},
276 {"sql_standard", INTSTYLE_SQL_STANDARD, false},
277 {"iso_8601", INTSTYLE_ISO_8601, false},
278 {NULL, 0, false}
279};
280
281static const struct config_enum_entry log_error_verbosity_options[] = {
282 {"terse", PGERROR_TERSE, false},
283 {"default", PGERROR_DEFAULT, false},
284 {"verbose", PGERROR_VERBOSE, false},
285 {NULL, 0, false}
286};
287
288static const struct config_enum_entry log_statement_options[] = {
289 {"none", LOGSTMT_NONE, false},
290 {"ddl", LOGSTMT_DDL, false},
291 {"mod", LOGSTMT_MOD, false},
292 {"all", LOGSTMT_ALL, false},
293 {NULL, 0, false}
294};
295
296static const struct config_enum_entry isolation_level_options[] = {
297 {"serializable", XACT_SERIALIZABLE, false},
298 {"repeatable read", XACT_REPEATABLE_READ, false},
299 {"read committed", XACT_READ_COMMITTED, false},
300 {"read uncommitted", XACT_READ_UNCOMMITTED, false},
301 {NULL, 0}
302};
303
304static const struct config_enum_entry session_replication_role_options[] = {
305 {"origin", SESSION_REPLICATION_ROLE_ORIGIN, false},
306 {"replica", SESSION_REPLICATION_ROLE_REPLICA, false},
307 {"local", SESSION_REPLICATION_ROLE_LOCAL, false},
308 {NULL, 0, false}
309};
310
311static const struct config_enum_entry syslog_facility_options[] = {
312#ifdef HAVE_SYSLOG
313 {"local0", LOG_LOCAL0, false},
314 {"local1", LOG_LOCAL1, false},
315 {"local2", LOG_LOCAL2, false},
316 {"local3", LOG_LOCAL3, false},
317 {"local4", LOG_LOCAL4, false},
318 {"local5", LOG_LOCAL5, false},
319 {"local6", LOG_LOCAL6, false},
320 {"local7", LOG_LOCAL7, false},
321#else
322 {"none", 0, false},
323#endif
324 {NULL, 0}
325};
326
327static const struct config_enum_entry track_function_options[] = {
328 {"none", TRACK_FUNC_OFF, false},
329 {"pl", TRACK_FUNC_PL, false},
330 {"all", TRACK_FUNC_ALL, false},
331 {NULL, 0, false}
332};
333
334static const struct config_enum_entry xmlbinary_options[] = {
335 {"base64", XMLBINARY_BASE64, false},
336 {"hex", XMLBINARY_HEX, false},
337 {NULL, 0, false}
338};
339
340static const struct config_enum_entry xmloption_options[] = {
341 {"content", XMLOPTION_CONTENT, false},
342 {"document", XMLOPTION_DOCUMENT, false},
343 {NULL, 0, false}
344};
345
346/*
347 * Although only "on", "off", and "safe_encoding" are documented, we
348 * accept all the likely variants of "on" and "off".
349 */
350static const struct config_enum_entry backslash_quote_options[] = {
351 {"safe_encoding", BACKSLASH_QUOTE_SAFE_ENCODING, false},
352 {"on", BACKSLASH_QUOTE_ON, false},
353 {"off", BACKSLASH_QUOTE_OFF, false},
354 {"true", BACKSLASH_QUOTE_ON, true},
355 {"false", BACKSLASH_QUOTE_OFF, true},
356 {"yes", BACKSLASH_QUOTE_ON, true},
357 {"no", BACKSLASH_QUOTE_OFF, true},
358 {"1", BACKSLASH_QUOTE_ON, true},
359 {"0", BACKSLASH_QUOTE_OFF, true},
360 {NULL, 0, false}
361};
362
363/*
364 * Although only "on", "off", and "partition" are documented, we
365 * accept all the likely variants of "on" and "off".
366 */
367static const struct config_enum_entry constraint_exclusion_options[] = {
368 {"partition", CONSTRAINT_EXCLUSION_PARTITION, false},
369 {"on", CONSTRAINT_EXCLUSION_ON, false},
370 {"off", CONSTRAINT_EXCLUSION_OFF, false},
371 {"true", CONSTRAINT_EXCLUSION_ON, true},
372 {"false", CONSTRAINT_EXCLUSION_OFF, true},
373 {"yes", CONSTRAINT_EXCLUSION_ON, true},
374 {"no", CONSTRAINT_EXCLUSION_OFF, true},
375 {"1", CONSTRAINT_EXCLUSION_ON, true},
376 {"0", CONSTRAINT_EXCLUSION_OFF, true},
377 {NULL, 0, false}
378};
379
380/*
381 * Although only "on", "off", "remote_apply", "remote_write", and "local" are
382 * documented, we accept all the likely variants of "on" and "off".
383 */
384static const struct config_enum_entry synchronous_commit_options[] = {
385 {"local", SYNCHRONOUS_COMMIT_LOCAL_FLUSH, false},
386 {"remote_write", SYNCHRONOUS_COMMIT_REMOTE_WRITE, false},
387 {"remote_apply", SYNCHRONOUS_COMMIT_REMOTE_APPLY, false},
388 {"on", SYNCHRONOUS_COMMIT_ON, false},
389 {"off", SYNCHRONOUS_COMMIT_OFF, false},
390 {"true", SYNCHRONOUS_COMMIT_ON, true},
391 {"false", SYNCHRONOUS_COMMIT_OFF, true},
392 {"yes", SYNCHRONOUS_COMMIT_ON, true},
393 {"no", SYNCHRONOUS_COMMIT_OFF, true},
394 {"1", SYNCHRONOUS_COMMIT_ON, true},
395 {"0", SYNCHRONOUS_COMMIT_OFF, true},
396 {NULL, 0, false}
397};
398
399/*
400 * Although only "on", "off", "try" are documented, we accept all the likely
401 * variants of "on" and "off".
402 */
403static const struct config_enum_entry huge_pages_options[] = {
404 {"off", HUGE_PAGES_OFF, false},
405 {"on", HUGE_PAGES_ON, false},
406 {"try", HUGE_PAGES_TRY, false},
407 {"true", HUGE_PAGES_ON, true},
408 {"false", HUGE_PAGES_OFF, true},
409 {"yes", HUGE_PAGES_ON, true},
410 {"no", HUGE_PAGES_OFF, true},
411 {"1", HUGE_PAGES_ON, true},
412 {"0", HUGE_PAGES_OFF, true},
413 {NULL, 0, false}
414};
415
416static const struct config_enum_entry force_parallel_mode_options[] = {
417 {"off", FORCE_PARALLEL_OFF, false},
418 {"on", FORCE_PARALLEL_ON, false},
419 {"regress", FORCE_PARALLEL_REGRESS, false},
420 {"true", FORCE_PARALLEL_ON, true},
421 {"false", FORCE_PARALLEL_OFF, true},
422 {"yes", FORCE_PARALLEL_ON, true},
423 {"no", FORCE_PARALLEL_OFF, true},
424 {"1", FORCE_PARALLEL_ON, true},
425 {"0", FORCE_PARALLEL_OFF, true},
426 {NULL, 0, false}
427};
428
429static const struct config_enum_entry plan_cache_mode_options[] = {
430 {"auto", PLAN_CACHE_MODE_AUTO, false},
431 {"force_generic_plan", PLAN_CACHE_MODE_FORCE_GENERIC_PLAN, false},
432 {"force_custom_plan", PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN, false},
433 {NULL, 0, false}
434};
435
436/*
437 * password_encryption used to be a boolean, so accept all the likely
438 * variants of "on", too. "off" used to store passwords in plaintext,
439 * but we don't support that anymore.
440 */
441static const struct config_enum_entry password_encryption_options[] = {
442 {"md5", PASSWORD_TYPE_MD5, false},
443 {"scram-sha-256", PASSWORD_TYPE_SCRAM_SHA_256, false},
444 {"on", PASSWORD_TYPE_MD5, true},
445 {"true", PASSWORD_TYPE_MD5, true},
446 {"yes", PASSWORD_TYPE_MD5, true},
447 {"1", PASSWORD_TYPE_MD5, true},
448 {NULL, 0, false}
449};
450
451const struct config_enum_entry ssl_protocol_versions_info[] = {
452 {"", PG_TLS_ANY, false},
453 {"TLSv1", PG_TLS1_VERSION, false},
454 {"TLSv1.1", PG_TLS1_1_VERSION, false},
455 {"TLSv1.2", PG_TLS1_2_VERSION, false},
456 {"TLSv1.3", PG_TLS1_3_VERSION, false},
457 {NULL, 0, false}
458};
459
460static struct config_enum_entry shared_memory_options[] = {
461#ifndef WIN32
462 {"sysv", SHMEM_TYPE_SYSV, false},
463#endif
464#ifndef EXEC_BACKEND
465 {"mmap", SHMEM_TYPE_MMAP, false},
466#endif
467#ifdef WIN32
468 {"windows", SHMEM_TYPE_WINDOWS, false},
469#endif
470 {NULL, 0, false}
471};
472
473/*
474 * Options for enum values stored in other modules
475 */
476extern const struct config_enum_entry wal_level_options[];
477extern const struct config_enum_entry archive_mode_options[];
478extern const struct config_enum_entry recovery_target_action_options[];
479extern const struct config_enum_entry sync_method_options[];
480extern const struct config_enum_entry dynamic_shared_memory_options[];
481
482/*
483 * GUC option variables that are exported from this module
484 */
485bool log_duration = false;
486bool Debug_print_plan = false;
487bool Debug_print_parse = false;
488bool Debug_print_rewritten = false;
489bool Debug_pretty_print = true;
490
491bool log_parser_stats = false;
492bool log_planner_stats = false;
493bool log_executor_stats = false;
494bool log_statement_stats = false; /* this is sort of all three above
495 * together */
496bool log_btree_build_stats = false;
497char *event_source;
498
499bool row_security;
500bool check_function_bodies = true;
501
502/*
503 * This GUC exists solely for backward compatibility, check its definition for
504 * details.
505 */
506bool default_with_oids = false;
507bool session_auth_is_superuser;
508
509int log_min_error_statement = ERROR;
510int log_min_messages = WARNING;
511int client_min_messages = NOTICE;
512int log_min_duration_statement = -1;
513int log_temp_files = -1;
514double log_xact_sample_rate = 0;
515int trace_recovery_messages = LOG;
516
517int temp_file_limit = -1;
518
519int num_temp_buffers = 1024;
520
521char *cluster_name = "";
522char *ConfigFileName;
523char *HbaFileName;
524char *IdentFileName;
525char *external_pid_file;
526
527char *pgstat_temp_directory;
528
529char *application_name;
530
531int tcp_keepalives_idle;
532int tcp_keepalives_interval;
533int tcp_keepalives_count;
534int tcp_user_timeout;
535
536/*
537 * SSL renegotiation was been removed in PostgreSQL 9.5, but we tolerate it
538 * being set to zero (meaning never renegotiate) for backward compatibility.
539 * This avoids breaking compatibility with clients that have never supported
540 * renegotiation and therefore always try to zero it.
541 */
542int ssl_renegotiation_limit;
543
544/*
545 * This really belongs in pg_shmem.c, but is defined here so that it doesn't
546 * need to be duplicated in all the different implementations of pg_shmem.c.
547 */
548int huge_pages;
549
550/*
551 * These variables are all dummies that don't do anything, except in some
552 * cases provide the value for SHOW to display. The real state is elsewhere
553 * and is kept in sync by assign_hooks.
554 */
555static char *syslog_ident_str;
556static double phony_random_seed;
557static char *client_encoding_string;
558static char *datestyle_string;
559static char *locale_collate;
560static char *locale_ctype;
561static char *server_encoding_string;
562static char *server_version_string;
563static int server_version_num;
564static char *timezone_string;
565static char *log_timezone_string;
566static char *timezone_abbreviations_string;
567static char *data_directory;
568static char *session_authorization_string;
569static int max_function_args;
570static int max_index_keys;
571static int max_identifier_length;
572static int block_size;
573static int segment_size;
574static int wal_block_size;
575static bool data_checksums;
576static bool integer_datetimes;
577static bool assert_enabled;
578static char *recovery_target_timeline_string;
579static char *recovery_target_string;
580static char *recovery_target_xid_string;
581static char *recovery_target_name_string;
582static char *recovery_target_lsn_string;
583
584
585/* should be static, but commands/variable.c needs to get at this */
586char *role_string;
587
588
589/*
590 * Displayable names for context types (enum GucContext)
591 *
592 * Note: these strings are deliberately not localized.
593 */
594const char *const GucContext_Names[] =
595{
596 /* PGC_INTERNAL */ "internal",
597 /* PGC_POSTMASTER */ "postmaster",
598 /* PGC_SIGHUP */ "sighup",
599 /* PGC_SU_BACKEND */ "superuser-backend",
600 /* PGC_BACKEND */ "backend",
601 /* PGC_SUSET */ "superuser",
602 /* PGC_USERSET */ "user"
603};
604
605/*
606 * Displayable names for source types (enum GucSource)
607 *
608 * Note: these strings are deliberately not localized.
609 */
610const char *const GucSource_Names[] =
611{
612 /* PGC_S_DEFAULT */ "default",
613 /* PGC_S_DYNAMIC_DEFAULT */ "default",
614 /* PGC_S_ENV_VAR */ "environment variable",
615 /* PGC_S_FILE */ "configuration file",
616 /* PGC_S_ARGV */ "command line",
617 /* PGC_S_GLOBAL */ "global",
618 /* PGC_S_DATABASE */ "database",
619 /* PGC_S_USER */ "user",
620 /* PGC_S_DATABASE_USER */ "database user",
621 /* PGC_S_CLIENT */ "client",
622 /* PGC_S_OVERRIDE */ "override",
623 /* PGC_S_INTERACTIVE */ "interactive",
624 /* PGC_S_TEST */ "test",
625 /* PGC_S_SESSION */ "session"
626};
627
628/*
629 * Displayable names for the groupings defined in enum config_group
630 */
631const char *const config_group_names[] =
632{
633 /* UNGROUPED */
634 gettext_noop("Ungrouped"),
635 /* FILE_LOCATIONS */
636 gettext_noop("File Locations"),
637 /* CONN_AUTH */
638 gettext_noop("Connections and Authentication"),
639 /* CONN_AUTH_SETTINGS */
640 gettext_noop("Connections and Authentication / Connection Settings"),
641 /* CONN_AUTH_AUTH */
642 gettext_noop("Connections and Authentication / Authentication"),
643 /* CONN_AUTH_SSL */
644 gettext_noop("Connections and Authentication / SSL"),
645 /* RESOURCES */
646 gettext_noop("Resource Usage"),
647 /* RESOURCES_MEM */
648 gettext_noop("Resource Usage / Memory"),
649 /* RESOURCES_DISK */
650 gettext_noop("Resource Usage / Disk"),
651 /* RESOURCES_KERNEL */
652 gettext_noop("Resource Usage / Kernel Resources"),
653 /* RESOURCES_VACUUM_DELAY */
654 gettext_noop("Resource Usage / Cost-Based Vacuum Delay"),
655 /* RESOURCES_BGWRITER */
656 gettext_noop("Resource Usage / Background Writer"),
657 /* RESOURCES_ASYNCHRONOUS */
658 gettext_noop("Resource Usage / Asynchronous Behavior"),
659 /* WAL */
660 gettext_noop("Write-Ahead Log"),
661 /* WAL_SETTINGS */
662 gettext_noop("Write-Ahead Log / Settings"),
663 /* WAL_CHECKPOINTS */
664 gettext_noop("Write-Ahead Log / Checkpoints"),
665 /* WAL_ARCHIVING */
666 gettext_noop("Write-Ahead Log / Archiving"),
667 /* WAL_ARCHIVE_RECOVERY */
668 gettext_noop("Write-Ahead Log / Archive Recovery"),
669 /* WAL_RECOVERY_TARGET */
670 gettext_noop("Write-Ahead Log / Recovery Target"),
671 /* REPLICATION */
672 gettext_noop("Replication"),
673 /* REPLICATION_SENDING */
674 gettext_noop("Replication / Sending Servers"),
675 /* REPLICATION_MASTER */
676 gettext_noop("Replication / Master Server"),
677 /* REPLICATION_STANDBY */
678 gettext_noop("Replication / Standby Servers"),
679 /* REPLICATION_SUBSCRIBERS */
680 gettext_noop("Replication / Subscribers"),
681 /* QUERY_TUNING */
682 gettext_noop("Query Tuning"),
683 /* QUERY_TUNING_METHOD */
684 gettext_noop("Query Tuning / Planner Method Configuration"),
685 /* QUERY_TUNING_COST */
686 gettext_noop("Query Tuning / Planner Cost Constants"),
687 /* QUERY_TUNING_GEQO */
688 gettext_noop("Query Tuning / Genetic Query Optimizer"),
689 /* QUERY_TUNING_OTHER */
690 gettext_noop("Query Tuning / Other Planner Options"),
691 /* LOGGING */
692 gettext_noop("Reporting and Logging"),
693 /* LOGGING_WHERE */
694 gettext_noop("Reporting and Logging / Where to Log"),
695 /* LOGGING_WHEN */
696 gettext_noop("Reporting and Logging / When to Log"),
697 /* LOGGING_WHAT */
698 gettext_noop("Reporting and Logging / What to Log"),
699 /* PROCESS_TITLE */
700 gettext_noop("Process Title"),
701 /* STATS */
702 gettext_noop("Statistics"),
703 /* STATS_MONITORING */
704 gettext_noop("Statistics / Monitoring"),
705 /* STATS_COLLECTOR */
706 gettext_noop("Statistics / Query and Index Statistics Collector"),
707 /* AUTOVACUUM */
708 gettext_noop("Autovacuum"),
709 /* CLIENT_CONN */
710 gettext_noop("Client Connection Defaults"),
711 /* CLIENT_CONN_STATEMENT */
712 gettext_noop("Client Connection Defaults / Statement Behavior"),
713 /* CLIENT_CONN_LOCALE */
714 gettext_noop("Client Connection Defaults / Locale and Formatting"),
715 /* CLIENT_CONN_PRELOAD */
716 gettext_noop("Client Connection Defaults / Shared Library Preloading"),
717 /* CLIENT_CONN_OTHER */
718 gettext_noop("Client Connection Defaults / Other Defaults"),
719 /* LOCK_MANAGEMENT */
720 gettext_noop("Lock Management"),
721 /* COMPAT_OPTIONS */
722 gettext_noop("Version and Platform Compatibility"),
723 /* COMPAT_OPTIONS_PREVIOUS */
724 gettext_noop("Version and Platform Compatibility / Previous PostgreSQL Versions"),
725 /* COMPAT_OPTIONS_CLIENT */
726 gettext_noop("Version and Platform Compatibility / Other Platforms and Clients"),
727 /* ERROR_HANDLING */
728 gettext_noop("Error Handling"),
729 /* PRESET_OPTIONS */
730 gettext_noop("Preset Options"),
731 /* CUSTOM_OPTIONS */
732 gettext_noop("Customized Options"),
733 /* DEVELOPER_OPTIONS */
734 gettext_noop("Developer Options"),
735 /* help_config wants this array to be null-terminated */
736 NULL
737};
738
739/*
740 * Displayable names for GUC variable types (enum config_type)
741 *
742 * Note: these strings are deliberately not localized.
743 */
744const char *const config_type_names[] =
745{
746 /* PGC_BOOL */ "bool",
747 /* PGC_INT */ "integer",
748 /* PGC_REAL */ "real",
749 /* PGC_STRING */ "string",
750 /* PGC_ENUM */ "enum"
751};
752
753/*
754 * Unit conversion tables.
755 *
756 * There are two tables, one for memory units, and another for time units.
757 * For each supported conversion from one unit to another, we have an entry
758 * in the table.
759 *
760 * To keep things simple, and to avoid possible roundoff error,
761 * conversions are never chained. There needs to be a direct conversion
762 * between all units (of the same type).
763 *
764 * The conversions for each base unit must be kept in order from greatest to
765 * smallest human-friendly unit; convert_xxx_from_base_unit() rely on that.
766 * (The order of the base-unit groups does not matter.)
767 */
768#define MAX_UNIT_LEN 3 /* length of longest recognized unit string */
769
770typedef struct
771{
772 char unit[MAX_UNIT_LEN + 1]; /* unit, as a string, like "kB" or
773 * "min" */
774 int base_unit; /* GUC_UNIT_XXX */
775 double multiplier; /* Factor for converting unit -> base_unit */
776} unit_conversion;
777
778/* Ensure that the constants in the tables don't overflow or underflow */
779#if BLCKSZ < 1024 || BLCKSZ > (1024*1024)
780#error BLCKSZ must be between 1KB and 1MB
781#endif
782#if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024*1024)
783#error XLOG_BLCKSZ must be between 1KB and 1MB
784#endif
785
786static const char *memory_units_hint = gettext_noop("Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\".");
787
788static const unit_conversion memory_unit_conversion_table[] =
789{
790 {"TB", GUC_UNIT_BYTE, 1024.0 * 1024.0 * 1024.0 * 1024.0},
791 {"GB", GUC_UNIT_BYTE, 1024.0 * 1024.0 * 1024.0},
792 {"MB", GUC_UNIT_BYTE, 1024.0 * 1024.0},
793 {"kB", GUC_UNIT_BYTE, 1024.0},
794 {"B", GUC_UNIT_BYTE, 1.0},
795
796 {"TB", GUC_UNIT_KB, 1024.0 * 1024.0 * 1024.0},
797 {"GB", GUC_UNIT_KB, 1024.0 * 1024.0},
798 {"MB", GUC_UNIT_KB, 1024.0},
799 {"kB", GUC_UNIT_KB, 1.0},
800 {"B", GUC_UNIT_KB, 1.0 / 1024.0},
801
802 {"TB", GUC_UNIT_MB, 1024.0 * 1024.0},
803 {"GB", GUC_UNIT_MB, 1024.0},
804 {"MB", GUC_UNIT_MB, 1.0},
805 {"kB", GUC_UNIT_MB, 1.0 / 1024.0},
806 {"B", GUC_UNIT_MB, 1.0 / (1024.0 * 1024.0)},
807
808 {"TB", GUC_UNIT_BLOCKS, (1024.0 * 1024.0 * 1024.0) / (BLCKSZ / 1024)},
809 {"GB", GUC_UNIT_BLOCKS, (1024.0 * 1024.0) / (BLCKSZ / 1024)},
810 {"MB", GUC_UNIT_BLOCKS, 1024.0 / (BLCKSZ / 1024)},
811 {"kB", GUC_UNIT_BLOCKS, 1.0 / (BLCKSZ / 1024)},
812 {"B", GUC_UNIT_BLOCKS, 1.0 / BLCKSZ},
813
814 {"TB", GUC_UNIT_XBLOCKS, (1024.0 * 1024.0 * 1024.0) / (XLOG_BLCKSZ / 1024)},
815 {"GB", GUC_UNIT_XBLOCKS, (1024.0 * 1024.0) / (XLOG_BLCKSZ / 1024)},
816 {"MB", GUC_UNIT_XBLOCKS, 1024.0 / (XLOG_BLCKSZ / 1024)},
817 {"kB", GUC_UNIT_XBLOCKS, 1.0 / (XLOG_BLCKSZ / 1024)},
818 {"B", GUC_UNIT_XBLOCKS, 1.0 / XLOG_BLCKSZ},
819
820 {""} /* end of table marker */
821};
822
823static const char *time_units_hint = gettext_noop("Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", and \"d\".");
824
825static const unit_conversion time_unit_conversion_table[] =
826{
827 {"d", GUC_UNIT_MS, 1000 * 60 * 60 * 24},
828 {"h", GUC_UNIT_MS, 1000 * 60 * 60},
829 {"min", GUC_UNIT_MS, 1000 * 60},
830 {"s", GUC_UNIT_MS, 1000},
831 {"ms", GUC_UNIT_MS, 1},
832 {"us", GUC_UNIT_MS, 1.0 / 1000},
833
834 {"d", GUC_UNIT_S, 60 * 60 * 24},
835 {"h", GUC_UNIT_S, 60 * 60},
836 {"min", GUC_UNIT_S, 60},
837 {"s", GUC_UNIT_S, 1},
838 {"ms", GUC_UNIT_S, 1.0 / 1000},
839 {"us", GUC_UNIT_S, 1.0 / (1000 * 1000)},
840
841 {"d", GUC_UNIT_MIN, 60 * 24},
842 {"h", GUC_UNIT_MIN, 60},
843 {"min", GUC_UNIT_MIN, 1},
844 {"s", GUC_UNIT_MIN, 1.0 / 60},
845 {"ms", GUC_UNIT_MIN, 1.0 / (1000 * 60)},
846 {"us", GUC_UNIT_MIN, 1.0 / (1000 * 1000 * 60)},
847
848 {""} /* end of table marker */
849};
850
851/*
852 * Contents of GUC tables
853 *
854 * See src/backend/utils/misc/README for design notes.
855 *
856 * TO ADD AN OPTION:
857 *
858 * 1. Declare a global variable of type bool, int, double, or char*
859 * and make use of it.
860 *
861 * 2. Decide at what times it's safe to set the option. See guc.h for
862 * details.
863 *
864 * 3. Decide on a name, a default value, upper and lower bounds (if
865 * applicable), etc.
866 *
867 * 4. Add a record below.
868 *
869 * 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
870 * appropriate.
871 *
872 * 6. Don't forget to document the option (at least in config.sgml).
873 *
874 * 7. If it's a new GUC_LIST_QUOTE option, you must add it to
875 * variable_is_guc_list_quote() in src/bin/pg_dump/dumputils.c.
876 */
877
878
879/******** option records follow ********/
880
881static struct config_bool ConfigureNamesBool[] =
882{
883 {
884 {"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
885 gettext_noop("Enables the planner's use of sequential-scan plans."),
886 NULL,
887 GUC_EXPLAIN
888 },
889 &enable_seqscan,
890 true,
891 NULL, NULL, NULL
892 },
893 {
894 {"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
895 gettext_noop("Enables the planner's use of index-scan plans."),
896 NULL,
897 GUC_EXPLAIN
898 },
899 &enable_indexscan,
900 true,
901 NULL, NULL, NULL
902 },
903 {
904 {"enable_indexonlyscan", PGC_USERSET, QUERY_TUNING_METHOD,
905 gettext_noop("Enables the planner's use of index-only-scan plans."),
906 NULL,
907 GUC_EXPLAIN
908 },
909 &enable_indexonlyscan,
910 true,
911 NULL, NULL, NULL
912 },
913 {
914 {"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
915 gettext_noop("Enables the planner's use of bitmap-scan plans."),
916 NULL,
917 GUC_EXPLAIN
918 },
919 &enable_bitmapscan,
920 true,
921 NULL, NULL, NULL
922 },
923 {
924 {"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
925 gettext_noop("Enables the planner's use of TID scan plans."),
926 NULL,
927 GUC_EXPLAIN
928 },
929 &enable_tidscan,
930 true,
931 NULL, NULL, NULL
932 },
933 {
934 {"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
935 gettext_noop("Enables the planner's use of explicit sort steps."),
936 NULL,
937 GUC_EXPLAIN
938 },
939 &enable_sort,
940 true,
941 NULL, NULL, NULL
942 },
943 {
944 {"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
945 gettext_noop("Enables the planner's use of hashed aggregation plans."),
946 NULL,
947 GUC_EXPLAIN
948 },
949 &enable_hashagg,
950 true,
951 NULL, NULL, NULL
952 },
953 {
954 {"enable_material", PGC_USERSET, QUERY_TUNING_METHOD,
955 gettext_noop("Enables the planner's use of materialization."),
956 NULL,
957 GUC_EXPLAIN
958 },
959 &enable_material,
960 true,
961 NULL, NULL, NULL
962 },
963 {
964 {"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
965 gettext_noop("Enables the planner's use of nested-loop join plans."),
966 NULL,
967 GUC_EXPLAIN
968 },
969 &enable_nestloop,
970 true,
971 NULL, NULL, NULL
972 },
973 {
974 {"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
975 gettext_noop("Enables the planner's use of merge join plans."),
976 NULL,
977 GUC_EXPLAIN
978 },
979 &enable_mergejoin,
980 true,
981 NULL, NULL, NULL
982 },
983 {
984 {"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
985 gettext_noop("Enables the planner's use of hash join plans."),
986 NULL,
987 GUC_EXPLAIN
988 },
989 &enable_hashjoin,
990 true,
991 NULL, NULL, NULL
992 },
993 {
994 {"enable_gathermerge", PGC_USERSET, QUERY_TUNING_METHOD,
995 gettext_noop("Enables the planner's use of gather merge plans."),
996 NULL,
997 GUC_EXPLAIN
998 },
999 &enable_gathermerge,
1000 true,
1001 NULL, NULL, NULL
1002 },
1003 {
1004 {"enable_partitionwise_join", PGC_USERSET, QUERY_TUNING_METHOD,
1005 gettext_noop("Enables partitionwise join."),
1006 NULL,
1007 GUC_EXPLAIN
1008 },
1009 &enable_partitionwise_join,
1010 false,
1011 NULL, NULL, NULL
1012 },
1013 {
1014 {"enable_partitionwise_aggregate", PGC_USERSET, QUERY_TUNING_METHOD,
1015 gettext_noop("Enables partitionwise aggregation and grouping."),
1016 NULL,
1017 GUC_EXPLAIN
1018 },
1019 &enable_partitionwise_aggregate,
1020 false,
1021 NULL, NULL, NULL
1022 },
1023 {
1024 {"enable_parallel_append", PGC_USERSET, QUERY_TUNING_METHOD,
1025 gettext_noop("Enables the planner's use of parallel append plans."),
1026 NULL,
1027 GUC_EXPLAIN
1028 },
1029 &enable_parallel_append,
1030 true,
1031 NULL, NULL, NULL
1032 },
1033 {
1034 {"enable_parallel_hash", PGC_USERSET, QUERY_TUNING_METHOD,
1035 gettext_noop("Enables the planner's use of parallel hash plans."),
1036 NULL,
1037 GUC_EXPLAIN
1038 },
1039 &enable_parallel_hash,
1040 true,
1041 NULL, NULL, NULL
1042 },
1043 {
1044 {"enable_partition_pruning", PGC_USERSET, QUERY_TUNING_METHOD,
1045 gettext_noop("Enables plan-time and run-time partition pruning."),
1046 gettext_noop("Allows the query planner and executor to compare partition "
1047 "bounds to conditions in the query to determine which "
1048 "partitions must be scanned."),
1049 GUC_EXPLAIN
1050 },
1051 &enable_partition_pruning,
1052 true,
1053 NULL, NULL, NULL
1054 },
1055 {
1056 {"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
1057 gettext_noop("Enables genetic query optimization."),
1058 gettext_noop("This algorithm attempts to do planning without "
1059 "exhaustive searching."),
1060 GUC_EXPLAIN
1061 },
1062 &enable_geqo,
1063 true,
1064 NULL, NULL, NULL
1065 },
1066 {
1067 /* Not for general use --- used by SET SESSION AUTHORIZATION */
1068 {"is_superuser", PGC_INTERNAL, UNGROUPED,
1069 gettext_noop("Shows whether the current user is a superuser."),
1070 NULL,
1071 GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1072 },
1073 &session_auth_is_superuser,
1074 false,
1075 NULL, NULL, NULL
1076 },
1077 {
1078 {"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1079 gettext_noop("Enables advertising the server via Bonjour."),
1080 NULL
1081 },
1082 &enable_bonjour,
1083 false,
1084 check_bonjour, NULL, NULL
1085 },
1086 {
1087 {"track_commit_timestamp", PGC_POSTMASTER, REPLICATION,
1088 gettext_noop("Collects transaction commit time."),
1089 NULL
1090 },
1091 &track_commit_timestamp,
1092 false,
1093 NULL, NULL, NULL
1094 },
1095 {
1096 {"ssl", PGC_SIGHUP, CONN_AUTH_SSL,
1097 gettext_noop("Enables SSL connections."),
1098 NULL
1099 },
1100 &EnableSSL,
1101 false,
1102 check_ssl, NULL, NULL
1103 },
1104 {
1105 {"ssl_passphrase_command_supports_reload", PGC_SIGHUP, CONN_AUTH_SSL,
1106 gettext_noop("Also use ssl_passphrase_command during server reload."),
1107 NULL
1108 },
1109 &ssl_passphrase_command_supports_reload,
1110 false,
1111 NULL, NULL, NULL
1112 },
1113 {
1114 {"ssl_prefer_server_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
1115 gettext_noop("Give priority to server ciphersuite order."),
1116 NULL
1117 },
1118 &SSLPreferServerCiphers,
1119 true,
1120 NULL, NULL, NULL
1121 },
1122 {
1123 {"fsync", PGC_SIGHUP, WAL_SETTINGS,
1124 gettext_noop("Forces synchronization of updates to disk."),
1125 gettext_noop("The server will use the fsync() system call in several places to make "
1126 "sure that updates are physically written to disk. This insures "
1127 "that a database cluster will recover to a consistent state after "
1128 "an operating system or hardware crash.")
1129 },
1130 &enableFsync,
1131 true,
1132 NULL, NULL, NULL
1133 },
1134 {
1135 {"ignore_checksum_failure", PGC_SUSET, DEVELOPER_OPTIONS,
1136 gettext_noop("Continues processing after a checksum failure."),
1137 gettext_noop("Detection of a checksum failure normally causes PostgreSQL to "
1138 "report an error, aborting the current transaction. Setting "
1139 "ignore_checksum_failure to true causes the system to ignore the failure "
1140 "(but still report a warning), and continue processing. This "
1141 "behavior could cause crashes or other serious problems. Only "
1142 "has an effect if checksums are enabled."),
1143 GUC_NOT_IN_SAMPLE
1144 },
1145 &ignore_checksum_failure,
1146 false,
1147 NULL, NULL, NULL
1148 },
1149 {
1150 {"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
1151 gettext_noop("Continues processing past damaged page headers."),
1152 gettext_noop("Detection of a damaged page header normally causes PostgreSQL to "
1153 "report an error, aborting the current transaction. Setting "
1154 "zero_damaged_pages to true causes the system to instead report a "
1155 "warning, zero out the damaged page, and continue processing. This "
1156 "behavior will destroy data, namely all the rows on the damaged page."),
1157 GUC_NOT_IN_SAMPLE
1158 },
1159 &zero_damaged_pages,
1160 false,
1161 NULL, NULL, NULL
1162 },
1163 {
1164 {"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
1165 gettext_noop("Writes full pages to WAL when first modified after a checkpoint."),
1166 gettext_noop("A page write in process during an operating system crash might be "
1167 "only partially written to disk. During recovery, the row changes "
1168 "stored in WAL are not enough to recover. This option writes "
1169 "pages when first modified after a checkpoint to WAL so full recovery "
1170 "is possible.")
1171 },
1172 &fullPageWrites,
1173 true,
1174 NULL, NULL, NULL
1175 },
1176
1177 {
1178 {"wal_log_hints", PGC_POSTMASTER, WAL_SETTINGS,
1179 gettext_noop("Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modifications."),
1180 NULL
1181 },
1182 &wal_log_hints,
1183 false,
1184 NULL, NULL, NULL
1185 },
1186
1187 {
1188 {"wal_compression", PGC_SUSET, WAL_SETTINGS,
1189 gettext_noop("Compresses full-page writes written in WAL file."),
1190 NULL
1191 },
1192 &wal_compression,
1193 false,
1194 NULL, NULL, NULL
1195 },
1196
1197 {
1198 {"wal_init_zero", PGC_SUSET, WAL_SETTINGS,
1199 gettext_noop("Writes zeroes to new WAL files before first use."),
1200 NULL
1201 },
1202 &wal_init_zero,
1203 true,
1204 NULL, NULL, NULL
1205 },
1206
1207 {
1208 {"wal_recycle", PGC_SUSET, WAL_SETTINGS,
1209 gettext_noop("Recycles WAL files by renaming them."),
1210 NULL
1211 },
1212 &wal_recycle,
1213 true,
1214 NULL, NULL, NULL
1215 },
1216
1217 {
1218 {"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
1219 gettext_noop("Logs each checkpoint."),
1220 NULL
1221 },
1222 &log_checkpoints,
1223 false,
1224 NULL, NULL, NULL
1225 },
1226 {
1227 {"log_connections", PGC_SU_BACKEND, LOGGING_WHAT,
1228 gettext_noop("Logs each successful connection."),
1229 NULL
1230 },
1231 &Log_connections,
1232 false,
1233 NULL, NULL, NULL
1234 },
1235 {
1236 {"log_disconnections", PGC_SU_BACKEND, LOGGING_WHAT,
1237 gettext_noop("Logs end of a session, including duration."),
1238 NULL
1239 },
1240 &Log_disconnections,
1241 false,
1242 NULL, NULL, NULL
1243 },
1244 {
1245 {"log_replication_commands", PGC_SUSET, LOGGING_WHAT,
1246 gettext_noop("Logs each replication command."),
1247 NULL
1248 },
1249 &log_replication_commands,
1250 false,
1251 NULL, NULL, NULL
1252 },
1253 {
1254 {"debug_assertions", PGC_INTERNAL, PRESET_OPTIONS,
1255 gettext_noop("Shows whether the running server has assertion checks enabled."),
1256 NULL,
1257 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1258 },
1259 &assert_enabled,
1260#ifdef USE_ASSERT_CHECKING
1261 true,
1262#else
1263 false,
1264#endif
1265 NULL, NULL, NULL
1266 },
1267
1268 {
1269 {"exit_on_error", PGC_USERSET, ERROR_HANDLING_OPTIONS,
1270 gettext_noop("Terminate session on any error."),
1271 NULL
1272 },
1273 &ExitOnAnyError,
1274 false,
1275 NULL, NULL, NULL
1276 },
1277 {
1278 {"restart_after_crash", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
1279 gettext_noop("Reinitialize server after backend crash."),
1280 NULL
1281 },
1282 &restart_after_crash,
1283 true,
1284 NULL, NULL, NULL
1285 },
1286
1287 {
1288 {"log_duration", PGC_SUSET, LOGGING_WHAT,
1289 gettext_noop("Logs the duration of each completed SQL statement."),
1290 NULL
1291 },
1292 &log_duration,
1293 false,
1294 NULL, NULL, NULL
1295 },
1296 {
1297 {"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
1298 gettext_noop("Logs each query's parse tree."),
1299 NULL
1300 },
1301 &Debug_print_parse,
1302 false,
1303 NULL, NULL, NULL
1304 },
1305 {
1306 {"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
1307 gettext_noop("Logs each query's rewritten parse tree."),
1308 NULL
1309 },
1310 &Debug_print_rewritten,
1311 false,
1312 NULL, NULL, NULL
1313 },
1314 {
1315 {"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
1316 gettext_noop("Logs each query's execution plan."),
1317 NULL
1318 },
1319 &Debug_print_plan,
1320 false,
1321 NULL, NULL, NULL
1322 },
1323 {
1324 {"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
1325 gettext_noop("Indents parse and plan tree displays."),
1326 NULL
1327 },
1328 &Debug_pretty_print,
1329 true,
1330 NULL, NULL, NULL
1331 },
1332 {
1333 {"log_parser_stats", PGC_SUSET, STATS_MONITORING,
1334 gettext_noop("Writes parser performance statistics to the server log."),
1335 NULL
1336 },
1337 &log_parser_stats,
1338 false,
1339 check_stage_log_stats, NULL, NULL
1340 },
1341 {
1342 {"log_planner_stats", PGC_SUSET, STATS_MONITORING,
1343 gettext_noop("Writes planner performance statistics to the server log."),
1344 NULL
1345 },
1346 &log_planner_stats,
1347 false,
1348 check_stage_log_stats, NULL, NULL
1349 },
1350 {
1351 {"log_executor_stats", PGC_SUSET, STATS_MONITORING,
1352 gettext_noop("Writes executor performance statistics to the server log."),
1353 NULL
1354 },
1355 &log_executor_stats,
1356 false,
1357 check_stage_log_stats, NULL, NULL
1358 },
1359 {
1360 {"log_statement_stats", PGC_SUSET, STATS_MONITORING,
1361 gettext_noop("Writes cumulative performance statistics to the server log."),
1362 NULL
1363 },
1364 &log_statement_stats,
1365 false,
1366 check_log_stats, NULL, NULL
1367 },
1368#ifdef BTREE_BUILD_STATS
1369 {
1370 {"log_btree_build_stats", PGC_SUSET, DEVELOPER_OPTIONS,
1371 gettext_noop("Logs system resource usage statistics (memory and CPU) on various B-tree operations."),
1372 NULL,
1373 GUC_NOT_IN_SAMPLE
1374 },
1375 &log_btree_build_stats,
1376 false,
1377 NULL, NULL, NULL
1378 },
1379#endif
1380
1381 {
1382 {"track_activities", PGC_SUSET, STATS_COLLECTOR,
1383 gettext_noop("Collects information about executing commands."),
1384 gettext_noop("Enables the collection of information on the currently "
1385 "executing command of each session, along with "
1386 "the time at which that command began execution.")
1387 },
1388 &pgstat_track_activities,
1389 true,
1390 NULL, NULL, NULL
1391 },
1392 {
1393 {"track_counts", PGC_SUSET, STATS_COLLECTOR,
1394 gettext_noop("Collects statistics on database activity."),
1395 NULL
1396 },
1397 &pgstat_track_counts,
1398 true,
1399 NULL, NULL, NULL
1400 },
1401 {
1402 {"track_io_timing", PGC_SUSET, STATS_COLLECTOR,
1403 gettext_noop("Collects timing statistics for database I/O activity."),
1404 NULL
1405 },
1406 &track_io_timing,
1407 false,
1408 NULL, NULL, NULL
1409 },
1410
1411 {
1412 {"update_process_title", PGC_SUSET, PROCESS_TITLE,
1413 gettext_noop("Updates the process title to show the active SQL command."),
1414 gettext_noop("Enables updating of the process title every time a new SQL command is received by the server.")
1415 },
1416 &update_process_title,
1417#ifdef WIN32
1418 false,
1419#else
1420 true,
1421#endif
1422 NULL, NULL, NULL
1423 },
1424
1425 {
1426 {"autovacuum", PGC_SIGHUP, AUTOVACUUM,
1427 gettext_noop("Starts the autovacuum subprocess."),
1428 NULL
1429 },
1430 &autovacuum_start_daemon,
1431 true,
1432 NULL, NULL, NULL
1433 },
1434
1435 {
1436 {"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
1437 gettext_noop("Generates debugging output for LISTEN and NOTIFY."),
1438 NULL,
1439 GUC_NOT_IN_SAMPLE
1440 },
1441 &Trace_notify,
1442 false,
1443 NULL, NULL, NULL
1444 },
1445
1446#ifdef LOCK_DEBUG
1447 {
1448 {"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
1449 gettext_noop("Emits information about lock usage."),
1450 NULL,
1451 GUC_NOT_IN_SAMPLE
1452 },
1453 &Trace_locks,
1454 false,
1455 NULL, NULL, NULL
1456 },
1457 {
1458 {"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
1459 gettext_noop("Emits information about user lock usage."),
1460 NULL,
1461 GUC_NOT_IN_SAMPLE
1462 },
1463 &Trace_userlocks,
1464 false,
1465 NULL, NULL, NULL
1466 },
1467 {
1468 {"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
1469 gettext_noop("Emits information about lightweight lock usage."),
1470 NULL,
1471 GUC_NOT_IN_SAMPLE
1472 },
1473 &Trace_lwlocks,
1474 false,
1475 NULL, NULL, NULL
1476 },
1477 {
1478 {"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
1479 gettext_noop("Dumps information about all current locks when a deadlock timeout occurs."),
1480 NULL,
1481 GUC_NOT_IN_SAMPLE
1482 },
1483 &Debug_deadlocks,
1484 false,
1485 NULL, NULL, NULL
1486 },
1487#endif
1488
1489 {
1490 {"log_lock_waits", PGC_SUSET, LOGGING_WHAT,
1491 gettext_noop("Logs long lock waits."),
1492 NULL
1493 },
1494 &log_lock_waits,
1495 false,
1496 NULL, NULL, NULL
1497 },
1498
1499 {
1500 {"log_hostname", PGC_SIGHUP, LOGGING_WHAT,
1501 gettext_noop("Logs the host name in the connection logs."),
1502 gettext_noop("By default, connection logs only show the IP address "
1503 "of the connecting host. If you want them to show the host name you "
1504 "can turn this on, but depending on your host name resolution "
1505 "setup it might impose a non-negligible performance penalty.")
1506 },
1507 &log_hostname,
1508 false,
1509 NULL, NULL, NULL
1510 },
1511 {
1512 {"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
1513 gettext_noop("Treats \"expr=NULL\" as \"expr IS NULL\"."),
1514 gettext_noop("When turned on, expressions of the form expr = NULL "
1515 "(or NULL = expr) are treated as expr IS NULL, that is, they "
1516 "return true if expr evaluates to the null value, and false "
1517 "otherwise. The correct behavior of expr = NULL is to always "
1518 "return null (unknown).")
1519 },
1520 &Transform_null_equals,
1521 false,
1522 NULL, NULL, NULL
1523 },
1524 {
1525 {"db_user_namespace", PGC_SIGHUP, CONN_AUTH_AUTH,
1526 gettext_noop("Enables per-database user names."),
1527 NULL
1528 },
1529 &Db_user_namespace,
1530 false,
1531 NULL, NULL, NULL
1532 },
1533 {
1534 {"default_transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
1535 gettext_noop("Sets the default read-only status of new transactions."),
1536 NULL
1537 },
1538 &DefaultXactReadOnly,
1539 false,
1540 NULL, NULL, NULL
1541 },
1542 {
1543 {"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
1544 gettext_noop("Sets the current transaction's read-only status."),
1545 NULL,
1546 GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1547 },
1548 &XactReadOnly,
1549 false,
1550 check_transaction_read_only, NULL, NULL
1551 },
1552 {
1553 {"default_transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
1554 gettext_noop("Sets the default deferrable status of new transactions."),
1555 NULL
1556 },
1557 &DefaultXactDeferrable,
1558 false,
1559 NULL, NULL, NULL
1560 },
1561 {
1562 {"transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
1563 gettext_noop("Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures."),
1564 NULL,
1565 GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1566 },
1567 &XactDeferrable,
1568 false,
1569 check_transaction_deferrable, NULL, NULL
1570 },
1571 {
1572 {"row_security", PGC_USERSET, CLIENT_CONN_STATEMENT,
1573 gettext_noop("Enable row security."),
1574 gettext_noop("When enabled, row security will be applied to all users.")
1575 },
1576 &row_security,
1577 true,
1578 NULL, NULL, NULL
1579 },
1580 {
1581 {"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
1582 gettext_noop("Check function bodies during CREATE FUNCTION."),
1583 NULL
1584 },
1585 &check_function_bodies,
1586 true,
1587 NULL, NULL, NULL
1588 },
1589 {
1590 {"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1591 gettext_noop("Enable input of NULL elements in arrays."),
1592 gettext_noop("When turned on, unquoted NULL in an array input "
1593 "value means a null value; "
1594 "otherwise it is taken literally.")
1595 },
1596 &Array_nulls,
1597 true,
1598 NULL, NULL, NULL
1599 },
1600
1601 /*
1602 * WITH OIDS support, and consequently default_with_oids, was removed in
1603 * PostgreSQL 12, but we tolerate the parameter being set to false to
1604 * avoid unnecessarily breaking older dump files.
1605 */
1606 {
1607 {"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1608 gettext_noop("WITH OIDS is no longer supported; this can only be false."),
1609 NULL,
1610 GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
1611 },
1612 &default_with_oids,
1613 false,
1614 check_default_with_oids, NULL, NULL
1615 },
1616 {
1617 {"logging_collector", PGC_POSTMASTER, LOGGING_WHERE,
1618 gettext_noop("Start a subprocess to capture stderr output and/or csvlogs into log files."),
1619 NULL
1620 },
1621 &Logging_collector,
1622 false,
1623 NULL, NULL, NULL
1624 },
1625 {
1626 {"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
1627 gettext_noop("Truncate existing log files of same name during log rotation."),
1628 NULL
1629 },
1630 &Log_truncate_on_rotation,
1631 false,
1632 NULL, NULL, NULL
1633 },
1634
1635#ifdef TRACE_SORT
1636 {
1637 {"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
1638 gettext_noop("Emit information about resource usage in sorting."),
1639 NULL,
1640 GUC_NOT_IN_SAMPLE
1641 },
1642 &trace_sort,
1643 false,
1644 NULL, NULL, NULL
1645 },
1646#endif
1647
1648#ifdef TRACE_SYNCSCAN
1649 /* this is undocumented because not exposed in a standard build */
1650 {
1651 {"trace_syncscan", PGC_USERSET, DEVELOPER_OPTIONS,
1652 gettext_noop("Generate debugging output for synchronized scanning."),
1653 NULL,
1654 GUC_NOT_IN_SAMPLE
1655 },
1656 &trace_syncscan,
1657 false,
1658 NULL, NULL, NULL
1659 },
1660#endif
1661
1662#ifdef DEBUG_BOUNDED_SORT
1663 /* this is undocumented because not exposed in a standard build */
1664 {
1665 {
1666 "optimize_bounded_sort", PGC_USERSET, QUERY_TUNING_METHOD,
1667 gettext_noop("Enable bounded sorting using heap sort."),
1668 NULL,
1669 GUC_NOT_IN_SAMPLE | GUC_EXPLAIN
1670 },
1671 &optimize_bounded_sort,
1672 true,
1673 NULL, NULL, NULL
1674 },
1675#endif
1676
1677#ifdef WAL_DEBUG
1678 {
1679 {"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
1680 gettext_noop("Emit WAL-related debugging output."),
1681 NULL,
1682 GUC_NOT_IN_SAMPLE
1683 },
1684 &XLOG_DEBUG,
1685 false,
1686 NULL, NULL, NULL
1687 },
1688#endif
1689
1690 {
1691 {"integer_datetimes", PGC_INTERNAL, PRESET_OPTIONS,
1692 gettext_noop("Datetimes are integer based."),
1693 NULL,
1694 GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1695 },
1696 &integer_datetimes,
1697 true,
1698 NULL, NULL, NULL
1699 },
1700
1701 {
1702 {"krb_caseins_users", PGC_SIGHUP, CONN_AUTH_AUTH,
1703 gettext_noop("Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."),
1704 NULL
1705 },
1706 &pg_krb_caseins_users,
1707 false,
1708 NULL, NULL, NULL
1709 },
1710
1711 {
1712 {"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1713 gettext_noop("Warn about backslash escapes in ordinary string literals."),
1714 NULL
1715 },
1716 &escape_string_warning,
1717 true,
1718 NULL, NULL, NULL
1719 },
1720
1721 {
1722 {"standard_conforming_strings", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1723 gettext_noop("Causes '...' strings to treat backslashes literally."),
1724 NULL,
1725 GUC_REPORT
1726 },
1727 &standard_conforming_strings,
1728 true,
1729 NULL, NULL, NULL
1730 },
1731
1732 {
1733 {"synchronize_seqscans", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1734 gettext_noop("Enable synchronized sequential scans."),
1735 NULL
1736 },
1737 &synchronize_seqscans,
1738 true,
1739 NULL, NULL, NULL
1740 },
1741
1742 {
1743 {"recovery_target_inclusive", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
1744 gettext_noop("Sets whether to include or exclude transaction with recovery target."),
1745 NULL
1746 },
1747 &recoveryTargetInclusive,
1748 true,
1749 NULL, NULL, NULL
1750 },
1751
1752 {
1753 {"hot_standby", PGC_POSTMASTER, REPLICATION_STANDBY,
1754 gettext_noop("Allows connections and queries during recovery."),
1755 NULL
1756 },
1757 &EnableHotStandby,
1758 true,
1759 NULL, NULL, NULL
1760 },
1761
1762 {
1763 {"hot_standby_feedback", PGC_SIGHUP, REPLICATION_STANDBY,
1764 gettext_noop("Allows feedback from a hot standby to the primary that will avoid query conflicts."),
1765 NULL
1766 },
1767 &hot_standby_feedback,
1768 false,
1769 NULL, NULL, NULL
1770 },
1771
1772 {
1773 {"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS,
1774 gettext_noop("Allows modifications of the structure of system tables."),
1775 NULL,
1776 GUC_NOT_IN_SAMPLE
1777 },
1778 &allowSystemTableMods,
1779 false,
1780 NULL, NULL, NULL
1781 },
1782
1783 {
1784 {"ignore_system_indexes", PGC_BACKEND, DEVELOPER_OPTIONS,
1785 gettext_noop("Disables reading from system indexes."),
1786 gettext_noop("It does not prevent updating the indexes, so it is safe "
1787 "to use. The worst consequence is slowness."),
1788 GUC_NOT_IN_SAMPLE
1789 },
1790 &IgnoreSystemIndexes,
1791 false,
1792 NULL, NULL, NULL
1793 },
1794
1795 {
1796 {"lo_compat_privileges", PGC_SUSET, COMPAT_OPTIONS_PREVIOUS,
1797 gettext_noop("Enables backward compatibility mode for privilege checks on large objects."),
1798 gettext_noop("Skips privilege checks when reading or modifying large objects, "
1799 "for compatibility with PostgreSQL releases prior to 9.0.")
1800 },
1801 &lo_compat_privileges,
1802 false,
1803 NULL, NULL, NULL
1804 },
1805
1806 {
1807 {"operator_precedence_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1808 gettext_noop("Emit a warning for constructs that changed meaning since PostgreSQL 9.4."),
1809 NULL,
1810 },
1811 &operator_precedence_warning,
1812 false,
1813 NULL, NULL, NULL
1814 },
1815
1816 {
1817 {"quote_all_identifiers", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1818 gettext_noop("When generating SQL fragments, quote all identifiers."),
1819 NULL,
1820 },
1821 &quote_all_identifiers,
1822 false,
1823 NULL, NULL, NULL
1824 },
1825
1826 {
1827 {"data_checksums", PGC_INTERNAL, PRESET_OPTIONS,
1828 gettext_noop("Shows whether data checksums are turned on for this cluster."),
1829 NULL,
1830 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1831 },
1832 &data_checksums,
1833 false,
1834 NULL, NULL, NULL
1835 },
1836
1837 {
1838 {"syslog_sequence_numbers", PGC_SIGHUP, LOGGING_WHERE,
1839 gettext_noop("Add sequence number to syslog messages to avoid duplicate suppression."),
1840 NULL
1841 },
1842 &syslog_sequence_numbers,
1843 true,
1844 NULL, NULL, NULL
1845 },
1846
1847 {
1848 {"syslog_split_messages", PGC_SIGHUP, LOGGING_WHERE,
1849 gettext_noop("Split messages sent to syslog by lines and to fit into 1024 bytes."),
1850 NULL
1851 },
1852 &syslog_split_messages,
1853 true,
1854 NULL, NULL, NULL
1855 },
1856
1857 {
1858 {"parallel_leader_participation", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
1859 gettext_noop("Controls whether Gather and Gather Merge also run subplans."),
1860 gettext_noop("Should gather nodes also run subplans, or just gather tuples?"),
1861 GUC_EXPLAIN
1862 },
1863 &parallel_leader_participation,
1864 true,
1865 NULL, NULL, NULL
1866 },
1867
1868 {
1869 {"jit", PGC_USERSET, QUERY_TUNING_OTHER,
1870 gettext_noop("Allow JIT compilation."),
1871 NULL,
1872 GUC_EXPLAIN
1873 },
1874 &jit_enabled,
1875 true,
1876 NULL, NULL, NULL
1877 },
1878
1879 {
1880 {"jit_debugging_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
1881 gettext_noop("Register JIT compiled function with debugger."),
1882 NULL,
1883 GUC_NOT_IN_SAMPLE
1884 },
1885 &jit_debugging_support,
1886 false,
1887
1888 /*
1889 * This is not guaranteed to be available, but given it's a developer
1890 * oriented option, it doesn't seem worth adding code checking
1891 * availability.
1892 */
1893 NULL, NULL, NULL
1894 },
1895
1896 {
1897 {"jit_dump_bitcode", PGC_SUSET, DEVELOPER_OPTIONS,
1898 gettext_noop("Write out LLVM bitcode to facilitate JIT debugging."),
1899 NULL,
1900 GUC_NOT_IN_SAMPLE
1901 },
1902 &jit_dump_bitcode,
1903 false,
1904 NULL, NULL, NULL
1905 },
1906
1907 {
1908 {"jit_expressions", PGC_USERSET, DEVELOPER_OPTIONS,
1909 gettext_noop("Allow JIT compilation of expressions."),
1910 NULL,
1911 GUC_NOT_IN_SAMPLE
1912 },
1913 &jit_expressions,
1914 true,
1915 NULL, NULL, NULL
1916 },
1917
1918 {
1919 {"jit_profiling_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
1920 gettext_noop("Register JIT compiled function with perf profiler."),
1921 NULL,
1922 GUC_NOT_IN_SAMPLE
1923 },
1924 &jit_profiling_support,
1925 false,
1926
1927 /*
1928 * This is not guaranteed to be available, but given it's a developer
1929 * oriented option, it doesn't seem worth adding code checking
1930 * availability.
1931 */
1932 NULL, NULL, NULL
1933 },
1934
1935 {
1936 {"jit_tuple_deforming", PGC_USERSET, DEVELOPER_OPTIONS,
1937 gettext_noop("Allow JIT compilation of tuple deforming."),
1938 NULL,
1939 GUC_NOT_IN_SAMPLE
1940 },
1941 &jit_tuple_deforming,
1942 true,
1943 NULL, NULL, NULL
1944 },
1945
1946 {
1947 {"data_sync_retry", PGC_POSTMASTER, ERROR_HANDLING_OPTIONS,
1948 gettext_noop("Whether to continue running after a failure to sync data files."),
1949 },
1950 &data_sync_retry,
1951 false,
1952 NULL, NULL, NULL
1953 },
1954
1955 /* End-of-list marker */
1956 {
1957 {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
1958 }
1959};
1960
1961
1962static struct config_int ConfigureNamesInt[] =
1963{
1964 {
1965 {"archive_timeout", PGC_SIGHUP, WAL_ARCHIVING,
1966 gettext_noop("Forces a switch to the next WAL file if a "
1967 "new file has not been started within N seconds."),
1968 NULL,
1969 GUC_UNIT_S
1970 },
1971 &XLogArchiveTimeout,
1972 0, 0, INT_MAX / 2,
1973 NULL, NULL, NULL
1974 },
1975 {
1976 {"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
1977 gettext_noop("Waits N seconds on connection startup after authentication."),
1978 gettext_noop("This allows attaching a debugger to the process."),
1979 GUC_NOT_IN_SAMPLE | GUC_UNIT_S
1980 },
1981 &PostAuthDelay,
1982 0, 0, INT_MAX / 1000000,
1983 NULL, NULL, NULL
1984 },
1985 {
1986 {"default_statistics_target", PGC_USERSET, QUERY_TUNING_OTHER,
1987 gettext_noop("Sets the default statistics target."),
1988 gettext_noop("This applies to table columns that have not had a "
1989 "column-specific target set via ALTER TABLE SET STATISTICS.")
1990 },
1991 &default_statistics_target,
1992 100, 1, 10000,
1993 NULL, NULL, NULL
1994 },
1995 {
1996 {"from_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
1997 gettext_noop("Sets the FROM-list size beyond which subqueries "
1998 "are not collapsed."),
1999 gettext_noop("The planner will merge subqueries into upper "
2000 "queries if the resulting FROM list would have no more than "
2001 "this many items."),
2002 GUC_EXPLAIN
2003 },
2004 &from_collapse_limit,
2005 8, 1, INT_MAX,
2006 NULL, NULL, NULL
2007 },
2008 {
2009 {"join_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
2010 gettext_noop("Sets the FROM-list size beyond which JOIN "
2011 "constructs are not flattened."),
2012 gettext_noop("The planner will flatten explicit JOIN "
2013 "constructs into lists of FROM items whenever a "
2014 "list of no more than this many items would result."),
2015 GUC_EXPLAIN
2016 },
2017 &join_collapse_limit,
2018 8, 1, INT_MAX,
2019 NULL, NULL, NULL
2020 },
2021 {
2022 {"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
2023 gettext_noop("Sets the threshold of FROM items beyond which GEQO is used."),
2024 NULL,
2025 GUC_EXPLAIN
2026 },
2027 &geqo_threshold,
2028 12, 2, INT_MAX,
2029 NULL, NULL, NULL
2030 },
2031 {
2032 {"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
2033 gettext_noop("GEQO: effort is used to set the default for other GEQO parameters."),
2034 NULL,
2035 GUC_EXPLAIN
2036 },
2037 &Geqo_effort,
2038 DEFAULT_GEQO_EFFORT, MIN_GEQO_EFFORT, MAX_GEQO_EFFORT,
2039 NULL, NULL, NULL
2040 },
2041 {
2042 {"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
2043 gettext_noop("GEQO: number of individuals in the population."),
2044 gettext_noop("Zero selects a suitable default value."),
2045 GUC_EXPLAIN
2046 },
2047 &Geqo_pool_size,
2048 0, 0, INT_MAX,
2049 NULL, NULL, NULL
2050 },
2051 {
2052 {"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
2053 gettext_noop("GEQO: number of iterations of the algorithm."),
2054 gettext_noop("Zero selects a suitable default value."),
2055 GUC_EXPLAIN
2056 },
2057 &Geqo_generations,
2058 0, 0, INT_MAX,
2059 NULL, NULL, NULL
2060 },
2061
2062 {
2063 /* This is PGC_SUSET to prevent hiding from log_lock_waits. */
2064 {"deadlock_timeout", PGC_SUSET, LOCK_MANAGEMENT,
2065 gettext_noop("Sets the time to wait on a lock before checking for deadlock."),
2066 NULL,
2067 GUC_UNIT_MS
2068 },
2069 &DeadlockTimeout,
2070 1000, 1, INT_MAX,
2071 NULL, NULL, NULL
2072 },
2073
2074 {
2075 {"max_standby_archive_delay", PGC_SIGHUP, REPLICATION_STANDBY,
2076 gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data."),
2077 NULL,
2078 GUC_UNIT_MS
2079 },
2080 &max_standby_archive_delay,
2081 30 * 1000, -1, INT_MAX,
2082 NULL, NULL, NULL
2083 },
2084
2085 {
2086 {"max_standby_streaming_delay", PGC_SIGHUP, REPLICATION_STANDBY,
2087 gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data."),
2088 NULL,
2089 GUC_UNIT_MS
2090 },
2091 &max_standby_streaming_delay,
2092 30 * 1000, -1, INT_MAX,
2093 NULL, NULL, NULL
2094 },
2095
2096 {
2097 {"recovery_min_apply_delay", PGC_SIGHUP, REPLICATION_STANDBY,
2098 gettext_noop("Sets the minimum delay for applying changes during recovery."),
2099 NULL,
2100 GUC_UNIT_MS
2101 },
2102 &recovery_min_apply_delay,
2103 0, 0, INT_MAX,
2104 NULL, NULL, NULL
2105 },
2106
2107 {
2108 {"wal_receiver_status_interval", PGC_SIGHUP, REPLICATION_STANDBY,
2109 gettext_noop("Sets the maximum interval between WAL receiver status reports to the sending server."),
2110 NULL,
2111 GUC_UNIT_S
2112 },
2113 &wal_receiver_status_interval,
2114 10, 0, INT_MAX / 1000,
2115 NULL, NULL, NULL
2116 },
2117
2118 {
2119 {"wal_receiver_timeout", PGC_SIGHUP, REPLICATION_STANDBY,
2120 gettext_noop("Sets the maximum wait time to receive data from the sending server."),
2121 NULL,
2122 GUC_UNIT_MS
2123 },
2124 &wal_receiver_timeout,
2125 60 * 1000, 0, INT_MAX,
2126 NULL, NULL, NULL
2127 },
2128
2129 {
2130 {"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2131 gettext_noop("Sets the maximum number of concurrent connections."),
2132 NULL
2133 },
2134 &MaxConnections,
2135 100, 1, MAX_BACKENDS,
2136 check_maxconnections, NULL, NULL
2137 },
2138
2139 {
2140 /* see max_connections */
2141 {"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2142 gettext_noop("Sets the number of connection slots reserved for superusers."),
2143 NULL
2144 },
2145 &ReservedBackends,
2146 3, 0, MAX_BACKENDS,
2147 NULL, NULL, NULL
2148 },
2149
2150 /*
2151 * We sometimes multiply the number of shared buffers by two without
2152 * checking for overflow, so we mustn't allow more than INT_MAX / 2.
2153 */
2154 {
2155 {"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
2156 gettext_noop("Sets the number of shared memory buffers used by the server."),
2157 NULL,
2158 GUC_UNIT_BLOCKS
2159 },
2160 &NBuffers,
2161 1024, 16, INT_MAX / 2,
2162 NULL, NULL, NULL
2163 },
2164
2165 {
2166 {"temp_buffers", PGC_USERSET, RESOURCES_MEM,
2167 gettext_noop("Sets the maximum number of temporary buffers used by each session."),
2168 NULL,
2169 GUC_UNIT_BLOCKS | GUC_EXPLAIN
2170 },
2171 &num_temp_buffers,
2172 1024, 100, INT_MAX / 2,
2173 check_temp_buffers, NULL, NULL
2174 },
2175
2176 {
2177 {"port", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2178 gettext_noop("Sets the TCP port the server listens on."),
2179 NULL
2180 },
2181 &PostPortNumber,
2182 DEF_PGPORT, 1, 65535,
2183 NULL, NULL, NULL
2184 },
2185
2186 {
2187 {"unix_socket_permissions", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2188 gettext_noop("Sets the access permissions of the Unix-domain socket."),
2189 gettext_noop("Unix-domain sockets use the usual Unix file system "
2190 "permission set. The parameter value is expected "
2191 "to be a numeric mode specification in the form "
2192 "accepted by the chmod and umask system calls. "
2193 "(To use the customary octal format the number must "
2194 "start with a 0 (zero).)")
2195 },
2196 &Unix_socket_permissions,
2197 0777, 0000, 0777,
2198 NULL, NULL, show_unix_socket_permissions
2199 },
2200
2201 {
2202 {"log_file_mode", PGC_SIGHUP, LOGGING_WHERE,
2203 gettext_noop("Sets the file permissions for log files."),
2204 gettext_noop("The parameter value is expected "
2205 "to be a numeric mode specification in the form "
2206 "accepted by the chmod and umask system calls. "
2207 "(To use the customary octal format the number must "
2208 "start with a 0 (zero).)")
2209 },
2210 &Log_file_mode,
2211 0600, 0000, 0777,
2212 NULL, NULL, show_log_file_mode
2213 },
2214
2215
2216 {
2217 {"data_directory_mode", PGC_INTERNAL, PRESET_OPTIONS,
2218 gettext_noop("Mode of the data directory."),
2219 gettext_noop("The parameter value is a numeric mode specification "
2220 "in the form accepted by the chmod and umask system "
2221 "calls. (To use the customary octal format the number "
2222 "must start with a 0 (zero).)"),
2223 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2224 },
2225 &data_directory_mode,
2226 0700, 0000, 0777,
2227 NULL, NULL, show_data_directory_mode
2228 },
2229
2230 {
2231 {"work_mem", PGC_USERSET, RESOURCES_MEM,
2232 gettext_noop("Sets the maximum memory to be used for query workspaces."),
2233 gettext_noop("This much memory can be used by each internal "
2234 "sort operation and hash table before switching to "
2235 "temporary disk files."),
2236 GUC_UNIT_KB | GUC_EXPLAIN
2237 },
2238 &work_mem,
2239 4096, 64, MAX_KILOBYTES,
2240 NULL, NULL, NULL
2241 },
2242
2243 {
2244 {"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
2245 gettext_noop("Sets the maximum memory to be used for maintenance operations."),
2246 gettext_noop("This includes operations such as VACUUM and CREATE INDEX."),
2247 GUC_UNIT_KB
2248 },
2249 &maintenance_work_mem,
2250 65536, 1024, MAX_KILOBYTES,
2251 NULL, NULL, NULL
2252 },
2253
2254 /*
2255 * We use the hopefully-safely-small value of 100kB as the compiled-in
2256 * default for max_stack_depth. InitializeGUCOptions will increase it if
2257 * possible, depending on the actual platform-specific stack limit.
2258 */
2259 {
2260 {"max_stack_depth", PGC_SUSET, RESOURCES_MEM,
2261 gettext_noop("Sets the maximum stack depth, in kilobytes."),
2262 NULL,
2263 GUC_UNIT_KB
2264 },
2265 &max_stack_depth,
2266 100, 100, MAX_KILOBYTES,
2267 check_max_stack_depth, assign_max_stack_depth, NULL
2268 },
2269
2270 {
2271 {"temp_file_limit", PGC_SUSET, RESOURCES_DISK,
2272 gettext_noop("Limits the total size of all temporary files used by each process."),
2273 gettext_noop("-1 means no limit."),
2274 GUC_UNIT_KB
2275 },
2276 &temp_file_limit,
2277 -1, -1, INT_MAX,
2278 NULL, NULL, NULL
2279 },
2280
2281 {
2282 {"vacuum_cost_page_hit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
2283 gettext_noop("Vacuum cost for a page found in the buffer cache."),
2284 NULL
2285 },
2286 &VacuumCostPageHit,
2287 1, 0, 10000,
2288 NULL, NULL, NULL
2289 },
2290
2291 {
2292 {"vacuum_cost_page_miss", PGC_USERSET, RESOURCES_VACUUM_DELAY,
2293 gettext_noop("Vacuum cost for a page not found in the buffer cache."),
2294 NULL
2295 },
2296 &VacuumCostPageMiss,
2297 10, 0, 10000,
2298 NULL, NULL, NULL
2299 },
2300
2301 {
2302 {"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES_VACUUM_DELAY,
2303 gettext_noop("Vacuum cost for a page dirtied by vacuum."),
2304 NULL
2305 },
2306 &VacuumCostPageDirty,
2307 20, 0, 10000,
2308 NULL, NULL, NULL
2309 },
2310
2311 {
2312 {"vacuum_cost_limit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
2313 gettext_noop("Vacuum cost amount available before napping."),
2314 NULL
2315 },
2316 &VacuumCostLimit,
2317 200, 1, 10000,
2318 NULL, NULL, NULL
2319 },
2320
2321 {
2322 {"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
2323 gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
2324 NULL
2325 },
2326 &autovacuum_vac_cost_limit,
2327 -1, -1, 10000,
2328 NULL, NULL, NULL
2329 },
2330
2331 {
2332 {"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
2333 gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
2334 NULL
2335 },
2336 &max_files_per_process,
2337 1000, 25, INT_MAX,
2338 NULL, NULL, NULL
2339 },
2340
2341 /*
2342 * See also CheckRequiredParameterValues() if this parameter changes
2343 */
2344 {
2345 {"max_prepared_transactions", PGC_POSTMASTER, RESOURCES_MEM,
2346 gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
2347 NULL
2348 },
2349 &max_prepared_xacts,
2350 0, 0, MAX_BACKENDS,
2351 NULL, NULL, NULL
2352 },
2353
2354#ifdef LOCK_DEBUG
2355 {
2356 {"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
2357 gettext_noop("Sets the minimum OID of tables for tracking locks."),
2358 gettext_noop("Is used to avoid output on system tables."),
2359 GUC_NOT_IN_SAMPLE
2360 },
2361 &Trace_lock_oidmin,
2362 FirstNormalObjectId, 0, INT_MAX,
2363 NULL, NULL, NULL
2364 },
2365 {
2366 {"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
2367 gettext_noop("Sets the OID of the table with unconditionally lock tracing."),
2368 NULL,
2369 GUC_NOT_IN_SAMPLE
2370 },
2371 &Trace_lock_table,
2372 0, 0, INT_MAX,
2373 NULL, NULL, NULL
2374 },
2375#endif
2376
2377 {
2378 {"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
2379 gettext_noop("Sets the maximum allowed duration of any statement."),
2380 gettext_noop("A value of 0 turns off the timeout."),
2381 GUC_UNIT_MS
2382 },
2383 &StatementTimeout,
2384 0, 0, INT_MAX,
2385 NULL, NULL, NULL
2386 },
2387
2388 {
2389 {"lock_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
2390 gettext_noop("Sets the maximum allowed duration of any wait for a lock."),
2391 gettext_noop("A value of 0 turns off the timeout."),
2392 GUC_UNIT_MS
2393 },
2394 &LockTimeout,
2395 0, 0, INT_MAX,
2396 NULL, NULL, NULL
2397 },
2398
2399 {
2400 {"idle_in_transaction_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
2401 gettext_noop("Sets the maximum allowed duration of any idling transaction."),
2402 gettext_noop("A value of 0 turns off the timeout."),
2403 GUC_UNIT_MS
2404 },
2405 &IdleInTransactionSessionTimeout,
2406 0, 0, INT_MAX,
2407 NULL, NULL, NULL
2408 },
2409
2410 {
2411 {"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
2412 gettext_noop("Minimum age at which VACUUM should freeze a table row."),
2413 NULL
2414 },
2415 &vacuum_freeze_min_age,
2416 50000000, 0, 1000000000,
2417 NULL, NULL, NULL
2418 },
2419
2420 {
2421 {"vacuum_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
2422 gettext_noop("Age at which VACUUM should scan whole table to freeze tuples."),
2423 NULL
2424 },
2425 &vacuum_freeze_table_age,
2426 150000000, 0, 2000000000,
2427 NULL, NULL, NULL
2428 },
2429
2430 {
2431 {"vacuum_multixact_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
2432 gettext_noop("Minimum age at which VACUUM should freeze a MultiXactId in a table row."),
2433 NULL
2434 },
2435 &vacuum_multixact_freeze_min_age,
2436 5000000, 0, 1000000000,
2437 NULL, NULL, NULL
2438 },
2439
2440 {
2441 {"vacuum_multixact_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
2442 gettext_noop("Multixact age at which VACUUM should scan whole table to freeze tuples."),
2443 NULL
2444 },
2445 &vacuum_multixact_freeze_table_age,
2446 150000000, 0, 2000000000,
2447 NULL, NULL, NULL
2448 },
2449
2450 {
2451 {"vacuum_defer_cleanup_age", PGC_SIGHUP, REPLICATION_MASTER,
2452 gettext_noop("Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."),
2453 NULL
2454 },
2455 &vacuum_defer_cleanup_age,
2456 0, 0, 1000000,
2457 NULL, NULL, NULL
2458 },
2459
2460 /*
2461 * See also CheckRequiredParameterValues() if this parameter changes
2462 */
2463 {
2464 {"max_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
2465 gettext_noop("Sets the maximum number of locks per transaction."),
2466 gettext_noop("The shared lock table is sized on the assumption that "
2467 "at most max_locks_per_transaction * max_connections distinct "
2468 "objects will need to be locked at any one time.")
2469 },
2470 &max_locks_per_xact,
2471 64, 10, INT_MAX,
2472 NULL, NULL, NULL
2473 },
2474
2475 {
2476 {"max_pred_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
2477 gettext_noop("Sets the maximum number of predicate locks per transaction."),
2478 gettext_noop("The shared predicate lock table is sized on the assumption that "
2479 "at most max_pred_locks_per_transaction * max_connections distinct "
2480 "objects will need to be locked at any one time.")
2481 },
2482 &max_predicate_locks_per_xact,
2483 64, 10, INT_MAX,
2484 NULL, NULL, NULL
2485 },
2486
2487 {
2488 {"max_pred_locks_per_relation", PGC_SIGHUP, LOCK_MANAGEMENT,
2489 gettext_noop("Sets the maximum number of predicate-locked pages and tuples per relation."),
2490 gettext_noop("If more than this total of pages and tuples in the same relation are locked "
2491 "by a connection, those locks are replaced by a relation-level lock.")
2492 },
2493 &max_predicate_locks_per_relation,
2494 -2, INT_MIN, INT_MAX,
2495 NULL, NULL, NULL
2496 },
2497
2498 {
2499 {"max_pred_locks_per_page", PGC_SIGHUP, LOCK_MANAGEMENT,
2500 gettext_noop("Sets the maximum number of predicate-locked tuples per page."),
2501 gettext_noop("If more than this number of tuples on the same page are locked "
2502 "by a connection, those locks are replaced by a page-level lock.")
2503 },
2504 &max_predicate_locks_per_page,
2505 2, 0, INT_MAX,
2506 NULL, NULL, NULL
2507 },
2508
2509 {
2510 {"authentication_timeout", PGC_SIGHUP, CONN_AUTH_AUTH,
2511 gettext_noop("Sets the maximum allowed time to complete client authentication."),
2512 NULL,
2513 GUC_UNIT_S
2514 },
2515 &AuthenticationTimeout,
2516 60, 1, 600,
2517 NULL, NULL, NULL
2518 },
2519
2520 {
2521 /* Not for general use */
2522 {"pre_auth_delay", PGC_SIGHUP, DEVELOPER_OPTIONS,
2523 gettext_noop("Waits N seconds on connection startup before authentication."),
2524 gettext_noop("This allows attaching a debugger to the process."),
2525 GUC_NOT_IN_SAMPLE | GUC_UNIT_S
2526 },
2527 &PreAuthDelay,
2528 0, 0, 60,
2529 NULL, NULL, NULL
2530 },
2531
2532 {
2533 {"wal_keep_segments", PGC_SIGHUP, REPLICATION_SENDING,
2534 gettext_noop("Sets the number of WAL files held for standby servers."),
2535 NULL
2536 },
2537 &wal_keep_segments,
2538 0, 0, INT_MAX,
2539 NULL, NULL, NULL
2540 },
2541
2542 {
2543 {"min_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
2544 gettext_noop("Sets the minimum size to shrink the WAL to."),
2545 NULL,
2546 GUC_UNIT_MB
2547 },
2548 &min_wal_size_mb,
2549 DEFAULT_MIN_WAL_SEGS * (DEFAULT_XLOG_SEG_SIZE / (1024 * 1024)),
2550 2, MAX_KILOBYTES,
2551 NULL, NULL, NULL
2552 },
2553
2554 {
2555 {"max_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
2556 gettext_noop("Sets the WAL size that triggers a checkpoint."),
2557 NULL,
2558 GUC_UNIT_MB
2559 },
2560 &max_wal_size_mb,
2561 DEFAULT_MAX_WAL_SEGS * (DEFAULT_XLOG_SEG_SIZE / (1024 * 1024)),
2562 2, MAX_KILOBYTES,
2563 NULL, assign_max_wal_size, NULL
2564 },
2565
2566 {
2567 {"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS,
2568 gettext_noop("Sets the maximum time between automatic WAL checkpoints."),
2569 NULL,
2570 GUC_UNIT_S
2571 },
2572 &CheckPointTimeout,
2573 300, 30, 86400,
2574 NULL, NULL, NULL
2575 },
2576
2577 {
2578 {"checkpoint_warning", PGC_SIGHUP, WAL_CHECKPOINTS,
2579 gettext_noop("Enables warnings if checkpoint segments are filled more "
2580 "frequently than this."),
2581 gettext_noop("Write a message to the server log if checkpoints "
2582 "caused by the filling of checkpoint segment files happens more "
2583 "frequently than this number of seconds. Zero turns off the warning."),
2584 GUC_UNIT_S
2585 },
2586 &CheckPointWarning,
2587 30, 0, INT_MAX,
2588 NULL, NULL, NULL
2589 },
2590
2591 {
2592 {"checkpoint_flush_after", PGC_SIGHUP, WAL_CHECKPOINTS,
2593 gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
2594 NULL,
2595 GUC_UNIT_BLOCKS
2596 },
2597 &checkpoint_flush_after,
2598 DEFAULT_CHECKPOINT_FLUSH_AFTER, 0, WRITEBACK_MAX_PENDING_FLUSHES,
2599 NULL, NULL, NULL
2600 },
2601
2602 {
2603 {"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
2604 gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
2605 NULL,
2606 GUC_UNIT_XBLOCKS
2607 },
2608 &XLOGbuffers,
2609 -1, -1, (INT_MAX / XLOG_BLCKSZ),
2610 check_wal_buffers, NULL, NULL
2611 },
2612
2613 {
2614 {"wal_writer_delay", PGC_SIGHUP, WAL_SETTINGS,
2615 gettext_noop("Time between WAL flushes performed in the WAL writer."),
2616 NULL,
2617 GUC_UNIT_MS
2618 },
2619 &WalWriterDelay,
2620 200, 1, 10000,
2621 NULL, NULL, NULL
2622 },
2623
2624 {
2625 {"wal_writer_flush_after", PGC_SIGHUP, WAL_SETTINGS,
2626 gettext_noop("Amount of WAL written out by WAL writer that triggers a flush."),
2627 NULL,
2628 GUC_UNIT_XBLOCKS
2629 },
2630 &WalWriterFlushAfter,
2631 (1024 * 1024) / XLOG_BLCKSZ, 0, INT_MAX,
2632 NULL, NULL, NULL
2633 },
2634
2635 {
2636 {"max_wal_senders", PGC_POSTMASTER, REPLICATION_SENDING,
2637 gettext_noop("Sets the maximum number of simultaneously running WAL sender processes."),
2638 NULL
2639 },
2640 &max_wal_senders,
2641 10, 0, MAX_BACKENDS,
2642 check_max_wal_senders, NULL, NULL
2643 },
2644
2645 {
2646 /* see max_wal_senders */
2647 {"max_replication_slots", PGC_POSTMASTER, REPLICATION_SENDING,
2648 gettext_noop("Sets the maximum number of simultaneously defined replication slots."),
2649 NULL
2650 },
2651 &max_replication_slots,
2652 10, 0, MAX_BACKENDS /* XXX? */ ,
2653 NULL, NULL, NULL
2654 },
2655
2656 {
2657 {"wal_sender_timeout", PGC_USERSET, REPLICATION_SENDING,
2658 gettext_noop("Sets the maximum time to wait for WAL replication."),
2659 NULL,
2660 GUC_UNIT_MS
2661 },
2662 &wal_sender_timeout,
2663 60 * 1000, 0, INT_MAX,
2664 NULL, NULL, NULL
2665 },
2666
2667 {
2668 {"commit_delay", PGC_SUSET, WAL_SETTINGS,
2669 gettext_noop("Sets the delay in microseconds between transaction commit and "
2670 "flushing WAL to disk."),
2671 NULL
2672 /* we have no microseconds designation, so can't supply units here */
2673 },
2674 &CommitDelay,
2675 0, 0, 100000,
2676 NULL, NULL, NULL
2677 },
2678
2679 {
2680 {"commit_siblings", PGC_USERSET, WAL_SETTINGS,
2681 gettext_noop("Sets the minimum concurrent open transactions before performing "
2682 "commit_delay."),
2683 NULL
2684 },
2685 &CommitSiblings,
2686 5, 0, 1000,
2687 NULL, NULL, NULL
2688 },
2689
2690 {
2691 {"extra_float_digits", PGC_USERSET, CLIENT_CONN_LOCALE,
2692 gettext_noop("Sets the number of digits displayed for floating-point values."),
2693 gettext_noop("This affects real, double precision, and geometric data types. "
2694 "A zero or negative parameter value is added to the standard "
2695 "number of digits (FLT_DIG or DBL_DIG as appropriate). "
2696 "Any value greater than zero selects precise output mode.")
2697 },
2698 &extra_float_digits,
2699 1, -15, 3,
2700 NULL, NULL, NULL
2701 },
2702
2703 {
2704 {"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN,
2705 gettext_noop("Sets the minimum execution time above which "
2706 "statements will be logged."),
2707 gettext_noop("Zero prints all queries. -1 turns this feature off."),
2708 GUC_UNIT_MS
2709 },
2710 &log_min_duration_statement,
2711 -1, -1, INT_MAX,
2712 NULL, NULL, NULL
2713 },
2714
2715 {
2716 {"log_autovacuum_min_duration", PGC_SIGHUP, LOGGING_WHAT,
2717 gettext_noop("Sets the minimum execution time above which "
2718 "autovacuum actions will be logged."),
2719 gettext_noop("Zero prints all actions. -1 turns autovacuum logging off."),
2720 GUC_UNIT_MS
2721 },
2722 &Log_autovacuum_min_duration,
2723 -1, -1, INT_MAX,
2724 NULL, NULL, NULL
2725 },
2726
2727 {
2728 {"bgwriter_delay", PGC_SIGHUP, RESOURCES_BGWRITER,
2729 gettext_noop("Background writer sleep time between rounds."),
2730 NULL,
2731 GUC_UNIT_MS
2732 },
2733 &BgWriterDelay,
2734 200, 10, 10000,
2735 NULL, NULL, NULL
2736 },
2737
2738 {
2739 {"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES_BGWRITER,
2740 gettext_noop("Background writer maximum number of LRU pages to flush per round."),
2741 NULL
2742 },
2743 &bgwriter_lru_maxpages,
2744 100, 0, INT_MAX / 2, /* Same upper limit as shared_buffers */
2745 NULL, NULL, NULL
2746 },
2747
2748 {
2749 {"bgwriter_flush_after", PGC_SIGHUP, RESOURCES_BGWRITER,
2750 gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
2751 NULL,
2752 GUC_UNIT_BLOCKS
2753 },
2754 &bgwriter_flush_after,
2755 DEFAULT_BGWRITER_FLUSH_AFTER, 0, WRITEBACK_MAX_PENDING_FLUSHES,
2756 NULL, NULL, NULL
2757 },
2758
2759 {
2760 {"effective_io_concurrency",
2761 PGC_USERSET,
2762 RESOURCES_ASYNCHRONOUS,
2763 gettext_noop("Number of simultaneous requests that can be handled efficiently by the disk subsystem."),
2764 gettext_noop("For RAID arrays, this should be approximately the number of drive spindles in the array."),
2765 GUC_EXPLAIN
2766 },
2767 &effective_io_concurrency,
2768#ifdef USE_PREFETCH
2769 1,
2770#else
2771 0,
2772#endif
2773 0, MAX_IO_CONCURRENCY,
2774 check_effective_io_concurrency, assign_effective_io_concurrency, NULL
2775 },
2776
2777 {
2778 {"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
2779 gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
2780 NULL,
2781 GUC_UNIT_BLOCKS
2782 },
2783 &backend_flush_after,
2784 DEFAULT_BACKEND_FLUSH_AFTER, 0, WRITEBACK_MAX_PENDING_FLUSHES,
2785 NULL, NULL, NULL
2786 },
2787
2788 {
2789 {"max_worker_processes",
2790 PGC_POSTMASTER,
2791 RESOURCES_ASYNCHRONOUS,
2792 gettext_noop("Maximum number of concurrent worker processes."),
2793 NULL,
2794 },
2795 &max_worker_processes,
2796 8, 0, MAX_BACKENDS,
2797 check_max_worker_processes, NULL, NULL
2798 },
2799
2800 {
2801 {"max_logical_replication_workers",
2802 PGC_POSTMASTER,
2803 REPLICATION_SUBSCRIBERS,
2804 gettext_noop("Maximum number of logical replication worker processes."),
2805 NULL,
2806 },
2807 &max_logical_replication_workers,
2808 4, 0, MAX_BACKENDS,
2809 NULL, NULL, NULL
2810 },
2811
2812 {
2813 {"max_sync_workers_per_subscription",
2814 PGC_SIGHUP,
2815 REPLICATION_SUBSCRIBERS,
2816 gettext_noop("Maximum number of table synchronization workers per subscription."),
2817 NULL,
2818 },
2819 &max_sync_workers_per_subscription,
2820 2, 0, MAX_BACKENDS,
2821 NULL, NULL, NULL
2822 },
2823
2824 {
2825 {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
2826 gettext_noop("Automatic log file rotation will occur after N minutes."),
2827 NULL,
2828 GUC_UNIT_MIN
2829 },
2830 &Log_RotationAge,
2831 HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / SECS_PER_MINUTE,
2832 NULL, NULL, NULL
2833 },
2834
2835 {
2836 {"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
2837 gettext_noop("Automatic log file rotation will occur after N kilobytes."),
2838 NULL,
2839 GUC_UNIT_KB
2840 },
2841 &Log_RotationSize,
2842 10 * 1024, 0, INT_MAX / 1024,
2843 NULL, NULL, NULL
2844 },
2845
2846 {
2847 {"max_function_args", PGC_INTERNAL, PRESET_OPTIONS,
2848 gettext_noop("Shows the maximum number of function arguments."),
2849 NULL,
2850 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2851 },
2852 &max_function_args,
2853 FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS,
2854 NULL, NULL, NULL
2855 },
2856
2857 {
2858 {"max_index_keys", PGC_INTERNAL, PRESET_OPTIONS,
2859 gettext_noop("Shows the maximum number of index keys."),
2860 NULL,
2861 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2862 },
2863 &max_index_keys,
2864 INDEX_MAX_KEYS, INDEX_MAX_KEYS, INDEX_MAX_KEYS,
2865 NULL, NULL, NULL
2866 },
2867
2868 {
2869 {"max_identifier_length", PGC_INTERNAL, PRESET_OPTIONS,
2870 gettext_noop("Shows the maximum identifier length."),
2871 NULL,
2872 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2873 },
2874 &max_identifier_length,
2875 NAMEDATALEN - 1, NAMEDATALEN - 1, NAMEDATALEN - 1,
2876 NULL, NULL, NULL
2877 },
2878
2879 {
2880 {"block_size", PGC_INTERNAL, PRESET_OPTIONS,
2881 gettext_noop("Shows the size of a disk block."),
2882 NULL,
2883 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2884 },
2885 &block_size,
2886 BLCKSZ, BLCKSZ, BLCKSZ,
2887 NULL, NULL, NULL
2888 },
2889
2890 {
2891 {"segment_size", PGC_INTERNAL, PRESET_OPTIONS,
2892 gettext_noop("Shows the number of pages per disk file."),
2893 NULL,
2894 GUC_UNIT_BLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2895 },
2896 &segment_size,
2897 RELSEG_SIZE, RELSEG_SIZE, RELSEG_SIZE,
2898 NULL, NULL, NULL
2899 },
2900
2901 {
2902 {"wal_block_size", PGC_INTERNAL, PRESET_OPTIONS,
2903 gettext_noop("Shows the block size in the write ahead log."),
2904 NULL,
2905 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2906 },
2907 &wal_block_size,
2908 XLOG_BLCKSZ, XLOG_BLCKSZ, XLOG_BLCKSZ,
2909 NULL, NULL, NULL
2910 },
2911
2912 {
2913 {"wal_retrieve_retry_interval", PGC_SIGHUP, REPLICATION_STANDBY,
2914 gettext_noop("Sets the time to wait before retrying to retrieve WAL "
2915 "after a failed attempt."),
2916 NULL,
2917 GUC_UNIT_MS
2918 },
2919 &wal_retrieve_retry_interval,
2920 5000, 1, INT_MAX,
2921 NULL, NULL, NULL
2922 },
2923
2924 {
2925 {"wal_segment_size", PGC_INTERNAL, PRESET_OPTIONS,
2926 gettext_noop("Shows the size of write ahead log segments."),
2927 NULL,
2928 GUC_UNIT_BYTE | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2929 },
2930 &wal_segment_size,
2931 DEFAULT_XLOG_SEG_SIZE,
2932 WalSegMinSize,
2933 WalSegMaxSize,
2934 NULL, NULL, NULL
2935 },
2936
2937 {
2938 {"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
2939 gettext_noop("Time to sleep between autovacuum runs."),
2940 NULL,
2941 GUC_UNIT_S
2942 },
2943 &autovacuum_naptime,
2944 60, 1, INT_MAX / 1000,
2945 NULL, NULL, NULL
2946 },
2947 {
2948 {"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
2949 gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
2950 NULL
2951 },
2952 &autovacuum_vac_thresh,
2953 50, 0, INT_MAX,
2954 NULL, NULL, NULL
2955 },
2956 {
2957 {"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
2958 gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."),
2959 NULL
2960 },
2961 &autovacuum_anl_thresh,
2962 50, 0, INT_MAX,
2963 NULL, NULL, NULL
2964 },
2965 {
2966 /* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
2967 {"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
2968 gettext_noop("Age at which to autovacuum a table to prevent transaction ID wraparound."),
2969 NULL
2970 },
2971 &autovacuum_freeze_max_age,
2972 /* see pg_resetwal if you change the upper-limit value */
2973 200000000, 100000, 2000000000,
2974 NULL, NULL, NULL
2975 },
2976 {
2977 /* see multixact.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
2978 {"autovacuum_multixact_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
2979 gettext_noop("Multixact age at which to autovacuum a table to prevent multixact wraparound."),
2980 NULL
2981 },
2982 &autovacuum_multixact_freeze_max_age,
2983 400000000, 10000, 2000000000,
2984 NULL, NULL, NULL
2985 },
2986 {
2987 /* see max_connections */
2988 {"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
2989 gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
2990 NULL
2991 },
2992 &autovacuum_max_workers,
2993 3, 1, MAX_BACKENDS,
2994 check_autovacuum_max_workers, NULL, NULL
2995 },
2996
2997 {
2998 {"max_parallel_maintenance_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
2999 gettext_noop("Sets the maximum number of parallel processes per maintenance operation."),
3000 NULL
3001 },
3002 &max_parallel_maintenance_workers,
3003 2, 0, 1024,
3004 NULL, NULL, NULL
3005 },
3006
3007 {
3008 {"max_parallel_workers_per_gather", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
3009 gettext_noop("Sets the maximum number of parallel processes per executor node."),
3010 NULL,
3011 GUC_EXPLAIN
3012 },
3013 &max_parallel_workers_per_gather,
3014 2, 0, MAX_PARALLEL_WORKER_LIMIT,
3015 NULL, NULL, NULL
3016 },
3017
3018 {
3019 {"max_parallel_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
3020 gettext_noop("Sets the maximum number of parallel workers that can be active at one time."),
3021 NULL,
3022 GUC_EXPLAIN
3023 },
3024 &max_parallel_workers,
3025 8, 0, MAX_PARALLEL_WORKER_LIMIT,
3026 NULL, NULL, NULL
3027 },
3028
3029 {
3030 {"autovacuum_work_mem", PGC_SIGHUP, RESOURCES_MEM,
3031 gettext_noop("Sets the maximum memory to be used by each autovacuum worker process."),
3032 NULL,
3033 GUC_UNIT_KB
3034 },
3035 &autovacuum_work_mem,
3036 -1, -1, MAX_KILOBYTES,
3037 check_autovacuum_work_mem, NULL, NULL
3038 },
3039
3040 {
3041 {"old_snapshot_threshold", PGC_POSTMASTER, RESOURCES_ASYNCHRONOUS,
3042 gettext_noop("Time before a snapshot is too old to read pages changed after the snapshot was taken."),
3043 gettext_noop("A value of -1 disables this feature."),
3044 GUC_UNIT_MIN
3045 },
3046 &old_snapshot_threshold,
3047 -1, -1, MINS_PER_HOUR * HOURS_PER_DAY * 60,
3048 NULL, NULL, NULL
3049 },
3050
3051 {
3052 {"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER,
3053 gettext_noop("Time between issuing TCP keepalives."),
3054 gettext_noop("A value of 0 uses the system default."),
3055 GUC_UNIT_S
3056 },
3057 &tcp_keepalives_idle,
3058 0, 0, INT_MAX,
3059 NULL, assign_tcp_keepalives_idle, show_tcp_keepalives_idle
3060 },
3061
3062 {
3063 {"tcp_keepalives_interval", PGC_USERSET, CLIENT_CONN_OTHER,
3064 gettext_noop("Time between TCP keepalive retransmits."),
3065 gettext_noop("A value of 0 uses the system default."),
3066 GUC_UNIT_S
3067 },
3068 &tcp_keepalives_interval,
3069 0, 0, INT_MAX,
3070 NULL, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
3071 },
3072
3073 {
3074 {"ssl_renegotiation_limit", PGC_USERSET, CONN_AUTH_SSL,
3075 gettext_noop("SSL renegotiation is no longer supported; this can only be 0."),
3076 NULL,
3077 GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE,
3078 },
3079 &ssl_renegotiation_limit,
3080 0, 0, 0,
3081 NULL, NULL, NULL
3082 },
3083
3084 {
3085 {"tcp_keepalives_count", PGC_USERSET, CLIENT_CONN_OTHER,
3086 gettext_noop("Maximum number of TCP keepalive retransmits."),
3087 gettext_noop("This controls the number of consecutive keepalive retransmits that can be "
3088 "lost before a connection is considered dead. A value of 0 uses the "
3089 "system default."),
3090 },
3091 &tcp_keepalives_count,
3092 0, 0, INT_MAX,
3093 NULL, assign_tcp_keepalives_count, show_tcp_keepalives_count
3094 },
3095
3096 {
3097 {"gin_fuzzy_search_limit", PGC_USERSET, CLIENT_CONN_OTHER,
3098 gettext_noop("Sets the maximum allowed result for exact search by GIN."),
3099 NULL,
3100 0
3101 },
3102 &GinFuzzySearchLimit,
3103 0, 0, INT_MAX,
3104 NULL, NULL, NULL
3105 },
3106
3107 {
3108 {"effective_cache_size", PGC_USERSET, QUERY_TUNING_COST,
3109 gettext_noop("Sets the planner's assumption about the total size of the data caches."),
3110 gettext_noop("That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. "
3111 "This is measured in disk pages, which are normally 8 kB each."),
3112 GUC_UNIT_BLOCKS | GUC_EXPLAIN,
3113 },
3114 &effective_cache_size,
3115 DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX,
3116 NULL, NULL, NULL
3117 },
3118
3119 {
3120 {"min_parallel_table_scan_size", PGC_USERSET, QUERY_TUNING_COST,
3121 gettext_noop("Sets the minimum amount of table data for a parallel scan."),
3122 gettext_noop("If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered."),
3123 GUC_UNIT_BLOCKS | GUC_EXPLAIN,
3124 },
3125 &min_parallel_table_scan_size,
3126 (8 * 1024 * 1024) / BLCKSZ, 0, INT_MAX / 3,
3127 NULL, NULL, NULL
3128 },
3129
3130 {
3131 {"min_parallel_index_scan_size", PGC_USERSET, QUERY_TUNING_COST,
3132 gettext_noop("Sets the minimum amount of index data for a parallel scan."),
3133 gettext_noop("If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered."),
3134 GUC_UNIT_BLOCKS | GUC_EXPLAIN,
3135 },
3136 &min_parallel_index_scan_size,
3137 (512 * 1024) / BLCKSZ, 0, INT_MAX / 3,
3138 NULL, NULL, NULL
3139 },
3140
3141 {
3142 /* Can't be set in postgresql.conf */
3143 {"server_version_num", PGC_INTERNAL, PRESET_OPTIONS,
3144 gettext_noop("Shows the server version as an integer."),
3145 NULL,
3146 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
3147 },
3148 &server_version_num,
3149 PG_VERSION_NUM, PG_VERSION_NUM, PG_VERSION_NUM,
3150 NULL, NULL, NULL
3151 },
3152
3153 {
3154 {"log_temp_files", PGC_SUSET, LOGGING_WHAT,
3155 gettext_noop("Log the use of temporary files larger than this number of kilobytes."),
3156 gettext_noop("Zero logs all files. The default is -1 (turning this feature off)."),
3157 GUC_UNIT_KB
3158 },
3159 &log_temp_files,
3160 -1, -1, INT_MAX,
3161 NULL, NULL, NULL
3162 },
3163
3164 {
3165 {"track_activity_query_size", PGC_POSTMASTER, RESOURCES_MEM,
3166 gettext_noop("Sets the size reserved for pg_stat_activity.query, in bytes."),
3167 NULL,
3168 GUC_UNIT_BYTE
3169 },
3170 &pgstat_track_activity_query_size,
3171 1024, 100, 102400,
3172 NULL, NULL, NULL
3173 },
3174
3175 {
3176 {"gin_pending_list_limit", PGC_USERSET, CLIENT_CONN_STATEMENT,
3177 gettext_noop("Sets the maximum size of the pending list for GIN index."),
3178 NULL,
3179 GUC_UNIT_KB
3180 },
3181 &gin_pending_list_limit,
3182 4096, 64, MAX_KILOBYTES,
3183 NULL, NULL, NULL
3184 },
3185
3186 {
3187 {"tcp_user_timeout", PGC_USERSET, CLIENT_CONN_OTHER,
3188 gettext_noop("TCP user timeout."),
3189 gettext_noop("A value of 0 uses the system default."),
3190 GUC_UNIT_MS
3191 },
3192 &tcp_user_timeout,
3193 0, 0, INT_MAX,
3194 NULL, assign_tcp_user_timeout, show_tcp_user_timeout
3195 },
3196
3197 /* End-of-list marker */
3198 {
3199 {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
3200 }
3201};
3202
3203
3204static struct config_real ConfigureNamesReal[] =
3205{
3206 {
3207 {"seq_page_cost", PGC_USERSET, QUERY_TUNING_COST,
3208 gettext_noop("Sets the planner's estimate of the cost of a "
3209 "sequentially fetched disk page."),
3210 NULL,
3211 GUC_EXPLAIN
3212 },
3213 &seq_page_cost,
3214 DEFAULT_SEQ_PAGE_COST, 0, DBL_MAX,
3215 NULL, NULL, NULL
3216 },
3217 {
3218 {"random_page_cost", PGC_USERSET, QUERY_TUNING_COST,
3219 gettext_noop("Sets the planner's estimate of the cost of a "
3220 "nonsequentially fetched disk page."),
3221 NULL,
3222 GUC_EXPLAIN
3223 },
3224 &random_page_cost,
3225 DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX,
3226 NULL, NULL, NULL
3227 },
3228 {
3229 {"cpu_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
3230 gettext_noop("Sets the planner's estimate of the cost of "
3231 "processing each tuple (row)."),
3232 NULL,
3233 GUC_EXPLAIN
3234 },
3235 &cpu_tuple_cost,
3236 DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX,
3237 NULL, NULL, NULL
3238 },
3239 {
3240 {"cpu_index_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
3241 gettext_noop("Sets the planner's estimate of the cost of "
3242 "processing each index entry during an index scan."),
3243 NULL,
3244 GUC_EXPLAIN
3245 },
3246 &cpu_index_tuple_cost,
3247 DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX,
3248 NULL, NULL, NULL
3249 },
3250 {
3251 {"cpu_operator_cost", PGC_USERSET, QUERY_TUNING_COST,
3252 gettext_noop("Sets the planner's estimate of the cost of "
3253 "processing each operator or function call."),
3254 NULL,
3255 GUC_EXPLAIN
3256 },
3257 &cpu_operator_cost,
3258 DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX,
3259 NULL, NULL, NULL
3260 },
3261 {
3262 {"parallel_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
3263 gettext_noop("Sets the planner's estimate of the cost of "
3264 "passing each tuple (row) from worker to master backend."),
3265 NULL,
3266 GUC_EXPLAIN
3267 },
3268 &parallel_tuple_cost,
3269 DEFAULT_PARALLEL_TUPLE_COST, 0, DBL_MAX,
3270 NULL, NULL, NULL
3271 },
3272 {
3273 {"parallel_setup_cost", PGC_USERSET, QUERY_TUNING_COST,
3274 gettext_noop("Sets the planner's estimate of the cost of "
3275 "starting up worker processes for parallel query."),
3276 NULL,
3277 GUC_EXPLAIN
3278 },
3279 &parallel_setup_cost,
3280 DEFAULT_PARALLEL_SETUP_COST, 0, DBL_MAX,
3281 NULL, NULL, NULL
3282 },
3283
3284 {
3285 {"jit_above_cost", PGC_USERSET, QUERY_TUNING_COST,
3286 gettext_noop("Perform JIT compilation if query is more expensive."),
3287 gettext_noop("-1 disables JIT compilation."),
3288 GUC_EXPLAIN
3289 },
3290 &jit_above_cost,
3291 100000, -1, DBL_MAX,
3292 NULL, NULL, NULL
3293 },
3294
3295 {
3296 {"jit_optimize_above_cost", PGC_USERSET, QUERY_TUNING_COST,
3297 gettext_noop("Optimize JITed functions if query is more expensive."),
3298 gettext_noop("-1 disables optimization."),
3299 GUC_EXPLAIN
3300 },
3301 &jit_optimize_above_cost,
3302 500000, -1, DBL_MAX,
3303 NULL, NULL, NULL
3304 },
3305
3306 {
3307 {"jit_inline_above_cost", PGC_USERSET, QUERY_TUNING_COST,
3308 gettext_noop("Perform JIT inlining if query is more expensive."),
3309 gettext_noop("-1 disables inlining."),
3310 GUC_EXPLAIN
3311 },
3312 &jit_inline_above_cost,
3313 500000, -1, DBL_MAX,
3314 NULL, NULL, NULL
3315 },
3316
3317 {
3318 {"cursor_tuple_fraction", PGC_USERSET, QUERY_TUNING_OTHER,
3319 gettext_noop("Sets the planner's estimate of the fraction of "
3320 "a cursor's rows that will be retrieved."),
3321 NULL,
3322 GUC_EXPLAIN
3323 },
3324 &cursor_tuple_fraction,
3325 DEFAULT_CURSOR_TUPLE_FRACTION, 0.0, 1.0,
3326 NULL, NULL, NULL
3327 },
3328
3329 {
3330 {"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO,
3331 gettext_noop("GEQO: selective pressure within the population."),
3332 NULL,
3333 GUC_EXPLAIN
3334 },
3335 &Geqo_selection_bias,
3336 DEFAULT_GEQO_SELECTION_BIAS,
3337 MIN_GEQO_SELECTION_BIAS, MAX_GEQO_SELECTION_BIAS,
3338 NULL, NULL, NULL
3339 },
3340 {
3341 {"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
3342 gettext_noop("GEQO: seed for random path selection."),
3343 NULL,
3344 GUC_EXPLAIN
3345 },
3346 &Geqo_seed,
3347 0.0, 0.0, 1.0,
3348 NULL, NULL, NULL
3349 },
3350
3351 {
3352 {"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES_BGWRITER,
3353 gettext_noop("Multiple of the average buffer usage to free per round."),
3354 NULL
3355 },
3356 &bgwriter_lru_multiplier,
3357 2.0, 0.0, 10.0,
3358 NULL, NULL, NULL
3359 },
3360
3361 {
3362 {"seed", PGC_USERSET, UNGROUPED,
3363 gettext_noop("Sets the seed for random-number generation."),
3364 NULL,
3365 GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
3366 },
3367 &phony_random_seed,
3368 0.0, -1.0, 1.0,
3369 check_random_seed, assign_random_seed, show_random_seed
3370 },
3371
3372 {
3373 {"vacuum_cost_delay", PGC_USERSET, RESOURCES_VACUUM_DELAY,
3374 gettext_noop("Vacuum cost delay in milliseconds."),
3375 NULL,
3376 GUC_UNIT_MS
3377 },
3378 &VacuumCostDelay,
3379 0, 0, 100,
3380 NULL, NULL, NULL
3381 },
3382
3383 {
3384 {"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
3385 gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
3386 NULL,
3387 GUC_UNIT_MS
3388 },
3389 &autovacuum_vac_cost_delay,
3390 2, -1, 100,
3391 NULL, NULL, NULL
3392 },
3393
3394 {
3395 {"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
3396 gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
3397 NULL
3398 },
3399 &autovacuum_vac_scale,
3400 0.2, 0.0, 100.0,
3401 NULL, NULL, NULL
3402 },
3403 {
3404 {"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
3405 gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."),
3406 NULL
3407 },
3408 &autovacuum_anl_scale,
3409 0.1, 0.0, 100.0,
3410 NULL, NULL, NULL
3411 },
3412
3413 {
3414 {"checkpoint_completion_target", PGC_SIGHUP, WAL_CHECKPOINTS,
3415 gettext_noop("Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."),
3416 NULL
3417 },
3418 &CheckPointCompletionTarget,
3419 0.5, 0.0, 1.0,
3420 NULL, NULL, NULL
3421 },
3422
3423 {
3424 {"vacuum_cleanup_index_scale_factor", PGC_USERSET, CLIENT_CONN_STATEMENT,
3425 gettext_noop("Number of tuple inserts prior to index cleanup as a fraction of reltuples."),
3426 NULL
3427 },
3428 &vacuum_cleanup_index_scale_factor,
3429 0.1, 0.0, 1e10,
3430 NULL, NULL, NULL
3431 },
3432
3433 {
3434 {"log_transaction_sample_rate", PGC_SUSET, LOGGING_WHEN,
3435 gettext_noop("Set the fraction of transactions to log for new transactions."),
3436 gettext_noop("Logs all statements from a fraction of transactions. "
3437 "Use a value between 0.0 (never log) and 1.0 (log all "
3438 "statements for all transactions).")
3439 },
3440 &log_xact_sample_rate,
3441 0.0, 0.0, 1.0,
3442 NULL, NULL, NULL
3443 },
3444
3445 /* End-of-list marker */
3446 {
3447 {NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL, NULL
3448 }
3449};
3450
3451
3452static struct config_string ConfigureNamesString[] =
3453{
3454 {
3455 {"archive_command", PGC_SIGHUP, WAL_ARCHIVING,
3456 gettext_noop("Sets the shell command that will be called to archive a WAL file."),
3457 NULL
3458 },
3459 &XLogArchiveCommand,
3460 "",
3461 NULL, NULL, show_archive_command
3462 },
3463
3464 {
3465 {"restore_command", PGC_POSTMASTER, WAL_ARCHIVE_RECOVERY,
3466 gettext_noop("Sets the shell command that will retrieve an archived WAL file."),
3467 NULL
3468 },
3469 &recoveryRestoreCommand,
3470 "",
3471 NULL, NULL, NULL
3472 },
3473
3474 {
3475 {"archive_cleanup_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
3476 gettext_noop("Sets the shell command that will be executed at every restart point."),
3477 NULL
3478 },
3479 &archiveCleanupCommand,
3480 "",
3481 NULL, NULL, NULL
3482 },
3483
3484 {
3485 {"recovery_end_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
3486 gettext_noop("Sets the shell command that will be executed once at the end of recovery."),
3487 NULL
3488 },
3489 &recoveryEndCommand,
3490 "",
3491 NULL, NULL, NULL
3492 },
3493
3494 {
3495 {"recovery_target_timeline", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
3496 gettext_noop("Specifies the timeline to recover into."),
3497 NULL
3498 },
3499 &recovery_target_timeline_string,
3500 "latest",
3501 check_recovery_target_timeline, assign_recovery_target_timeline, NULL
3502 },
3503
3504 {
3505 {"recovery_target", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
3506 gettext_noop("Set to \"immediate\" to end recovery as soon as a consistent state is reached."),
3507 NULL
3508 },
3509 &recovery_target_string,
3510 "",
3511 check_recovery_target, assign_recovery_target, NULL
3512 },
3513 {
3514 {"recovery_target_xid", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
3515 gettext_noop("Sets the transaction ID up to which recovery will proceed."),
3516 NULL
3517 },
3518 &recovery_target_xid_string,
3519 "",
3520 check_recovery_target_xid, assign_recovery_target_xid, NULL
3521 },
3522 {
3523 {"recovery_target_time", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
3524 gettext_noop("Sets the time stamp up to which recovery will proceed."),
3525 NULL
3526 },
3527 &recovery_target_time_string,
3528 "",
3529 check_recovery_target_time, assign_recovery_target_time, NULL
3530 },
3531 {
3532 {"recovery_target_name", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
3533 gettext_noop("Sets the named restore point up to which recovery will proceed."),
3534 NULL
3535 },
3536 &recovery_target_name_string,
3537 "",
3538 check_recovery_target_name, assign_recovery_target_name, NULL
3539 },
3540 {
3541 {"recovery_target_lsn", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
3542 gettext_noop("Sets the LSN of the write-ahead log location up to which recovery will proceed."),
3543 NULL
3544 },
3545 &recovery_target_lsn_string,
3546 "",
3547 check_recovery_target_lsn, assign_recovery_target_lsn, NULL
3548 },
3549
3550 {
3551 {"promote_trigger_file", PGC_SIGHUP, REPLICATION_STANDBY,
3552 gettext_noop("Specifies a file name whose presence ends recovery in the standby."),
3553 NULL
3554 },
3555 &PromoteTriggerFile,
3556 "",
3557 NULL, NULL, NULL
3558 },
3559
3560 {
3561 {"primary_conninfo", PGC_POSTMASTER, REPLICATION_STANDBY,
3562 gettext_noop("Sets the connection string to be used to connect to the sending server."),
3563 NULL,
3564 GUC_SUPERUSER_ONLY
3565 },
3566 &PrimaryConnInfo,
3567 "",
3568 NULL, NULL, NULL
3569 },
3570
3571 {
3572 {"primary_slot_name", PGC_POSTMASTER, REPLICATION_STANDBY,
3573 gettext_noop("Sets the name of the replication slot to use on the sending server."),
3574 NULL
3575 },
3576 &PrimarySlotName,
3577 "",
3578 check_primary_slot_name, NULL, NULL
3579 },
3580
3581 {
3582 {"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
3583 gettext_noop("Sets the client's character set encoding."),
3584 NULL,
3585 GUC_IS_NAME | GUC_REPORT
3586 },
3587 &client_encoding_string,
3588 "SQL_ASCII",
3589 check_client_encoding, assign_client_encoding, NULL
3590 },
3591
3592 {
3593 {"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
3594 gettext_noop("Controls information prefixed to each log line."),
3595 gettext_noop("If blank, no prefix is used.")
3596 },
3597 &Log_line_prefix,
3598 "%m [%p] ",
3599 NULL, NULL, NULL
3600 },
3601
3602 {
3603 {"log_timezone", PGC_SIGHUP, LOGGING_WHAT,
3604 gettext_noop("Sets the time zone to use in log messages."),
3605 NULL
3606 },
3607 &log_timezone_string,
3608 "GMT",
3609 check_log_timezone, assign_log_timezone, show_log_timezone
3610 },
3611
3612 {
3613 {"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
3614 gettext_noop("Sets the display format for date and time values."),
3615 gettext_noop("Also controls interpretation of ambiguous "
3616 "date inputs."),
3617 GUC_LIST_INPUT | GUC_REPORT
3618 },
3619 &datestyle_string,
3620 "ISO, MDY",
3621 check_datestyle, assign_datestyle, NULL
3622 },
3623
3624 {
3625 {"default_table_access_method", PGC_USERSET, CLIENT_CONN_STATEMENT,
3626 gettext_noop("Sets the default table access method for new tables."),
3627 NULL,
3628 GUC_IS_NAME
3629 },
3630 &default_table_access_method,
3631 DEFAULT_TABLE_ACCESS_METHOD,
3632 check_default_table_access_method, NULL, NULL
3633 },
3634
3635 {
3636 {"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT,
3637 gettext_noop("Sets the default tablespace to create tables and indexes in."),
3638 gettext_noop("An empty string selects the database's default tablespace."),
3639 GUC_IS_NAME
3640 },
3641 &default_tablespace,
3642 "",
3643 check_default_tablespace, NULL, NULL
3644 },
3645
3646 {
3647 {"temp_tablespaces", PGC_USERSET, CLIENT_CONN_STATEMENT,
3648 gettext_noop("Sets the tablespace(s) to use for temporary tables and sort files."),
3649 NULL,
3650 GUC_LIST_INPUT | GUC_LIST_QUOTE
3651 },
3652 &temp_tablespaces,
3653 "",
3654 check_temp_tablespaces, assign_temp_tablespaces, NULL
3655 },
3656
3657 {
3658 {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
3659 gettext_noop("Sets the path for dynamically loadable modules."),
3660 gettext_noop("If a dynamically loadable module needs to be opened and "
3661 "the specified name does not have a directory component (i.e., the "
3662 "name does not contain a slash), the system will search this path for "
3663 "the specified file."),
3664 GUC_SUPERUSER_ONLY
3665 },
3666 &Dynamic_library_path,
3667 "$libdir",
3668 NULL, NULL, NULL
3669 },
3670
3671 {
3672 {"krb_server_keyfile", PGC_SIGHUP, CONN_AUTH_AUTH,
3673 gettext_noop("Sets the location of the Kerberos server key file."),
3674 NULL,
3675 GUC_SUPERUSER_ONLY
3676 },
3677 &pg_krb_server_keyfile,
3678 PG_KRB_SRVTAB,
3679 NULL, NULL, NULL
3680 },
3681
3682 {
3683 {"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
3684 gettext_noop("Sets the Bonjour service name."),
3685 NULL
3686 },
3687 &bonjour_name,
3688 "",
3689 NULL, NULL, NULL
3690 },
3691
3692 /* See main.c about why defaults for LC_foo are not all alike */
3693
3694 {
3695 {"lc_collate", PGC_INTERNAL, CLIENT_CONN_LOCALE,
3696 gettext_noop("Shows the collation order locale."),
3697 NULL,
3698 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
3699 },
3700 &locale_collate,
3701 "C",
3702 NULL, NULL, NULL
3703 },
3704
3705 {
3706 {"lc_ctype", PGC_INTERNAL, CLIENT_CONN_LOCALE,
3707 gettext_noop("Shows the character classification and case conversion locale."),
3708 NULL,
3709 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
3710 },
3711 &locale_ctype,
3712 "C",
3713 NULL, NULL, NULL
3714 },
3715
3716 {
3717 {"lc_messages", PGC_SUSET, CLIENT_CONN_LOCALE,
3718 gettext_noop("Sets the language in which messages are displayed."),
3719 NULL
3720 },
3721 &locale_messages,
3722 "",
3723 check_locale_messages, assign_locale_messages, NULL
3724 },
3725
3726 {
3727 {"lc_monetary", PGC_USERSET, CLIENT_CONN_LOCALE,
3728 gettext_noop("Sets the locale for formatting monetary amounts."),
3729 NULL
3730 },
3731 &locale_monetary,
3732 "C",
3733 check_locale_monetary, assign_locale_monetary, NULL
3734 },
3735
3736 {
3737 {"lc_numeric", PGC_USERSET, CLIENT_CONN_LOCALE,
3738 gettext_noop("Sets the locale for formatting numbers."),
3739 NULL
3740 },
3741 &locale_numeric,
3742 "C",
3743 check_locale_numeric, assign_locale_numeric, NULL
3744 },
3745
3746 {
3747 {"lc_time", PGC_USERSET, CLIENT_CONN_LOCALE,
3748 gettext_noop("Sets the locale for formatting date and time values."),
3749 NULL
3750 },
3751 &locale_time,
3752 "C",
3753 check_locale_time, assign_locale_time, NULL
3754 },
3755
3756 {
3757 {"session_preload_libraries", PGC_SUSET, CLIENT_CONN_PRELOAD,
3758 gettext_noop("Lists shared libraries to preload into each backend."),
3759 NULL,
3760 GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
3761 },
3762 &session_preload_libraries_string,
3763 "",
3764 NULL, NULL, NULL
3765 },
3766
3767 {
3768 {"shared_preload_libraries", PGC_POSTMASTER, CLIENT_CONN_PRELOAD,
3769 gettext_noop("Lists shared libraries to preload into server."),
3770 NULL,
3771 GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
3772 },
3773 &shared_preload_libraries_string,
3774 "",
3775 NULL, NULL, NULL
3776 },
3777
3778 {
3779 {"local_preload_libraries", PGC_USERSET, CLIENT_CONN_PRELOAD,
3780 gettext_noop("Lists unprivileged shared libraries to preload into each backend."),
3781 NULL,
3782 GUC_LIST_INPUT | GUC_LIST_QUOTE
3783 },
3784 &local_preload_libraries_string,
3785 "",
3786 NULL, NULL, NULL
3787 },
3788
3789 {
3790 {"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT,
3791 gettext_noop("Sets the schema search order for names that are not schema-qualified."),
3792 NULL,
3793 GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_EXPLAIN
3794 },
3795 &namespace_search_path,
3796 "\"$user\", public",
3797 check_search_path, assign_search_path, NULL
3798 },
3799
3800 {
3801 /* Can't be set in postgresql.conf */
3802 {"server_encoding", PGC_INTERNAL, CLIENT_CONN_LOCALE,
3803 gettext_noop("Sets the server (database) character set encoding."),
3804 NULL,
3805 GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
3806 },
3807 &server_encoding_string,
3808 "SQL_ASCII",
3809 NULL, NULL, NULL
3810 },
3811
3812 {
3813 /* Can't be set in postgresql.conf */
3814 {"server_version", PGC_INTERNAL, PRESET_OPTIONS,
3815 gettext_noop("Shows the server version."),
3816 NULL,
3817 GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
3818 },
3819 &server_version_string,
3820 PG_VERSION,
3821 NULL, NULL, NULL
3822 },
3823
3824 {
3825 /* Not for general use --- used by SET ROLE */
3826 {"role", PGC_USERSET, UNGROUPED,
3827 gettext_noop("Sets the current role."),
3828 NULL,
3829 GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
3830 },
3831 &role_string,
3832 "none",
3833 check_role, assign_role, show_role
3834 },
3835
3836 {
3837 /* Not for general use --- used by SET SESSION AUTHORIZATION */
3838 {"session_authorization", PGC_USERSET, UNGROUPED,
3839 gettext_noop("Sets the session user name."),
3840 NULL,
3841 GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
3842 },
3843 &session_authorization_string,
3844 NULL,
3845 check_session_authorization, assign_session_authorization, NULL
3846 },
3847
3848 {
3849 {"log_destination", PGC_SIGHUP, LOGGING_WHERE,
3850 gettext_noop("Sets the destination for server log output."),
3851 gettext_noop("Valid values are combinations of \"stderr\", "
3852 "\"syslog\", \"csvlog\", and \"eventlog\", "
3853 "depending on the platform."),
3854 GUC_LIST_INPUT
3855 },
3856 &Log_destination_string,
3857 "stderr",
3858 check_log_destination, assign_log_destination, NULL
3859 },
3860 {
3861 {"log_directory", PGC_SIGHUP, LOGGING_WHERE,
3862 gettext_noop("Sets the destination directory for log files."),
3863 gettext_noop("Can be specified as relative to the data directory "
3864 "or as absolute path."),
3865 GUC_SUPERUSER_ONLY
3866 },
3867 &Log_directory,
3868 "log",
3869 check_canonical_path, NULL, NULL
3870 },
3871 {
3872 {"log_filename", PGC_SIGHUP, LOGGING_WHERE,
3873 gettext_noop("Sets the file name pattern for log files."),
3874 NULL,
3875 GUC_SUPERUSER_ONLY
3876 },
3877 &Log_filename,
3878 "postgresql-%Y-%m-%d_%H%M%S.log",
3879 NULL, NULL, NULL
3880 },
3881
3882 {
3883 {"syslog_ident", PGC_SIGHUP, LOGGING_WHERE,
3884 gettext_noop("Sets the program name used to identify PostgreSQL "
3885 "messages in syslog."),
3886 NULL
3887 },
3888 &syslog_ident_str,
3889 "postgres",
3890 NULL, assign_syslog_ident, NULL
3891 },
3892
3893 {
3894 {"event_source", PGC_POSTMASTER, LOGGING_WHERE,
3895 gettext_noop("Sets the application name used to identify "
3896 "PostgreSQL messages in the event log."),
3897 NULL
3898 },
3899 &event_source,
3900 DEFAULT_EVENT_SOURCE,
3901 NULL, NULL, NULL
3902 },
3903
3904 {
3905 {"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
3906 gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
3907 NULL,
3908 GUC_REPORT
3909 },
3910 &timezone_string,
3911 "GMT",
3912 check_timezone, assign_timezone, show_timezone
3913 },
3914 {
3915 {"timezone_abbreviations", PGC_USERSET, CLIENT_CONN_LOCALE,
3916 gettext_noop("Selects a file of time zone abbreviations."),
3917 NULL
3918 },
3919 &timezone_abbreviations_string,
3920 NULL,
3921 check_timezone_abbreviations, assign_timezone_abbreviations, NULL
3922 },
3923
3924 {
3925 {"unix_socket_group", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
3926 gettext_noop("Sets the owning group of the Unix-domain socket."),
3927 gettext_noop("The owning user of the socket is always the user "
3928 "that starts the server.")
3929 },
3930 &Unix_socket_group,
3931 "",
3932 NULL, NULL, NULL
3933 },
3934
3935 {
3936 {"unix_socket_directories", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
3937 gettext_noop("Sets the directories where Unix-domain sockets will be created."),
3938 NULL,
3939 GUC_SUPERUSER_ONLY
3940 },
3941 &Unix_socket_directories,
3942#ifdef HAVE_UNIX_SOCKETS
3943 DEFAULT_PGSOCKET_DIR,
3944#else
3945 "",
3946#endif
3947 NULL, NULL, NULL
3948 },
3949
3950 {
3951 {"listen_addresses", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
3952 gettext_noop("Sets the host name or IP address(es) to listen to."),
3953 NULL,
3954 GUC_LIST_INPUT
3955 },
3956 &ListenAddresses,
3957 "localhost",
3958 NULL, NULL, NULL
3959 },
3960
3961 {
3962 /*
3963 * Can't be set by ALTER SYSTEM as it can lead to recursive definition
3964 * of data_directory.
3965 */
3966 {"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
3967 gettext_noop("Sets the server's data directory."),
3968 NULL,
3969 GUC_SUPERUSER_ONLY | GUC_DISALLOW_IN_AUTO_FILE
3970 },
3971 &data_directory,
3972 NULL,
3973 NULL, NULL, NULL
3974 },
3975
3976 {
3977 {"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
3978 gettext_noop("Sets the server's main configuration file."),
3979 NULL,
3980 GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
3981 },
3982 &ConfigFileName,
3983 NULL,
3984 NULL, NULL, NULL
3985 },
3986
3987 {
3988 {"hba_file", PGC_POSTMASTER, FILE_LOCATIONS,
3989 gettext_noop("Sets the server's \"hba\" configuration file."),
3990 NULL,
3991 GUC_SUPERUSER_ONLY
3992 },
3993 &HbaFileName,
3994 NULL,
3995 NULL, NULL, NULL
3996 },
3997
3998 {
3999 {"ident_file", PGC_POSTMASTER, FILE_LOCATIONS,
4000 gettext_noop("Sets the server's \"ident\" configuration file."),
4001 NULL,
4002 GUC_SUPERUSER_ONLY
4003 },
4004 &IdentFileName,
4005 NULL,
4006 NULL, NULL, NULL
4007 },
4008
4009 {
4010 {"external_pid_file", PGC_POSTMASTER, FILE_LOCATIONS,
4011 gettext_noop("Writes the postmaster PID to the specified file."),
4012 NULL,
4013 GUC_SUPERUSER_ONLY
4014 },
4015 &external_pid_file,
4016 NULL,
4017 check_canonical_path, NULL, NULL
4018 },
4019
4020 {
4021 {"ssl_library", PGC_INTERNAL, PRESET_OPTIONS,
4022 gettext_noop("Name of the SSL library."),
4023 NULL,
4024 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
4025 },
4026 &ssl_library,
4027#ifdef USE_SSL
4028 "OpenSSL",
4029#else
4030 "",
4031#endif
4032 NULL, NULL, NULL
4033 },
4034
4035 {
4036 {"ssl_cert_file", PGC_SIGHUP, CONN_AUTH_SSL,
4037 gettext_noop("Location of the SSL server certificate file."),
4038 NULL
4039 },
4040 &ssl_cert_file,
4041 "server.crt",
4042 NULL, NULL, NULL
4043 },
4044
4045 {
4046 {"ssl_key_file", PGC_SIGHUP, CONN_AUTH_SSL,
4047 gettext_noop("Location of the SSL server private key file."),
4048 NULL
4049 },
4050 &ssl_key_file,
4051 "server.key",
4052 NULL, NULL, NULL
4053 },
4054
4055 {
4056 {"ssl_ca_file", PGC_SIGHUP, CONN_AUTH_SSL,
4057 gettext_noop("Location of the SSL certificate authority file."),
4058 NULL
4059 },
4060 &ssl_ca_file,
4061 "",
4062 NULL, NULL, NULL
4063 },
4064
4065 {
4066 {"ssl_crl_file", PGC_SIGHUP, CONN_AUTH_SSL,
4067 gettext_noop("Location of the SSL certificate revocation list file."),
4068 NULL
4069 },
4070 &ssl_crl_file,
4071 "",
4072 NULL, NULL, NULL
4073 },
4074
4075 {
4076 {"stats_temp_directory", PGC_SIGHUP, STATS_COLLECTOR,
4077 gettext_noop("Writes temporary statistics files to the specified directory."),
4078 NULL,
4079 GUC_SUPERUSER_ONLY
4080 },
4081 &pgstat_temp_directory,
4082 PG_STAT_TMP_DIR,
4083 check_canonical_path, assign_pgstat_temp_directory, NULL
4084 },
4085
4086 {
4087 {"synchronous_standby_names", PGC_SIGHUP, REPLICATION_MASTER,
4088 gettext_noop("Number of synchronous standbys and list of names of potential synchronous ones."),
4089 NULL,
4090 GUC_LIST_INPUT
4091 },
4092 &SyncRepStandbyNames,
4093 "",
4094 check_synchronous_standby_names, assign_synchronous_standby_names, NULL
4095 },
4096
4097 {
4098 {"default_text_search_config", PGC_USERSET, CLIENT_CONN_LOCALE,
4099 gettext_noop("Sets default text search configuration."),
4100 NULL
4101 },
4102 &TSCurrentConfig,
4103 "pg_catalog.simple",
4104 check_TSCurrentConfig, assign_TSCurrentConfig, NULL
4105 },
4106
4107 {
4108 {"ssl_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
4109 gettext_noop("Sets the list of allowed SSL ciphers."),
4110 NULL,
4111 GUC_SUPERUSER_ONLY
4112 },
4113 &SSLCipherSuites,
4114#ifdef USE_SSL
4115 "HIGH:MEDIUM:+3DES:!aNULL",
4116#else
4117 "none",
4118#endif
4119 NULL, NULL, NULL
4120 },
4121
4122 {
4123 {"ssl_ecdh_curve", PGC_SIGHUP, CONN_AUTH_SSL,
4124 gettext_noop("Sets the curve to use for ECDH."),
4125 NULL,
4126 GUC_SUPERUSER_ONLY
4127 },
4128 &SSLECDHCurve,
4129#ifdef USE_SSL
4130 "prime256v1",
4131#else
4132 "none",
4133#endif
4134 NULL, NULL, NULL
4135 },
4136
4137 {
4138 {"ssl_dh_params_file", PGC_SIGHUP, CONN_AUTH_SSL,
4139 gettext_noop("Location of the SSL DH parameters file."),
4140 NULL,
4141 GUC_SUPERUSER_ONLY
4142 },
4143 &ssl_dh_params_file,
4144 "",
4145 NULL, NULL, NULL
4146 },
4147
4148 {
4149 {"ssl_passphrase_command", PGC_SIGHUP, CONN_AUTH_SSL,
4150 gettext_noop("Command to obtain passphrases for SSL."),
4151 NULL
4152 },
4153 &ssl_passphrase_command,
4154 "",
4155 NULL, NULL, NULL
4156 },
4157
4158 {
4159 {"application_name", PGC_USERSET, LOGGING_WHAT,
4160 gettext_noop("Sets the application name to be reported in statistics and logs."),
4161 NULL,
4162 GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE
4163 },
4164 &application_name,
4165 "",
4166 check_application_name, assign_application_name, NULL
4167 },
4168
4169 {
4170 {"cluster_name", PGC_POSTMASTER, PROCESS_TITLE,
4171 gettext_noop("Sets the name of the cluster, which is included in the process title."),
4172 NULL,
4173 GUC_IS_NAME
4174 },
4175 &cluster_name,
4176 "",
4177 check_cluster_name, NULL, NULL
4178 },
4179
4180 {
4181 {"wal_consistency_checking", PGC_SUSET, DEVELOPER_OPTIONS,
4182 gettext_noop("Sets the WAL resource managers for which WAL consistency checks are done."),
4183 gettext_noop("Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay."),
4184 GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE
4185 },
4186 &wal_consistency_checking_string,
4187 "",
4188 check_wal_consistency_checking, assign_wal_consistency_checking, NULL
4189 },
4190
4191 {
4192 {"jit_provider", PGC_POSTMASTER, CLIENT_CONN_PRELOAD,
4193 gettext_noop("JIT provider to use."),
4194 NULL,
4195 GUC_SUPERUSER_ONLY
4196 },
4197 &jit_provider,
4198 "llvmjit",
4199 NULL, NULL, NULL
4200 },
4201
4202 /* End-of-list marker */
4203 {
4204 {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
4205 }
4206};
4207
4208
4209static struct config_enum ConfigureNamesEnum[] =
4210{
4211 {
4212 {"backslash_quote", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
4213 gettext_noop("Sets whether \"\\'\" is allowed in string literals."),
4214 NULL
4215 },
4216 &backslash_quote,
4217 BACKSLASH_QUOTE_SAFE_ENCODING, backslash_quote_options,
4218 NULL, NULL, NULL
4219 },
4220
4221 {
4222 {"bytea_output", PGC_USERSET, CLIENT_CONN_STATEMENT,
4223 gettext_noop("Sets the output format for bytea."),
4224 NULL
4225 },
4226 &bytea_output,
4227 BYTEA_OUTPUT_HEX, bytea_output_options,
4228 NULL, NULL, NULL
4229 },
4230
4231 {
4232 {"client_min_messages", PGC_USERSET, CLIENT_CONN_STATEMENT,
4233 gettext_noop("Sets the message levels that are sent to the client."),
4234 gettext_noop("Each level includes all the levels that follow it. The later"
4235 " the level, the fewer messages are sent.")
4236 },
4237 &client_min_messages,
4238 NOTICE, client_message_level_options,
4239 NULL, NULL, NULL
4240 },
4241
4242 {
4243 {"constraint_exclusion", PGC_USERSET, QUERY_TUNING_OTHER,
4244 gettext_noop("Enables the planner to use constraints to optimize queries."),
4245 gettext_noop("Table scans will be skipped if their constraints"
4246 " guarantee that no rows match the query."),
4247 GUC_EXPLAIN
4248 },
4249 &constraint_exclusion,
4250 CONSTRAINT_EXCLUSION_PARTITION, constraint_exclusion_options,
4251 NULL, NULL, NULL
4252 },
4253
4254 {
4255 {"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
4256 gettext_noop("Sets the transaction isolation level of each new transaction."),
4257 NULL
4258 },
4259 &DefaultXactIsoLevel,
4260 XACT_READ_COMMITTED, isolation_level_options,
4261 NULL, NULL, NULL
4262 },
4263
4264 {
4265 {"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
4266 gettext_noop("Sets the current transaction's isolation level."),
4267 NULL,
4268 GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
4269 },
4270 &XactIsoLevel,
4271 XACT_READ_COMMITTED, isolation_level_options,
4272 check_XactIsoLevel, NULL, NULL
4273 },
4274
4275 {
4276 {"IntervalStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
4277 gettext_noop("Sets the display format for interval values."),
4278 NULL,
4279 GUC_REPORT
4280 },
4281 &IntervalStyle,
4282 INTSTYLE_POSTGRES, intervalstyle_options,
4283 NULL, NULL, NULL
4284 },
4285
4286 {
4287 {"log_error_verbosity", PGC_SUSET, LOGGING_WHAT,
4288 gettext_noop("Sets the verbosity of logged messages."),
4289 NULL
4290 },
4291 &Log_error_verbosity,
4292 PGERROR_DEFAULT, log_error_verbosity_options,
4293 NULL, NULL, NULL
4294 },
4295
4296 {
4297 {"log_min_messages", PGC_SUSET, LOGGING_WHEN,
4298 gettext_noop("Sets the message levels that are logged."),
4299 gettext_noop("Each level includes all the levels that follow it. The later"
4300 " the level, the fewer messages are sent.")
4301 },
4302 &log_min_messages,
4303 WARNING, server_message_level_options,
4304 NULL, NULL, NULL
4305 },
4306
4307 {
4308 {"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
4309 gettext_noop("Causes all statements generating error at or above this level to be logged."),
4310 gettext_noop("Each level includes all the levels that follow it. The later"
4311 " the level, the fewer messages are sent.")
4312 },
4313 &log_min_error_statement,
4314 ERROR, server_message_level_options,
4315 NULL, NULL, NULL
4316 },
4317
4318 {
4319 {"log_statement", PGC_SUSET, LOGGING_WHAT,
4320 gettext_noop("Sets the type of statements logged."),
4321 NULL
4322 },
4323 &log_statement,
4324 LOGSTMT_NONE, log_statement_options,
4325 NULL, NULL, NULL
4326 },
4327
4328 {
4329 {"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
4330 gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
4331 NULL
4332 },
4333 &syslog_facility,
4334#ifdef HAVE_SYSLOG
4335 LOG_LOCAL0,
4336#else
4337 0,
4338#endif
4339 syslog_facility_options,
4340 NULL, assign_syslog_facility, NULL
4341 },
4342
4343 {
4344 {"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
4345 gettext_noop("Sets the session's behavior for triggers and rewrite rules."),
4346 NULL
4347 },
4348 &SessionReplicationRole,
4349 SESSION_REPLICATION_ROLE_ORIGIN, session_replication_role_options,
4350 NULL, assign_session_replication_role, NULL
4351 },
4352
4353 {
4354 {"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
4355 gettext_noop("Sets the current transaction's synchronization level."),
4356 NULL
4357 },
4358 &synchronous_commit,
4359 SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
4360 NULL, assign_synchronous_commit, NULL
4361 },
4362
4363 {
4364 {"archive_mode", PGC_POSTMASTER, WAL_ARCHIVING,
4365 gettext_noop("Allows archiving of WAL files using archive_command."),
4366 NULL
4367 },
4368 &XLogArchiveMode,
4369 ARCHIVE_MODE_OFF, archive_mode_options,
4370 NULL, NULL, NULL
4371 },
4372
4373 {
4374 {"recovery_target_action", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
4375 gettext_noop("Sets the action to perform upon reaching the recovery target."),
4376 NULL
4377 },
4378 &recoveryTargetAction,
4379 RECOVERY_TARGET_ACTION_PAUSE, recovery_target_action_options,
4380 NULL, NULL, NULL
4381 },
4382
4383 {
4384 {"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS,
4385 gettext_noop("Enables logging of recovery-related debugging information."),
4386 gettext_noop("Each level includes all the levels that follow it. The later"
4387 " the level, the fewer messages are sent.")
4388 },
4389 &trace_recovery_messages,
4390
4391 /*
4392 * client_message_level_options allows too many values, really, but
4393 * it's not worth having a separate options array for this.
4394 */
4395 LOG, client_message_level_options,
4396 NULL, NULL, NULL
4397 },
4398
4399 {
4400 {"track_functions", PGC_SUSET, STATS_COLLECTOR,
4401 gettext_noop("Collects function-level statistics on database activity."),
4402 NULL
4403 },
4404 &pgstat_track_functions,
4405 TRACK_FUNC_OFF, track_function_options,
4406 NULL, NULL, NULL
4407 },
4408
4409 {
4410 {"wal_level", PGC_POSTMASTER, WAL_SETTINGS,
4411 gettext_noop("Set the level of information written to the WAL."),
4412 NULL
4413 },
4414 &wal_level,
4415 WAL_LEVEL_REPLICA, wal_level_options,
4416 NULL, NULL, NULL
4417 },
4418
4419 {
4420 {"dynamic_shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
4421 gettext_noop("Selects the dynamic shared memory implementation used."),
4422 NULL
4423 },
4424 &dynamic_shared_memory_type,
4425 DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE, dynamic_shared_memory_options,
4426 NULL, NULL, NULL
4427 },
4428
4429 {
4430 {"shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
4431 gettext_noop("Selects the shared memory implementation used for the main shared memory region."),
4432 NULL
4433 },
4434 &shared_memory_type,
4435 DEFAULT_SHARED_MEMORY_TYPE, shared_memory_options,
4436 NULL, NULL, NULL
4437 },
4438
4439 {
4440 {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
4441 gettext_noop("Selects the method used for forcing WAL updates to disk."),
4442 NULL
4443 },
4444 &sync_method,
4445 DEFAULT_SYNC_METHOD, sync_method_options,
4446 NULL, assign_xlog_sync_method, NULL
4447 },
4448
4449 {
4450 {"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
4451 gettext_noop("Sets how binary values are to be encoded in XML."),
4452 NULL
4453 },
4454 &xmlbinary,
4455 XMLBINARY_BASE64, xmlbinary_options,
4456 NULL, NULL, NULL
4457 },
4458
4459 {
4460 {"xmloption", PGC_USERSET, CLIENT_CONN_STATEMENT,
4461 gettext_noop("Sets whether XML data in implicit parsing and serialization "
4462 "operations is to be considered as documents or content fragments."),
4463 NULL
4464 },
4465 &xmloption,
4466 XMLOPTION_CONTENT, xmloption_options,
4467 NULL, NULL, NULL
4468 },
4469
4470 {
4471 {"huge_pages", PGC_POSTMASTER, RESOURCES_MEM,
4472 gettext_noop("Use of huge pages on Linux or Windows."),
4473 NULL
4474 },
4475 &huge_pages,
4476 HUGE_PAGES_TRY, huge_pages_options,
4477 NULL, NULL, NULL
4478 },
4479
4480 {
4481 {"force_parallel_mode", PGC_USERSET, QUERY_TUNING_OTHER,
4482 gettext_noop("Forces use of parallel query facilities."),
4483 gettext_noop("If possible, run query using a parallel worker and with parallel restrictions."),
4484 GUC_EXPLAIN
4485 },
4486 &force_parallel_mode,
4487 FORCE_PARALLEL_OFF, force_parallel_mode_options,
4488 NULL, NULL, NULL
4489 },
4490
4491 {
4492 {"password_encryption", PGC_USERSET, CONN_AUTH_AUTH,
4493 gettext_noop("Encrypt passwords."),
4494 gettext_noop("When a password is specified in CREATE USER or "
4495 "ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
4496 "this parameter determines whether the password is to be encrypted.")
4497 },
4498 &Password_encryption,
4499 PASSWORD_TYPE_MD5, password_encryption_options,
4500 NULL, NULL, NULL
4501 },
4502
4503 {
4504 {"plan_cache_mode", PGC_USERSET, QUERY_TUNING_OTHER,
4505 gettext_noop("Controls the planner's selection of custom or generic plan."),
4506 gettext_noop("Prepared statements can have custom and generic plans, and the planner "
4507 "will attempt to choose which is better. This can be set to override "
4508 "the default behavior."),
4509 GUC_EXPLAIN
4510 },
4511 &plan_cache_mode,
4512 PLAN_CACHE_MODE_AUTO, plan_cache_mode_options,
4513 NULL, NULL, NULL
4514 },
4515
4516 {
4517 {"ssl_min_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
4518 gettext_noop("Sets the minimum SSL/TLS protocol version to use."),
4519 NULL,
4520 GUC_SUPERUSER_ONLY
4521 },
4522 &ssl_min_protocol_version,
4523 PG_TLS1_VERSION,
4524 ssl_protocol_versions_info + 1, /* don't allow PG_TLS_ANY */
4525 NULL, NULL, NULL
4526 },
4527
4528 {
4529 {"ssl_max_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
4530 gettext_noop("Sets the maximum SSL/TLS protocol version to use."),
4531 NULL,
4532 GUC_SUPERUSER_ONLY
4533 },
4534 &ssl_max_protocol_version,
4535 PG_TLS_ANY,
4536 ssl_protocol_versions_info,
4537 NULL, NULL, NULL
4538 },
4539
4540 /* End-of-list marker */
4541 {
4542 {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
4543 }
4544};
4545
4546/******** end of options list ********/
4547
4548
4549/*
4550 * To allow continued support of obsolete names for GUC variables, we apply
4551 * the following mappings to any unrecognized name. Note that an old name
4552 * should be mapped to a new one only if the new variable has very similar
4553 * semantics to the old.
4554 */
4555static const char *const map_old_guc_names[] = {
4556 "sort_mem", "work_mem",
4557 "vacuum_mem", "maintenance_work_mem",
4558 NULL
4559};
4560
4561
4562/*
4563 * Actual lookup of variables is done through this single, sorted array.
4564 */
4565static struct config_generic **guc_variables;
4566
4567/* Current number of variables contained in the vector */
4568static int num_guc_variables;
4569
4570/* Current number of variables marked with GUC_EXPLAIN */
4571static int num_guc_explain_variables;
4572
4573/* Vector capacity */
4574static int size_guc_variables;
4575
4576
4577static bool guc_dirty; /* true if need to do commit/abort work */
4578
4579static bool reporting_enabled; /* true to enable GUC_REPORT */
4580
4581static int GUCNestLevel = 0; /* 1 when in main transaction */
4582
4583
4584static int guc_var_compare(const void *a, const void *b);
4585static int guc_name_compare(const char *namea, const char *nameb);
4586static void InitializeGUCOptionsFromEnvironment(void);
4587static void InitializeOneGUCOption(struct config_generic *gconf);
4588static void push_old_value(struct config_generic *gconf, GucAction action);
4589static void ReportGUCOption(struct config_generic *record);
4590static void reapply_stacked_values(struct config_generic *variable,
4591 struct config_string *pHolder,
4592 GucStack *stack,
4593 const char *curvalue,
4594 GucContext curscontext, GucSource cursource);
4595static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
4596static void ShowAllGUCConfig(DestReceiver *dest);
4597static char *_ShowOption(struct config_generic *record, bool use_units);
4598static bool validate_option_array_item(const char *name, const char *value,
4599 bool skipIfNoPermissions);
4600static void write_auto_conf_file(int fd, const char *filename, ConfigVariable *head_p);
4601static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
4602 const char *name, const char *value);
4603
4604
4605/*
4606 * Some infrastructure for checking malloc/strdup/realloc calls
4607 */
4608static void *
4609guc_malloc(int elevel, size_t size)
4610{
4611 void *data;
4612
4613 /* Avoid unportable behavior of malloc(0) */
4614 if (size == 0)
4615 size = 1;
4616 data = malloc(size);
4617 if (data == NULL)
4618 ereport(elevel,
4619 (errcode(ERRCODE_OUT_OF_MEMORY),
4620 errmsg("out of memory")));
4621 return data;
4622}
4623
4624static void *
4625guc_realloc(int elevel, void *old, size_t size)
4626{
4627 void *data;
4628
4629 /* Avoid unportable behavior of realloc(NULL, 0) */
4630 if (old == NULL && size == 0)
4631 size = 1;
4632 data = realloc(old, size);
4633 if (data == NULL)
4634 ereport(elevel,
4635 (errcode(ERRCODE_OUT_OF_MEMORY),
4636 errmsg("out of memory")));
4637 return data;
4638}
4639
4640static char *
4641guc_strdup(int elevel, const char *src)
4642{
4643 char *data;
4644
4645 data = strdup(src);
4646 if (data == NULL)
4647 ereport(elevel,
4648 (errcode(ERRCODE_OUT_OF_MEMORY),
4649 errmsg("out of memory")));
4650 return data;
4651}
4652
4653
4654/*
4655 * Detect whether strval is referenced anywhere in a GUC string item
4656 */
4657static bool
4658string_field_used(struct config_string *conf, char *strval)
4659{
4660 GucStack *stack;
4661
4662 if (strval == *(conf->variable) ||
4663 strval == conf->reset_val ||
4664 strval == conf->boot_val)
4665 return true;
4666 for (stack = conf->gen.stack; stack; stack = stack->prev)
4667 {
4668 if (strval == stack->prior.val.stringval ||
4669 strval == stack->masked.val.stringval)
4670 return true;
4671 }
4672 return false;
4673}
4674
4675/*
4676 * Support for assigning to a field of a string GUC item. Free the prior
4677 * value if it's not referenced anywhere else in the item (including stacked
4678 * states).
4679 */
4680static void
4681set_string_field(struct config_string *conf, char **field, char *newval)
4682{
4683 char *oldval = *field;
4684
4685 /* Do the assignment */
4686 *field = newval;
4687
4688 /* Free old value if it's not NULL and isn't referenced anymore */
4689 if (oldval && !string_field_used(conf, oldval))
4690 free(oldval);
4691}
4692
4693/*
4694 * Detect whether an "extra" struct is referenced anywhere in a GUC item
4695 */
4696static bool
4697extra_field_used(struct config_generic *gconf, void *extra)
4698{
4699 GucStack *stack;
4700
4701 if (extra == gconf->extra)
4702 return true;
4703 switch (gconf->vartype)
4704 {
4705 case PGC_BOOL:
4706 if (extra == ((struct config_bool *) gconf)->reset_extra)
4707 return true;
4708 break;
4709 case PGC_INT:
4710 if (extra == ((struct config_int *) gconf)->reset_extra)
4711 return true;
4712 break;
4713 case PGC_REAL:
4714 if (extra == ((struct config_real *) gconf)->reset_extra)
4715 return true;
4716 break;
4717 case PGC_STRING:
4718 if (extra == ((struct config_string *) gconf)->reset_extra)
4719 return true;
4720 break;
4721 case PGC_ENUM:
4722 if (extra == ((struct config_enum *) gconf)->reset_extra)
4723 return true;
4724 break;
4725 }
4726 for (stack = gconf->stack; stack; stack = stack->prev)
4727 {
4728 if (extra == stack->prior.extra ||
4729 extra == stack->masked.extra)
4730 return true;
4731 }
4732
4733 return false;
4734}
4735
4736/*
4737 * Support for assigning to an "extra" field of a GUC item. Free the prior
4738 * value if it's not referenced anywhere else in the item (including stacked
4739 * states).
4740 */
4741static void
4742set_extra_field(struct config_generic *gconf, void **field, void *newval)
4743{
4744 void *oldval = *field;
4745
4746 /* Do the assignment */
4747 *field = newval;
4748
4749 /* Free old value if it's not NULL and isn't referenced anymore */
4750 if (oldval && !extra_field_used(gconf, oldval))
4751 free(oldval);
4752}
4753
4754/*
4755 * Support for copying a variable's active value into a stack entry.
4756 * The "extra" field associated with the active value is copied, too.
4757 *
4758 * NB: be sure stringval and extra fields of a new stack entry are
4759 * initialized to NULL before this is used, else we'll try to free() them.
4760 */
4761static void
4762set_stack_value(struct config_generic *gconf, config_var_value *val)
4763{
4764 switch (gconf->vartype)
4765 {
4766 case PGC_BOOL:
4767 val->val.boolval =
4768 *((struct config_bool *) gconf)->variable;
4769 break;
4770 case PGC_INT:
4771 val->val.intval =
4772 *((struct config_int *) gconf)->variable;
4773 break;
4774 case PGC_REAL:
4775 val->val.realval =
4776 *((struct config_real *) gconf)->variable;
4777 break;
4778 case PGC_STRING:
4779 set_string_field((struct config_string *) gconf,
4780 &(val->val.stringval),
4781 *((struct config_string *) gconf)->variable);
4782 break;
4783 case PGC_ENUM:
4784 val->val.enumval =
4785 *((struct config_enum *) gconf)->variable;
4786 break;
4787 }
4788 set_extra_field(gconf, &(val->extra), gconf->extra);
4789}
4790
4791/*
4792 * Support for discarding a no-longer-needed value in a stack entry.
4793 * The "extra" field associated with the stack entry is cleared, too.
4794 */
4795static void
4796discard_stack_value(struct config_generic *gconf, config_var_value *val)
4797{
4798 switch (gconf->vartype)
4799 {
4800 case PGC_BOOL:
4801 case PGC_INT:
4802 case PGC_REAL:
4803 case PGC_ENUM:
4804 /* no need to do anything */
4805 break;
4806 case PGC_STRING:
4807 set_string_field((struct config_string *) gconf,
4808 &(val->val.stringval),
4809 NULL);
4810 break;
4811 }
4812 set_extra_field(gconf, &(val->extra), NULL);
4813}
4814
4815
4816/*
4817 * Fetch the sorted array pointer (exported for help_config.c's use ONLY)
4818 */
4819struct config_generic **
4820get_guc_variables(void)
4821{
4822 return guc_variables;
4823}
4824
4825
4826/*
4827 * Build the sorted array. This is split out so that it could be
4828 * re-executed after startup (e.g., we could allow loadable modules to
4829 * add vars, and then we'd need to re-sort).
4830 */
4831void
4832build_guc_variables(void)
4833{
4834 int size_vars;
4835 int num_vars = 0;
4836 int num_explain_vars = 0;
4837 struct config_generic **guc_vars;
4838 int i;
4839
4840 for (i = 0; ConfigureNamesBool[i].gen.name; i++)
4841 {
4842 struct config_bool *conf = &ConfigureNamesBool[i];
4843
4844 /* Rather than requiring vartype to be filled in by hand, do this: */
4845 conf->gen.vartype = PGC_BOOL;
4846 num_vars++;
4847
4848 if (conf->gen.flags & GUC_EXPLAIN)
4849 num_explain_vars++;
4850 }
4851
4852 for (i = 0; ConfigureNamesInt[i].gen.name; i++)
4853 {
4854 struct config_int *conf = &ConfigureNamesInt[i];
4855
4856 conf->gen.vartype = PGC_INT;
4857 num_vars++;
4858
4859 if (conf->gen.flags & GUC_EXPLAIN)
4860 num_explain_vars++;
4861 }
4862
4863 for (i = 0; ConfigureNamesReal[i].gen.name; i++)
4864 {
4865 struct config_real *conf = &ConfigureNamesReal[i];
4866
4867 conf->gen.vartype = PGC_REAL;
4868 num_vars++;
4869
4870 if (conf->gen.flags & GUC_EXPLAIN)
4871 num_explain_vars++;
4872 }
4873
4874 for (i = 0; ConfigureNamesString[i].gen.name; i++)
4875 {
4876 struct config_string *conf = &ConfigureNamesString[i];
4877
4878 conf->gen.vartype = PGC_STRING;
4879 num_vars++;
4880
4881 if (conf->gen.flags & GUC_EXPLAIN)
4882 num_explain_vars++;
4883 }
4884
4885 for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
4886 {
4887 struct config_enum *conf = &ConfigureNamesEnum[i];
4888
4889 conf->gen.vartype = PGC_ENUM;
4890 num_vars++;
4891
4892 if (conf->gen.flags & GUC_EXPLAIN)
4893 num_explain_vars++;
4894 }
4895
4896 /*
4897 * Create table with 20% slack
4898 */
4899 size_vars = num_vars + num_vars / 4;
4900
4901 guc_vars = (struct config_generic **)
4902 guc_malloc(FATAL, size_vars * sizeof(struct config_generic *));
4903
4904 num_vars = 0;
4905
4906 for (i = 0; ConfigureNamesBool[i].gen.name; i++)
4907 guc_vars[num_vars++] = &ConfigureNamesBool[i].gen;
4908
4909 for (i = 0; ConfigureNamesInt[i].gen.name; i++)
4910 guc_vars[num_vars++] = &ConfigureNamesInt[i].gen;
4911
4912 for (i = 0; ConfigureNamesReal[i].gen.name; i++)
4913 guc_vars[num_vars++] = &ConfigureNamesReal[i].gen;
4914
4915 for (i = 0; ConfigureNamesString[i].gen.name; i++)
4916 guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
4917
4918 for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
4919 guc_vars[num_vars++] = &ConfigureNamesEnum[i].gen;
4920
4921 if (guc_variables)
4922 free(guc_variables);
4923 guc_variables = guc_vars;
4924 num_guc_variables = num_vars;
4925 num_guc_explain_variables = num_explain_vars;
4926 size_guc_variables = size_vars;
4927 qsort((void *) guc_variables, num_guc_variables,
4928 sizeof(struct config_generic *), guc_var_compare);
4929}
4930
4931/*
4932 * Add a new GUC variable to the list of known variables. The
4933 * list is expanded if needed.
4934 */
4935static bool
4936add_guc_variable(struct config_generic *var, int elevel)
4937{
4938 if (num_guc_variables + 1 >= size_guc_variables)
4939 {
4940 /*
4941 * Increase the vector by 25%
4942 */
4943 int size_vars = size_guc_variables + size_guc_variables / 4;
4944 struct config_generic **guc_vars;
4945
4946 if (size_vars == 0)
4947 {
4948 size_vars = 100;
4949 guc_vars = (struct config_generic **)
4950 guc_malloc(elevel, size_vars * sizeof(struct config_generic *));
4951 }
4952 else
4953 {
4954 guc_vars = (struct config_generic **)
4955 guc_realloc(elevel, guc_variables, size_vars * sizeof(struct config_generic *));
4956 }
4957
4958 if (guc_vars == NULL)
4959 return false; /* out of memory */
4960
4961 guc_variables = guc_vars;
4962 size_guc_variables = size_vars;
4963 }
4964 guc_variables[num_guc_variables++] = var;
4965 qsort((void *) guc_variables, num_guc_variables,
4966 sizeof(struct config_generic *), guc_var_compare);
4967 return true;
4968}
4969
4970/*
4971 * Create and add a placeholder variable for a custom variable name.
4972 */
4973static struct config_generic *
4974add_placeholder_variable(const char *name, int elevel)
4975{
4976 size_t sz = sizeof(struct config_string) + sizeof(char *);
4977 struct config_string *var;
4978 struct config_generic *gen;
4979
4980 var = (struct config_string *) guc_malloc(elevel, sz);
4981 if (var == NULL)
4982 return NULL;
4983 memset(var, 0, sz);
4984 gen = &var->gen;
4985
4986 gen->name = guc_strdup(elevel, name);
4987 if (gen->name == NULL)
4988 {
4989 free(var);
4990 return NULL;
4991 }
4992
4993 gen->context = PGC_USERSET;
4994 gen->group = CUSTOM_OPTIONS;
4995 gen->short_desc = "GUC placeholder variable";
4996 gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER;
4997 gen->vartype = PGC_STRING;
4998
4999 /*
5000 * The char* is allocated at the end of the struct since we have no
5001 * 'static' place to point to. Note that the current value, as well as
5002 * the boot and reset values, start out NULL.
5003 */
5004 var->variable = (char **) (var + 1);
5005
5006 if (!add_guc_variable((struct config_generic *) var, elevel))
5007 {
5008 free(unconstify(char *, gen->name));
5009 free(var);
5010 return NULL;
5011 }
5012
5013 return gen;
5014}
5015
5016/*
5017 * Look up option NAME. If it exists, return a pointer to its record,
5018 * else return NULL. If create_placeholders is true, we'll create a
5019 * placeholder record for a valid-looking custom variable name.
5020 */
5021static struct config_generic *
5022find_option(const char *name, bool create_placeholders, int elevel)
5023{
5024 const char **key = &name;
5025 struct config_generic **res;
5026 int i;
5027
5028 Assert(name);
5029
5030 /*
5031 * By equating const char ** with struct config_generic *, we are assuming
5032 * the name field is first in config_generic.
5033 */
5034 res = (struct config_generic **) bsearch((void *) &key,
5035 (void *) guc_variables,
5036 num_guc_variables,
5037 sizeof(struct config_generic *),
5038 guc_var_compare);
5039 if (res)
5040 return *res;
5041
5042 /*
5043 * See if the name is an obsolete name for a variable. We assume that the
5044 * set of supported old names is short enough that a brute-force search is
5045 * the best way.
5046 */
5047 for (i = 0; map_old_guc_names[i] != NULL; i += 2)
5048 {
5049 if (guc_name_compare(name, map_old_guc_names[i]) == 0)
5050 return find_option(map_old_guc_names[i + 1], false, elevel);
5051 }
5052
5053 if (create_placeholders)
5054 {
5055 /*
5056 * Check if the name is qualified, and if so, add a placeholder.
5057 */
5058 if (strchr(name, GUC_QUALIFIER_SEPARATOR) != NULL)
5059 return add_placeholder_variable(name, elevel);
5060 }
5061
5062 /* Unknown name */
5063 return NULL;
5064}
5065
5066
5067/*
5068 * comparator for qsorting and bsearching guc_variables array
5069 */
5070static int
5071guc_var_compare(const void *a, const void *b)
5072{
5073 const struct config_generic *confa = *(struct config_generic *const *) a;
5074 const struct config_generic *confb = *(struct config_generic *const *) b;
5075
5076 return guc_name_compare(confa->name, confb->name);
5077}
5078
5079/*
5080 * the bare comparison function for GUC names
5081 */
5082static int
5083guc_name_compare(const char *namea, const char *nameb)
5084{
5085 /*
5086 * The temptation to use strcasecmp() here must be resisted, because the
5087 * array ordering has to remain stable across setlocale() calls. So, build
5088 * our own with a simple ASCII-only downcasing.
5089 */
5090 while (*namea && *nameb)
5091 {
5092 char cha = *namea++;
5093 char chb = *nameb++;
5094
5095 if (cha >= 'A' && cha <= 'Z')
5096 cha += 'a' - 'A';
5097 if (chb >= 'A' && chb <= 'Z')
5098 chb += 'a' - 'A';
5099 if (cha != chb)
5100 return cha - chb;
5101 }
5102 if (*namea)
5103 return 1; /* a is longer */
5104 if (*nameb)
5105 return -1; /* b is longer */
5106 return 0;
5107}
5108
5109
5110/*
5111 * Initialize GUC options during program startup.
5112 *
5113 * Note that we cannot read the config file yet, since we have not yet
5114 * processed command-line switches.
5115 */
5116void
5117InitializeGUCOptions(void)
5118{
5119 int i;
5120
5121 /*
5122 * Before log_line_prefix could possibly receive a nonempty setting, make
5123 * sure that timezone processing is minimally alive (see elog.c).
5124 */
5125 pg_timezone_initialize();
5126
5127 /*
5128 * Build sorted array of all GUC variables.
5129 */
5130 build_guc_variables();
5131
5132 /*
5133 * Load all variables with their compiled-in defaults, and initialize
5134 * status fields as needed.
5135 */
5136 for (i = 0; i < num_guc_variables; i++)
5137 {
5138 InitializeOneGUCOption(guc_variables[i]);
5139 }
5140
5141 guc_dirty = false;
5142
5143 reporting_enabled = false;
5144
5145 /*
5146 * Prevent any attempt to override the transaction modes from
5147 * non-interactive sources.
5148 */
5149 SetConfigOption("transaction_isolation", "read committed",
5150 PGC_POSTMASTER, PGC_S_OVERRIDE);
5151 SetConfigOption("transaction_read_only", "no",
5152 PGC_POSTMASTER, PGC_S_OVERRIDE);
5153 SetConfigOption("transaction_deferrable", "no",
5154 PGC_POSTMASTER, PGC_S_OVERRIDE);
5155
5156 /*
5157 * For historical reasons, some GUC parameters can receive defaults from
5158 * environment variables. Process those settings.
5159 */
5160 InitializeGUCOptionsFromEnvironment();
5161}
5162
5163/*
5164 * Assign any GUC values that can come from the server's environment.
5165 *
5166 * This is called from InitializeGUCOptions, and also from ProcessConfigFile
5167 * to deal with the possibility that a setting has been removed from
5168 * postgresql.conf and should now get a value from the environment.
5169 * (The latter is a kludge that should probably go away someday; if so,
5170 * fold this back into InitializeGUCOptions.)
5171 */
5172static void
5173InitializeGUCOptionsFromEnvironment(void)
5174{
5175 char *env;
5176 long stack_rlimit;
5177
5178 env = getenv("PGPORT");
5179 if (env != NULL)
5180 SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
5181
5182 env = getenv("PGDATESTYLE");
5183 if (env != NULL)
5184 SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
5185
5186 env = getenv("PGCLIENTENCODING");
5187 if (env != NULL)
5188 SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
5189
5190 /*
5191 * rlimit isn't exactly an "environment variable", but it behaves about
5192 * the same. If we can identify the platform stack depth rlimit, increase
5193 * default stack depth setting up to whatever is safe (but at most 2MB).
5194 */
5195 stack_rlimit = get_stack_depth_rlimit();
5196 if (stack_rlimit > 0)
5197 {
5198 long new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;
5199
5200 if (new_limit > 100)
5201 {
5202 char limbuf[16];
5203
5204 new_limit = Min(new_limit, 2048);
5205 sprintf(limbuf, "%ld", new_limit);
5206 SetConfigOption("max_stack_depth", limbuf,
5207 PGC_POSTMASTER, PGC_S_ENV_VAR);
5208 }
5209 }
5210}
5211
5212/*
5213 * Initialize one GUC option variable to its compiled-in default.
5214 *
5215 * Note: the reason for calling check_hooks is not that we think the boot_val
5216 * might fail, but that the hooks might wish to compute an "extra" struct.
5217 */
5218static void
5219InitializeOneGUCOption(struct config_generic *gconf)
5220{
5221 gconf->status = 0;
5222 gconf->source = PGC_S_DEFAULT;
5223 gconf->reset_source = PGC_S_DEFAULT;
5224 gconf->scontext = PGC_INTERNAL;
5225 gconf->reset_scontext = PGC_INTERNAL;
5226 gconf->stack = NULL;
5227 gconf->extra = NULL;
5228 gconf->sourcefile = NULL;
5229 gconf->sourceline = 0;
5230
5231 switch (gconf->vartype)
5232 {
5233 case PGC_BOOL:
5234 {
5235 struct config_bool *conf = (struct config_bool *) gconf;
5236 bool newval = conf->boot_val;
5237 void *extra = NULL;
5238
5239 if (!call_bool_check_hook(conf, &newval, &extra,
5240 PGC_S_DEFAULT, LOG))
5241 elog(FATAL, "failed to initialize %s to %d",
5242 conf->gen.name, (int) newval);
5243 if (conf->assign_hook)
5244 conf->assign_hook(newval, extra);
5245 *conf->variable = conf->reset_val = newval;
5246 conf->gen.extra = conf->reset_extra = extra;
5247 break;
5248 }
5249 case PGC_INT:
5250 {
5251 struct config_int *conf = (struct config_int *) gconf;
5252 int newval = conf->boot_val;
5253 void *extra = NULL;
5254
5255 Assert(newval >= conf->min);
5256 Assert(newval <= conf->max);
5257 if (!call_int_check_hook(conf, &newval, &extra,
5258 PGC_S_DEFAULT, LOG))
5259 elog(FATAL, "failed to initialize %s to %d",
5260 conf->gen.name, newval);
5261 if (conf->assign_hook)
5262 conf->assign_hook(newval, extra);
5263 *conf->variable = conf->reset_val = newval;
5264 conf->gen.extra = conf->reset_extra = extra;
5265 break;
5266 }
5267 case PGC_REAL:
5268 {
5269 struct config_real *conf = (struct config_real *) gconf;
5270 double newval = conf->boot_val;
5271 void *extra = NULL;
5272
5273 Assert(newval >= conf->min);
5274 Assert(newval <= conf->max);
5275 if (!call_real_check_hook(conf, &newval, &extra,
5276 PGC_S_DEFAULT, LOG))
5277 elog(FATAL, "failed to initialize %s to %g",
5278 conf->gen.name, newval);
5279 if (conf->assign_hook)
5280 conf->assign_hook(newval, extra);
5281 *conf->variable = conf->reset_val = newval;
5282 conf->gen.extra = conf->reset_extra = extra;
5283 break;
5284 }
5285 case PGC_STRING:
5286 {
5287 struct config_string *conf = (struct config_string *) gconf;
5288 char *newval;
5289 void *extra = NULL;
5290
5291 /* non-NULL boot_val must always get strdup'd */
5292 if (conf->boot_val != NULL)
5293 newval = guc_strdup(FATAL, conf->boot_val);
5294 else
5295 newval = NULL;
5296
5297 if (!call_string_check_hook(conf, &newval, &extra,
5298 PGC_S_DEFAULT, LOG))
5299 elog(FATAL, "failed to initialize %s to \"%s\"",
5300 conf->gen.name, newval ? newval : "");
5301 if (conf->assign_hook)
5302 conf->assign_hook(newval, extra);
5303 *conf->variable = conf->reset_val = newval;
5304 conf->gen.extra = conf->reset_extra = extra;
5305 break;
5306 }
5307 case PGC_ENUM:
5308 {
5309 struct config_enum *conf = (struct config_enum *) gconf;
5310 int newval = conf->boot_val;
5311 void *extra = NULL;
5312
5313 if (!call_enum_check_hook(conf, &newval, &extra,
5314 PGC_S_DEFAULT, LOG))
5315 elog(FATAL, "failed to initialize %s to %d",
5316 conf->gen.name, newval);
5317 if (conf->assign_hook)
5318 conf->assign_hook(newval, extra);
5319 *conf->variable = conf->reset_val = newval;
5320 conf->gen.extra = conf->reset_extra = extra;
5321 break;
5322 }
5323 }
5324}
5325
5326
5327/*
5328 * Select the configuration files and data directory to be used, and
5329 * do the initial read of postgresql.conf.
5330 *
5331 * This is called after processing command-line switches.
5332 * userDoption is the -D switch value if any (NULL if unspecified).
5333 * progname is just for use in error messages.
5334 *
5335 * Returns true on success; on failure, prints a suitable error message
5336 * to stderr and returns false.
5337 */
5338bool
5339SelectConfigFiles(const char *userDoption, const char *progname)
5340{
5341 char *configdir;
5342 char *fname;
5343 struct stat stat_buf;
5344
5345 /* configdir is -D option, or $PGDATA if no -D */
5346 if (userDoption)
5347 configdir = make_absolute_path(userDoption);
5348 else
5349 configdir = make_absolute_path(getenv("PGDATA"));
5350
5351 if (configdir && stat(configdir, &stat_buf) != 0)
5352 {
5353 write_stderr("%s: could not access directory \"%s\": %s\n",
5354 progname,
5355 configdir,
5356 strerror(errno));
5357 if (errno == ENOENT)
5358 write_stderr("Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n");
5359 return false;
5360 }
5361
5362 /*
5363 * Find the configuration file: if config_file was specified on the
5364 * command line, use it, else use configdir/postgresql.conf. In any case
5365 * ensure the result is an absolute path, so that it will be interpreted
5366 * the same way by future backends.
5367 */
5368 if (ConfigFileName)
5369 fname = make_absolute_path(ConfigFileName);
5370 else if (configdir)
5371 {
5372 fname = guc_malloc(FATAL,
5373 strlen(configdir) + strlen(CONFIG_FILENAME) + 2);
5374 sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);
5375 }
5376 else
5377 {
5378 write_stderr("%s does not know where to find the server configuration file.\n"
5379 "You must specify the --config-file or -D invocation "
5380 "option or set the PGDATA environment variable.\n",
5381 progname);
5382 return false;
5383 }
5384
5385 /*
5386 * Set the ConfigFileName GUC variable to its final value, ensuring that
5387 * it can't be overridden later.
5388 */
5389 SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
5390 free(fname);
5391
5392 /*
5393 * Now read the config file for the first time.
5394 */
5395 if (stat(ConfigFileName, &stat_buf) != 0)
5396 {
5397 write_stderr("%s: could not access the server configuration file \"%s\": %s\n",
5398 progname, ConfigFileName, strerror(errno));
5399 free(configdir);
5400 return false;
5401 }
5402
5403 /*
5404 * Read the configuration file for the first time. This time only the
5405 * data_directory parameter is picked up to determine the data directory,
5406 * so that we can read the PG_AUTOCONF_FILENAME file next time.
5407 */
5408 ProcessConfigFile(PGC_POSTMASTER);
5409
5410 /*
5411 * If the data_directory GUC variable has been set, use that as DataDir;
5412 * otherwise use configdir if set; else punt.
5413 *
5414 * Note: SetDataDir will copy and absolute-ize its argument, so we don't
5415 * have to.
5416 */
5417 if (data_directory)
5418 SetDataDir(data_directory);
5419 else if (configdir)
5420 SetDataDir(configdir);
5421 else
5422 {
5423 write_stderr("%s does not know where to find the database system data.\n"
5424 "This can be specified as \"data_directory\" in \"%s\", "
5425 "or by the -D invocation option, or by the "
5426 "PGDATA environment variable.\n",
5427 progname, ConfigFileName);
5428 return false;
5429 }
5430
5431 /*
5432 * Reflect the final DataDir value back into the data_directory GUC var.
5433 * (If you are wondering why we don't just make them a single variable,
5434 * it's because the EXEC_BACKEND case needs DataDir to be transmitted to
5435 * child backends specially. XXX is that still true? Given that we now
5436 * chdir to DataDir, EXEC_BACKEND can read the config file without knowing
5437 * DataDir in advance.)
5438 */
5439 SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
5440
5441 /*
5442 * Now read the config file a second time, allowing any settings in the
5443 * PG_AUTOCONF_FILENAME file to take effect. (This is pretty ugly, but
5444 * since we have to determine the DataDir before we can find the autoconf
5445 * file, the alternatives seem worse.)
5446 */
5447 ProcessConfigFile(PGC_POSTMASTER);
5448
5449 /*
5450 * If timezone_abbreviations wasn't set in the configuration file, install
5451 * the default value. We do it this way because we can't safely install a
5452 * "real" value until my_exec_path is set, which may not have happened
5453 * when InitializeGUCOptions runs, so the bootstrap default value cannot
5454 * be the real desired default.
5455 */
5456 pg_timezone_abbrev_initialize();
5457
5458 /*
5459 * Figure out where pg_hba.conf is, and make sure the path is absolute.
5460 */
5461 if (HbaFileName)
5462 fname = make_absolute_path(HbaFileName);
5463 else if (configdir)
5464 {
5465 fname = guc_malloc(FATAL,
5466 strlen(configdir) + strlen(HBA_FILENAME) + 2);
5467 sprintf(fname, "%s/%s", configdir, HBA_FILENAME);
5468 }
5469 else
5470 {
5471 write_stderr("%s does not know where to find the \"hba\" configuration file.\n"
5472 "This can be specified as \"hba_file\" in \"%s\", "
5473 "or by the -D invocation option, or by the "
5474 "PGDATA environment variable.\n",
5475 progname, ConfigFileName);
5476 return false;
5477 }
5478 SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
5479 free(fname);
5480
5481 /*
5482 * Likewise for pg_ident.conf.
5483 */
5484 if (IdentFileName)
5485 fname = make_absolute_path(IdentFileName);
5486 else if (configdir)
5487 {
5488 fname = guc_malloc(FATAL,
5489 strlen(configdir) + strlen(IDENT_FILENAME) + 2);
5490 sprintf(fname, "%s/%s", configdir, IDENT_FILENAME);
5491 }
5492 else
5493 {
5494 write_stderr("%s does not know where to find the \"ident\" configuration file.\n"
5495 "This can be specified as \"ident_file\" in \"%s\", "
5496 "or by the -D invocation option, or by the "
5497 "PGDATA environment variable.\n",
5498 progname, ConfigFileName);
5499 return false;
5500 }
5501 SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
5502 free(fname);
5503
5504 free(configdir);
5505
5506 return true;
5507}
5508
5509
5510/*
5511 * Reset all options to their saved default values (implements RESET ALL)
5512 */
5513void
5514ResetAllOptions(void)
5515{
5516 int i;
5517
5518 for (i = 0; i < num_guc_variables; i++)
5519 {
5520 struct config_generic *gconf = guc_variables[i];
5521
5522 /* Don't reset non-SET-able values */
5523 if (gconf->context != PGC_SUSET &&
5524 gconf->context != PGC_USERSET)
5525 continue;
5526 /* Don't reset if special exclusion from RESET ALL */
5527 if (gconf->flags & GUC_NO_RESET_ALL)
5528 continue;
5529 /* No need to reset if wasn't SET */
5530 if (gconf->source <= PGC_S_OVERRIDE)
5531 continue;
5532
5533 /* Save old value to support transaction abort */
5534 push_old_value(gconf, GUC_ACTION_SET);
5535
5536 switch (gconf->vartype)
5537 {
5538 case PGC_BOOL:
5539 {
5540 struct config_bool *conf = (struct config_bool *) gconf;
5541
5542 if (conf->assign_hook)
5543 conf->assign_hook(conf->reset_val,
5544 conf->reset_extra);
5545 *conf->variable = conf->reset_val;
5546 set_extra_field(&conf->gen, &conf->gen.extra,
5547 conf->reset_extra);
5548 break;
5549 }
5550 case PGC_INT:
5551 {
5552 struct config_int *conf = (struct config_int *) gconf;
5553
5554 if (conf->assign_hook)
5555 conf->assign_hook(conf->reset_val,
5556 conf->reset_extra);
5557 *conf->variable = conf->reset_val;
5558 set_extra_field(&conf->gen, &conf->gen.extra,
5559 conf->reset_extra);
5560 break;
5561 }
5562 case PGC_REAL:
5563 {
5564 struct config_real *conf = (struct config_real *) gconf;
5565
5566 if (conf->assign_hook)
5567 conf->assign_hook(conf->reset_val,
5568 conf->reset_extra);
5569 *conf->variable = conf->reset_val;
5570 set_extra_field(&conf->gen, &conf->gen.extra,
5571 conf->reset_extra);
5572 break;
5573 }
5574 case PGC_STRING:
5575 {
5576 struct config_string *conf = (struct config_string *) gconf;
5577
5578 if (conf->assign_hook)
5579 conf->assign_hook(conf->reset_val,
5580 conf->reset_extra);
5581 set_string_field(conf, conf->variable, conf->reset_val);
5582 set_extra_field(&conf->gen, &conf->gen.extra,
5583 conf->reset_extra);
5584 break;
5585 }
5586 case PGC_ENUM:
5587 {
5588 struct config_enum *conf = (struct config_enum *) gconf;
5589
5590 if (conf->assign_hook)
5591 conf->assign_hook(conf->reset_val,
5592 conf->reset_extra);
5593 *conf->variable = conf->reset_val;
5594 set_extra_field(&conf->gen, &conf->gen.extra,
5595 conf->reset_extra);
5596 break;
5597 }
5598 }
5599
5600 gconf->source = gconf->reset_source;
5601 gconf->scontext = gconf->reset_scontext;
5602
5603 if (gconf->flags & GUC_REPORT)
5604 ReportGUCOption(gconf);
5605 }
5606}
5607
5608
5609/*
5610 * push_old_value
5611 * Push previous state during transactional assignment to a GUC variable.
5612 */
5613static void
5614push_old_value(struct config_generic *gconf, GucAction action)
5615{
5616 GucStack *stack;
5617
5618 /* If we're not inside a nest level, do nothing */
5619 if (GUCNestLevel == 0)
5620 return;
5621
5622 /* Do we already have a stack entry of the current nest level? */
5623 stack = gconf->stack;
5624 if (stack && stack->nest_level >= GUCNestLevel)
5625 {
5626 /* Yes, so adjust its state if necessary */
5627 Assert(stack->nest_level == GUCNestLevel);
5628 switch (action)
5629 {
5630 case GUC_ACTION_SET:
5631 /* SET overrides any prior action at same nest level */
5632 if (stack->state == GUC_SET_LOCAL)
5633 {
5634 /* must discard old masked value */
5635 discard_stack_value(gconf, &stack->masked);
5636 }
5637 stack->state = GUC_SET;
5638 break;
5639 case GUC_ACTION_LOCAL:
5640 if (stack->state == GUC_SET)
5641 {
5642 /* SET followed by SET LOCAL, remember SET's value */
5643 stack->masked_scontext = gconf->scontext;
5644 set_stack_value(gconf, &stack->masked);
5645 stack->state = GUC_SET_LOCAL;
5646 }
5647 /* in all other cases, no change to stack entry */
5648 break;
5649 case GUC_ACTION_SAVE:
5650 /* Could only have a prior SAVE of same variable */
5651 Assert(stack->state == GUC_SAVE);
5652 break;
5653 }
5654 Assert(guc_dirty); /* must be set already */
5655 return;
5656 }
5657
5658 /*
5659 * Push a new stack entry
5660 *
5661 * We keep all the stack entries in TopTransactionContext for simplicity.
5662 */
5663 stack = (GucStack *) MemoryContextAllocZero(TopTransactionContext,
5664 sizeof(GucStack));
5665
5666 stack->prev = gconf->stack;
5667 stack->nest_level = GUCNestLevel;
5668 switch (action)
5669 {
5670 case GUC_ACTION_SET:
5671 stack->state = GUC_SET;
5672 break;
5673 case GUC_ACTION_LOCAL:
5674 stack->state = GUC_LOCAL;
5675 break;
5676 case GUC_ACTION_SAVE:
5677 stack->state = GUC_SAVE;
5678 break;
5679 }
5680 stack->source = gconf->source;
5681 stack->scontext = gconf->scontext;
5682 set_stack_value(gconf, &stack->prior);
5683
5684 gconf->stack = stack;
5685
5686 /* Ensure we remember to pop at end of xact */
5687 guc_dirty = true;
5688}
5689
5690
5691/*
5692 * Do GUC processing at main transaction start.
5693 */
5694void
5695AtStart_GUC(void)
5696{
5697 /*
5698 * The nest level should be 0 between transactions; if it isn't, somebody
5699 * didn't call AtEOXact_GUC, or called it with the wrong nestLevel. We
5700 * throw a warning but make no other effort to clean up.
5701 */
5702 if (GUCNestLevel != 0)
5703 elog(WARNING, "GUC nest level = %d at transaction start",
5704 GUCNestLevel);
5705 GUCNestLevel = 1;
5706}
5707
5708/*
5709 * Enter a new nesting level for GUC values. This is called at subtransaction
5710 * start, and when entering a function that has proconfig settings, and in
5711 * some other places where we want to set GUC variables transiently.
5712 * NOTE we must not risk error here, else subtransaction start will be unhappy.
5713 */
5714int
5715NewGUCNestLevel(void)
5716{
5717 return ++GUCNestLevel;
5718}
5719
5720/*
5721 * Do GUC processing at transaction or subtransaction commit or abort, or
5722 * when exiting a function that has proconfig settings, or when undoing a
5723 * transient assignment to some GUC variables. (The name is thus a bit of
5724 * a misnomer; perhaps it should be ExitGUCNestLevel or some such.)
5725 * During abort, we discard all GUC settings that were applied at nesting
5726 * levels >= nestLevel. nestLevel == 1 corresponds to the main transaction.
5727 */
5728void
5729AtEOXact_GUC(bool isCommit, int nestLevel)
5730{
5731 bool still_dirty;
5732 int i;
5733
5734 /*
5735 * Note: it's possible to get here with GUCNestLevel == nestLevel-1 during
5736 * abort, if there is a failure during transaction start before
5737 * AtStart_GUC is called.
5738 */
5739 Assert(nestLevel > 0 &&
5740 (nestLevel <= GUCNestLevel ||
5741 (nestLevel == GUCNestLevel + 1 && !isCommit)));
5742
5743 /* Quick exit if nothing's changed in this transaction */
5744 if (!guc_dirty)
5745 {
5746 GUCNestLevel = nestLevel - 1;
5747 return;
5748 }
5749
5750 still_dirty = false;
5751 for (i = 0; i < num_guc_variables; i++)
5752 {
5753 struct config_generic *gconf = guc_variables[i];
5754 GucStack *stack;
5755
5756 /*
5757 * Process and pop each stack entry within the nest level. To simplify
5758 * fmgr_security_definer() and other places that use GUC_ACTION_SAVE,
5759 * we allow failure exit from code that uses a local nest level to be
5760 * recovered at the surrounding transaction or subtransaction abort;
5761 * so there could be more than one stack entry to pop.
5762 */
5763 while ((stack = gconf->stack) != NULL &&
5764 stack->nest_level >= nestLevel)
5765 {
5766 GucStack *prev = stack->prev;
5767 bool restorePrior = false;
5768 bool restoreMasked = false;
5769 bool changed;
5770
5771 /*
5772 * In this next bit, if we don't set either restorePrior or
5773 * restoreMasked, we must "discard" any unwanted fields of the
5774 * stack entries to avoid leaking memory. If we do set one of
5775 * those flags, unused fields will be cleaned up after restoring.
5776 */
5777 if (!isCommit) /* if abort, always restore prior value */
5778 restorePrior = true;
5779 else if (stack->state == GUC_SAVE)
5780 restorePrior = true;
5781 else if (stack->nest_level == 1)
5782 {
5783 /* transaction commit */
5784 if (stack->state == GUC_SET_LOCAL)
5785 restoreMasked = true;
5786 else if (stack->state == GUC_SET)
5787 {
5788 /* we keep the current active value */
5789 discard_stack_value(gconf, &stack->prior);
5790 }
5791 else /* must be GUC_LOCAL */
5792 restorePrior = true;
5793 }
5794 else if (prev == NULL ||
5795 prev->nest_level < stack->nest_level - 1)
5796 {
5797 /* decrement entry's level and do not pop it */
5798 stack->nest_level--;
5799 continue;
5800 }
5801 else
5802 {
5803 /*
5804 * We have to merge this stack entry into prev. See README for
5805 * discussion of this bit.
5806 */
5807 switch (stack->state)
5808 {
5809 case GUC_SAVE:
5810 Assert(false); /* can't get here */
5811 break;
5812
5813 case GUC_SET:
5814 /* next level always becomes SET */
5815 discard_stack_value(gconf, &stack->prior);
5816 if (prev->state == GUC_SET_LOCAL)
5817 discard_stack_value(gconf, &prev->masked);
5818 prev->state = GUC_SET;
5819 break;
5820
5821 case GUC_LOCAL:
5822 if (prev->state == GUC_SET)
5823 {
5824 /* LOCAL migrates down */
5825 prev->masked_scontext = stack->scontext;
5826 prev->masked = stack->prior;
5827 prev->state = GUC_SET_LOCAL;
5828 }
5829 else
5830 {
5831 /* else just forget this stack level */
5832 discard_stack_value(gconf, &stack->prior);
5833 }
5834 break;
5835
5836 case GUC_SET_LOCAL:
5837 /* prior state at this level no longer wanted */
5838 discard_stack_value(gconf, &stack->prior);
5839 /* copy down the masked state */
5840 prev->masked_scontext = stack->masked_scontext;
5841 if (prev->state == GUC_SET_LOCAL)
5842 discard_stack_value(gconf, &prev->masked);
5843 prev->masked = stack->masked;
5844 prev->state = GUC_SET_LOCAL;
5845 break;
5846 }
5847 }
5848
5849 changed = false;
5850
5851 if (restorePrior || restoreMasked)
5852 {
5853 /* Perform appropriate restoration of the stacked value */
5854 config_var_value newvalue;
5855 GucSource newsource;
5856 GucContext newscontext;
5857
5858 if (restoreMasked)
5859 {
5860 newvalue = stack->masked;
5861 newsource = PGC_S_SESSION;
5862 newscontext = stack->masked_scontext;
5863 }
5864 else
5865 {
5866 newvalue = stack->prior;
5867 newsource = stack->source;
5868 newscontext = stack->scontext;
5869 }
5870
5871 switch (gconf->vartype)
5872 {
5873 case PGC_BOOL:
5874 {
5875 struct config_bool *conf = (struct config_bool *) gconf;
5876 bool newval = newvalue.val.boolval;
5877 void *newextra = newvalue.extra;
5878
5879 if (*conf->variable != newval ||
5880 conf->gen.extra != newextra)
5881 {
5882 if (conf->assign_hook)
5883 conf->assign_hook(newval, newextra);
5884 *conf->variable = newval;
5885 set_extra_field(&conf->gen, &conf->gen.extra,
5886 newextra);
5887 changed = true;
5888 }
5889 break;
5890 }
5891 case PGC_INT:
5892 {
5893 struct config_int *conf = (struct config_int *) gconf;
5894 int newval = newvalue.val.intval;
5895 void *newextra = newvalue.extra;
5896
5897 if (*conf->variable != newval ||
5898 conf->gen.extra != newextra)
5899 {
5900 if (conf->assign_hook)
5901 conf->assign_hook(newval, newextra);
5902 *conf->variable = newval;
5903 set_extra_field(&conf->gen, &conf->gen.extra,
5904 newextra);
5905 changed = true;
5906 }
5907 break;
5908 }
5909 case PGC_REAL:
5910 {
5911 struct config_real *conf = (struct config_real *) gconf;
5912 double newval = newvalue.val.realval;
5913 void *newextra = newvalue.extra;
5914
5915 if (*conf->variable != newval ||
5916 conf->gen.extra != newextra)
5917 {
5918 if (conf->assign_hook)
5919 conf->assign_hook(newval, newextra);
5920 *conf->variable = newval;
5921 set_extra_field(&conf->gen, &conf->gen.extra,
5922 newextra);
5923 changed = true;
5924 }
5925 break;
5926 }
5927 case PGC_STRING:
5928 {
5929 struct config_string *conf = (struct config_string *) gconf;
5930 char *newval = newvalue.val.stringval;
5931 void *newextra = newvalue.extra;
5932
5933 if (*conf->variable != newval ||
5934 conf->gen.extra != newextra)
5935 {
5936 if (conf->assign_hook)
5937 conf->assign_hook(newval, newextra);
5938 set_string_field(conf, conf->variable, newval);
5939 set_extra_field(&conf->gen, &conf->gen.extra,
5940 newextra);
5941 changed = true;
5942 }
5943
5944 /*
5945 * Release stacked values if not used anymore. We
5946 * could use discard_stack_value() here, but since
5947 * we have type-specific code anyway, might as
5948 * well inline it.
5949 */
5950 set_string_field(conf, &stack->prior.val.stringval, NULL);
5951 set_string_field(conf, &stack->masked.val.stringval, NULL);
5952 break;
5953 }
5954 case PGC_ENUM:
5955 {
5956 struct config_enum *conf = (struct config_enum *) gconf;
5957 int newval = newvalue.val.enumval;
5958 void *newextra = newvalue.extra;
5959
5960 if (*conf->variable != newval ||
5961 conf->gen.extra != newextra)
5962 {
5963 if (conf->assign_hook)
5964 conf->assign_hook(newval, newextra);
5965 *conf->variable = newval;
5966 set_extra_field(&conf->gen, &conf->gen.extra,
5967 newextra);
5968 changed = true;
5969 }
5970 break;
5971 }
5972 }
5973
5974 /*
5975 * Release stacked extra values if not used anymore.
5976 */
5977 set_extra_field(gconf, &(stack->prior.extra), NULL);
5978 set_extra_field(gconf, &(stack->masked.extra), NULL);
5979
5980 /* And restore source information */
5981 gconf->source = newsource;
5982 gconf->scontext = newscontext;
5983 }
5984
5985 /* Finish popping the state stack */
5986 gconf->stack = prev;
5987 pfree(stack);
5988
5989 /* Report new value if we changed it */
5990 if (changed && (gconf->flags & GUC_REPORT))
5991 ReportGUCOption(gconf);
5992 } /* end of stack-popping loop */
5993
5994 if (stack != NULL)
5995 still_dirty = true;
5996 }
5997
5998 /* If there are no remaining stack entries, we can reset guc_dirty */
5999 guc_dirty = still_dirty;
6000
6001 /* Update nesting level */
6002 GUCNestLevel = nestLevel - 1;
6003}
6004
6005
6006/*
6007 * Start up automatic reporting of changes to variables marked GUC_REPORT.
6008 * This is executed at completion of backend startup.
6009 */
6010void
6011BeginReportingGUCOptions(void)
6012{
6013 int i;
6014
6015 /*
6016 * Don't do anything unless talking to an interactive frontend of protocol
6017 * 3.0 or later.
6018 */
6019 if (whereToSendOutput != DestRemote ||
6020 PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
6021 return;
6022
6023 reporting_enabled = true;
6024
6025 /* Transmit initial values of interesting variables */
6026 for (i = 0; i < num_guc_variables; i++)
6027 {
6028 struct config_generic *conf = guc_variables[i];
6029
6030 if (conf->flags & GUC_REPORT)
6031 ReportGUCOption(conf);
6032 }
6033}
6034
6035/*
6036 * ReportGUCOption: if appropriate, transmit option value to frontend
6037 */
6038static void
6039ReportGUCOption(struct config_generic *record)
6040{
6041 if (reporting_enabled && (record->flags & GUC_REPORT))
6042 {
6043 char *val = _ShowOption(record, false);
6044 StringInfoData msgbuf;
6045
6046 pq_beginmessage(&msgbuf, 'S');
6047 pq_sendstring(&msgbuf, record->name);
6048 pq_sendstring(&msgbuf, val);
6049 pq_endmessage(&msgbuf);
6050
6051 pfree(val);
6052 }
6053}
6054
6055/*
6056 * Convert a value from one of the human-friendly units ("kB", "min" etc.)
6057 * to the given base unit. 'value' and 'unit' are the input value and unit
6058 * to convert from (there can be trailing spaces in the unit string).
6059 * The converted value is stored in *base_value.
6060 * It's caller's responsibility to round off the converted value as necessary
6061 * and check for out-of-range.
6062 *
6063 * Returns true on success, false if the input unit is not recognized.
6064 */
6065static bool
6066convert_to_base_unit(double value, const char *unit,
6067 int base_unit, double *base_value)
6068{
6069 char unitstr[MAX_UNIT_LEN + 1];
6070 int unitlen;
6071 const unit_conversion *table;
6072 int i;
6073
6074 /* extract unit string to compare to table entries */
6075 unitlen = 0;
6076 while (*unit != '\0' && !isspace((unsigned char) *unit) &&
6077 unitlen < MAX_UNIT_LEN)
6078 unitstr[unitlen++] = *(unit++);
6079 unitstr[unitlen] = '\0';
6080 /* allow whitespace after unit */
6081 while (isspace((unsigned char) *unit))
6082 unit++;
6083 if (*unit != '\0')
6084 return false; /* unit too long, or garbage after it */
6085
6086 /* now search the appropriate table */
6087 if (base_unit & GUC_UNIT_MEMORY)
6088 table = memory_unit_conversion_table;
6089 else
6090 table = time_unit_conversion_table;
6091
6092 for (i = 0; *table[i].unit; i++)
6093 {
6094 if (base_unit == table[i].base_unit &&
6095 strcmp(unitstr, table[i].unit) == 0)
6096 {
6097 double cvalue = value * table[i].multiplier;
6098
6099 /*
6100 * If the user gave a fractional value such as "30.1GB", round it
6101 * off to the nearest multiple of the next smaller unit, if there
6102 * is one.
6103 */
6104 if (*table[i + 1].unit &&
6105 base_unit == table[i + 1].base_unit)
6106 cvalue = rint(cvalue / table[i + 1].multiplier) *
6107 table[i + 1].multiplier;
6108
6109 *base_value = cvalue;
6110 return true;
6111 }
6112 }
6113 return false;
6114}
6115
6116/*
6117 * Convert an integer value in some base unit to a human-friendly unit.
6118 *
6119 * The output unit is chosen so that it's the greatest unit that can represent
6120 * the value without loss. For example, if the base unit is GUC_UNIT_KB, 1024
6121 * is converted to 1 MB, but 1025 is represented as 1025 kB.
6122 */
6123static void
6124convert_int_from_base_unit(int64 base_value, int base_unit,
6125 int64 *value, const char **unit)
6126{
6127 const unit_conversion *table;
6128 int i;
6129
6130 *unit = NULL;
6131
6132 if (base_unit & GUC_UNIT_MEMORY)
6133 table = memory_unit_conversion_table;
6134 else
6135 table = time_unit_conversion_table;
6136
6137 for (i = 0; *table[i].unit; i++)
6138 {
6139 if (base_unit == table[i].base_unit)
6140 {
6141 /*
6142 * Accept the first conversion that divides the value evenly. We
6143 * assume that the conversions for each base unit are ordered from
6144 * greatest unit to the smallest!
6145 */
6146 if (table[i].multiplier <= 1.0 ||
6147 base_value % (int64) table[i].multiplier == 0)
6148 {
6149 *value = (int64) rint(base_value / table[i].multiplier);
6150 *unit = table[i].unit;
6151 break;
6152 }
6153 }
6154 }
6155
6156 Assert(*unit != NULL);
6157}
6158
6159/*
6160 * Convert a floating-point value in some base unit to a human-friendly unit.
6161 *
6162 * Same as above, except we have to do the math a bit differently, and
6163 * there's a possibility that we don't find any exact divisor.
6164 */
6165static void
6166convert_real_from_base_unit(double base_value, int base_unit,
6167 double *value, const char **unit)
6168{
6169 const unit_conversion *table;
6170 int i;
6171
6172 *unit = NULL;
6173
6174 if (base_unit & GUC_UNIT_MEMORY)
6175 table = memory_unit_conversion_table;
6176 else
6177 table = time_unit_conversion_table;
6178
6179 for (i = 0; *table[i].unit; i++)
6180 {
6181 if (base_unit == table[i].base_unit)
6182 {
6183 /*
6184 * Accept the first conversion that divides the value evenly; or
6185 * if there is none, use the smallest (last) target unit.
6186 *
6187 * What we actually care about here is whether snprintf with "%g"
6188 * will print the value as an integer, so the obvious test of
6189 * "*value == rint(*value)" is too strict; roundoff error might
6190 * make us choose an unreasonably small unit. As a compromise,
6191 * accept a divisor that is within 1e-8 of producing an integer.
6192 */
6193 *value = base_value / table[i].multiplier;
6194 *unit = table[i].unit;
6195 if (*value > 0 &&
6196 fabs((rint(*value) / *value) - 1.0) <= 1e-8)
6197 break;
6198 }
6199 }
6200
6201 Assert(*unit != NULL);
6202}
6203
6204/*
6205 * Return the name of a GUC's base unit (e.g. "ms") given its flags.
6206 * Return NULL if the GUC is unitless.
6207 */
6208static const char *
6209get_config_unit_name(int flags)
6210{
6211 switch (flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME))
6212 {
6213 case 0:
6214 return NULL; /* GUC has no units */
6215 case GUC_UNIT_BYTE:
6216 return "B";
6217 case GUC_UNIT_KB:
6218 return "kB";
6219 case GUC_UNIT_MB:
6220 return "MB";
6221 case GUC_UNIT_BLOCKS:
6222 {
6223 static char bbuf[8];
6224
6225 /* initialize if first time through */
6226 if (bbuf[0] == '\0')
6227 snprintf(bbuf, sizeof(bbuf), "%dkB", BLCKSZ / 1024);
6228 return bbuf;
6229 }
6230 case GUC_UNIT_XBLOCKS:
6231 {
6232 static char xbuf[8];
6233
6234 /* initialize if first time through */
6235 if (xbuf[0] == '\0')
6236 snprintf(xbuf, sizeof(xbuf), "%dkB", XLOG_BLCKSZ / 1024);
6237 return xbuf;
6238 }
6239 case GUC_UNIT_MS:
6240 return "ms";
6241 case GUC_UNIT_S:
6242 return "s";
6243 case GUC_UNIT_MIN:
6244 return "min";
6245 default:
6246 elog(ERROR, "unrecognized GUC units value: %d",
6247 flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME));
6248 return NULL;
6249 }
6250}
6251
6252
6253/*
6254 * Try to parse value as an integer. The accepted formats are the
6255 * usual decimal, octal, or hexadecimal formats, as well as floating-point
6256 * formats (which will be rounded to integer after any units conversion).
6257 * Optionally, the value can be followed by a unit name if "flags" indicates
6258 * a unit is allowed.
6259 *
6260 * If the string parses okay, return true, else false.
6261 * If okay and result is not NULL, return the value in *result.
6262 * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
6263 * HINT message, or NULL if no hint provided.
6264 */
6265bool
6266parse_int(const char *value, int *result, int flags, const char **hintmsg)
6267{
6268 /*
6269 * We assume here that double is wide enough to represent any integer
6270 * value with adequate precision.
6271 */
6272 double val;
6273 char *endptr;
6274
6275 /* To suppress compiler warnings, always set output params */
6276 if (result)
6277 *result = 0;
6278 if (hintmsg)
6279 *hintmsg = NULL;
6280
6281 /*
6282 * Try to parse as an integer (allowing octal or hex input). If the
6283 * conversion stops at a decimal point or 'e', or overflows, re-parse as
6284 * float. This should work fine as long as we have no unit names starting
6285 * with 'e'. If we ever do, the test could be extended to check for a
6286 * sign or digit after 'e', but for now that's unnecessary.
6287 */
6288 errno = 0;
6289 val = strtol(value, &endptr, 0);
6290 if (*endptr == '.' || *endptr == 'e' || *endptr == 'E' ||
6291 errno == ERANGE)
6292 {
6293 errno = 0;
6294 val = strtod(value, &endptr);
6295 }
6296
6297 if (endptr == value || errno == ERANGE)
6298 return false; /* no HINT for these cases */
6299
6300 /* reject NaN (infinities will fail range check below) */
6301 if (isnan(val))
6302 return false; /* treat same as syntax error; no HINT */
6303
6304 /* allow whitespace between number and unit */
6305 while (isspace((unsigned char) *endptr))
6306 endptr++;
6307
6308 /* Handle possible unit */
6309 if (*endptr != '\0')
6310 {
6311 if ((flags & GUC_UNIT) == 0)
6312 return false; /* this setting does not accept a unit */
6313
6314 if (!convert_to_base_unit(val,
6315 endptr, (flags & GUC_UNIT),
6316 &val))
6317 {
6318 /* invalid unit, or garbage after the unit; set hint and fail. */
6319 if (hintmsg)
6320 {
6321 if (flags & GUC_UNIT_MEMORY)
6322 *hintmsg = memory_units_hint;
6323 else
6324 *hintmsg = time_units_hint;
6325 }
6326 return false;
6327 }
6328 }
6329
6330 /* Round to int, then check for overflow */
6331 val = rint(val);
6332
6333 if (val > INT_MAX || val < INT_MIN)
6334 {
6335 if (hintmsg)
6336 *hintmsg = gettext_noop("Value exceeds integer range.");
6337 return false;
6338 }
6339
6340 if (result)
6341 *result = (int) val;
6342 return true;
6343}
6344
6345/*
6346 * Try to parse value as a floating point number in the usual format.
6347 * Optionally, the value can be followed by a unit name if "flags" indicates
6348 * a unit is allowed.
6349 *
6350 * If the string parses okay, return true, else false.
6351 * If okay and result is not NULL, return the value in *result.
6352 * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
6353 * HINT message, or NULL if no hint provided.
6354 */
6355bool
6356parse_real(const char *value, double *result, int flags, const char **hintmsg)
6357{
6358 double val;
6359 char *endptr;
6360
6361 /* To suppress compiler warnings, always set output params */
6362 if (result)
6363 *result = 0;
6364 if (hintmsg)
6365 *hintmsg = NULL;
6366
6367 errno = 0;
6368 val = strtod(value, &endptr);
6369
6370 if (endptr == value || errno == ERANGE)
6371 return false; /* no HINT for these cases */
6372
6373 /* reject NaN (infinities will fail range checks later) */
6374 if (isnan(val))
6375 return false; /* treat same as syntax error; no HINT */
6376
6377 /* allow whitespace between number and unit */
6378 while (isspace((unsigned char) *endptr))
6379 endptr++;
6380
6381 /* Handle possible unit */
6382 if (*endptr != '\0')
6383 {
6384 if ((flags & GUC_UNIT) == 0)
6385 return false; /* this setting does not accept a unit */
6386
6387 if (!convert_to_base_unit(val,
6388 endptr, (flags & GUC_UNIT),
6389 &val))
6390 {
6391 /* invalid unit, or garbage after the unit; set hint and fail. */
6392 if (hintmsg)
6393 {
6394 if (flags & GUC_UNIT_MEMORY)
6395 *hintmsg = memory_units_hint;
6396 else
6397 *hintmsg = time_units_hint;
6398 }
6399 return false;
6400 }
6401 }
6402
6403 if (result)
6404 *result = val;
6405 return true;
6406}
6407
6408
6409/*
6410 * Lookup the name for an enum option with the selected value.
6411 * Should only ever be called with known-valid values, so throws
6412 * an elog(ERROR) if the enum option is not found.
6413 *
6414 * The returned string is a pointer to static data and not
6415 * allocated for modification.
6416 */
6417const char *
6418config_enum_lookup_by_value(struct config_enum *record, int val)
6419{
6420 const struct config_enum_entry *entry;
6421
6422 for (entry = record->options; entry && entry->name; entry++)
6423 {
6424 if (entry->val == val)
6425 return entry->name;
6426 }
6427
6428 elog(ERROR, "could not find enum option %d for %s",
6429 val, record->gen.name);
6430 return NULL; /* silence compiler */
6431}
6432
6433
6434/*
6435 * Lookup the value for an enum option with the selected name
6436 * (case-insensitive).
6437 * If the enum option is found, sets the retval value and returns
6438 * true. If it's not found, return false and retval is set to 0.
6439 */
6440bool
6441config_enum_lookup_by_name(struct config_enum *record, const char *value,
6442 int *retval)
6443{
6444 const struct config_enum_entry *entry;
6445
6446 for (entry = record->options; entry && entry->name; entry++)
6447 {
6448 if (pg_strcasecmp(value, entry->name) == 0)
6449 {
6450 *retval = entry->val;
6451 return true;
6452 }
6453 }
6454
6455 *retval = 0;
6456 return false;
6457}
6458
6459
6460/*
6461 * Return a list of all available options for an enum, excluding
6462 * hidden ones, separated by the given separator.
6463 * If prefix is non-NULL, it is added before the first enum value.
6464 * If suffix is non-NULL, it is added to the end of the string.
6465 */
6466static char *
6467config_enum_get_options(struct config_enum *record, const char *prefix,
6468 const char *suffix, const char *separator)
6469{
6470 const struct config_enum_entry *entry;
6471 StringInfoData retstr;
6472 int seplen;
6473
6474 initStringInfo(&retstr);
6475 appendStringInfoString(&retstr, prefix);
6476
6477 seplen = strlen(separator);
6478 for (entry = record->options; entry && entry->name; entry++)
6479 {
6480 if (!entry->hidden)
6481 {
6482 appendStringInfoString(&retstr, entry->name);
6483 appendBinaryStringInfo(&retstr, separator, seplen);
6484 }
6485 }
6486
6487 /*
6488 * All the entries may have been hidden, leaving the string empty if no
6489 * prefix was given. This indicates a broken GUC setup, since there is no
6490 * use for an enum without any values, so we just check to make sure we
6491 * don't write to invalid memory instead of actually trying to do
6492 * something smart with it.
6493 */
6494 if (retstr.len >= seplen)
6495 {
6496 /* Replace final separator */
6497 retstr.data[retstr.len - seplen] = '\0';
6498 retstr.len -= seplen;
6499 }
6500
6501 appendStringInfoString(&retstr, suffix);
6502
6503 return retstr.data;
6504}
6505
6506/*
6507 * Parse and validate a proposed value for the specified configuration
6508 * parameter.
6509 *
6510 * This does built-in checks (such as range limits for an integer parameter)
6511 * and also calls any check hook the parameter may have.
6512 *
6513 * record: GUC variable's info record
6514 * name: variable name (should match the record of course)
6515 * value: proposed value, as a string
6516 * source: identifies source of value (check hooks may need this)
6517 * elevel: level to log any error reports at
6518 * newval: on success, converted parameter value is returned here
6519 * newextra: on success, receives any "extra" data returned by check hook
6520 * (caller must initialize *newextra to NULL)
6521 *
6522 * Returns true if OK, false if not (or throws error, if elevel >= ERROR)
6523 */
6524static bool
6525parse_and_validate_value(struct config_generic *record,
6526 const char *name, const char *value,
6527 GucSource source, int elevel,
6528 union config_var_val *newval, void **newextra)
6529{
6530 switch (record->vartype)
6531 {
6532 case PGC_BOOL:
6533 {
6534 struct config_bool *conf = (struct config_bool *) record;
6535
6536 if (!parse_bool(value, &newval->boolval))
6537 {
6538 ereport(elevel,
6539 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6540 errmsg("parameter \"%s\" requires a Boolean value",
6541 name)));
6542 return false;
6543 }
6544
6545 if (!call_bool_check_hook(conf, &newval->boolval, newextra,
6546 source, elevel))
6547 return false;
6548 }
6549 break;
6550 case PGC_INT:
6551 {
6552 struct config_int *conf = (struct config_int *) record;
6553 const char *hintmsg;
6554
6555 if (!parse_int(value, &newval->intval,
6556 conf->gen.flags, &hintmsg))
6557 {
6558 ereport(elevel,
6559 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6560 errmsg("invalid value for parameter \"%s\": \"%s\"",
6561 name, value),
6562 hintmsg ? errhint("%s", _(hintmsg)) : 0));
6563 return false;
6564 }
6565
6566 if (newval->intval < conf->min || newval->intval > conf->max)
6567 {
6568 const char *unit = get_config_unit_name(conf->gen.flags);
6569
6570 ereport(elevel,
6571 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6572 errmsg("%d%s%s is outside the valid range for parameter \"%s\" (%d .. %d)",
6573 newval->intval,
6574 unit ? " " : "",
6575 unit ? unit : "",
6576 name,
6577 conf->min, conf->max)));
6578 return false;
6579 }
6580
6581 if (!call_int_check_hook(conf, &newval->intval, newextra,
6582 source, elevel))
6583 return false;
6584 }
6585 break;
6586 case PGC_REAL:
6587 {
6588 struct config_real *conf = (struct config_real *) record;
6589 const char *hintmsg;
6590
6591 if (!parse_real(value, &newval->realval,
6592 conf->gen.flags, &hintmsg))
6593 {
6594 ereport(elevel,
6595 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6596 errmsg("invalid value for parameter \"%s\": \"%s\"",
6597 name, value),
6598 hintmsg ? errhint("%s", _(hintmsg)) : 0));
6599 return false;
6600 }
6601
6602 if (newval->realval < conf->min || newval->realval > conf->max)
6603 {
6604 const char *unit = get_config_unit_name(conf->gen.flags);
6605
6606 ereport(elevel,
6607 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6608 errmsg("%g%s%s is outside the valid range for parameter \"%s\" (%g .. %g)",
6609 newval->realval,
6610 unit ? " " : "",
6611 unit ? unit : "",
6612 name,
6613 conf->min, conf->max)));
6614 return false;
6615 }
6616
6617 if (!call_real_check_hook(conf, &newval->realval, newextra,
6618 source, elevel))
6619 return false;
6620 }
6621 break;
6622 case PGC_STRING:
6623 {
6624 struct config_string *conf = (struct config_string *) record;
6625
6626 /*
6627 * The value passed by the caller could be transient, so we
6628 * always strdup it.
6629 */
6630 newval->stringval = guc_strdup(elevel, value);
6631 if (newval->stringval == NULL)
6632 return false;
6633
6634 /*
6635 * The only built-in "parsing" check we have is to apply
6636 * truncation if GUC_IS_NAME.
6637 */
6638 if (conf->gen.flags & GUC_IS_NAME)
6639 truncate_identifier(newval->stringval,
6640 strlen(newval->stringval),
6641 true);
6642
6643 if (!call_string_check_hook(conf, &newval->stringval, newextra,
6644 source, elevel))
6645 {
6646 free(newval->stringval);
6647 newval->stringval = NULL;
6648 return false;
6649 }
6650 }
6651 break;
6652 case PGC_ENUM:
6653 {
6654 struct config_enum *conf = (struct config_enum *) record;
6655
6656 if (!config_enum_lookup_by_name(conf, value, &newval->enumval))
6657 {
6658 char *hintmsg;
6659
6660 hintmsg = config_enum_get_options(conf,
6661 "Available values: ",
6662 ".", ", ");
6663
6664 ereport(elevel,
6665 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6666 errmsg("invalid value for parameter \"%s\": \"%s\"",
6667 name, value),
6668 hintmsg ? errhint("%s", _(hintmsg)) : 0));
6669
6670 if (hintmsg)
6671 pfree(hintmsg);
6672 return false;
6673 }
6674
6675 if (!call_enum_check_hook(conf, &newval->enumval, newextra,
6676 source, elevel))
6677 return false;
6678 }
6679 break;
6680 }
6681
6682 return true;
6683}
6684
6685
6686/*
6687 * Sets option `name' to given value.
6688 *
6689 * The value should be a string, which will be parsed and converted to
6690 * the appropriate data type. The context and source parameters indicate
6691 * in which context this function is being called, so that it can apply the
6692 * access restrictions properly.
6693 *
6694 * If value is NULL, set the option to its default value (normally the
6695 * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
6696 *
6697 * action indicates whether to set the value globally in the session, locally
6698 * to the current top transaction, or just for the duration of a function call.
6699 *
6700 * If changeVal is false then don't really set the option but do all
6701 * the checks to see if it would work.
6702 *
6703 * elevel should normally be passed as zero, allowing this function to make
6704 * its standard choice of ereport level. However some callers need to be
6705 * able to override that choice; they should pass the ereport level to use.
6706 *
6707 * Return value:
6708 * +1: the value is valid and was successfully applied.
6709 * 0: the name or value is invalid (but see below).
6710 * -1: the value was not applied because of context, priority, or changeVal.
6711 *
6712 * If there is an error (non-existing option, invalid value) then an
6713 * ereport(ERROR) is thrown *unless* this is called for a source for which
6714 * we don't want an ERROR (currently, those are defaults, the config file,
6715 * and per-database or per-user settings, as well as callers who specify
6716 * a less-than-ERROR elevel). In those cases we write a suitable error
6717 * message via ereport() and return 0.
6718 *
6719 * See also SetConfigOption for an external interface.
6720 */
6721int
6722set_config_option(const char *name, const char *value,
6723 GucContext context, GucSource source,
6724 GucAction action, bool changeVal, int elevel,
6725 bool is_reload)
6726{
6727 struct config_generic *record;
6728 union config_var_val newval_union;
6729 void *newextra = NULL;
6730 bool prohibitValueChange = false;
6731 bool makeDefault;
6732
6733 if (elevel == 0)
6734 {
6735 if (source == PGC_S_DEFAULT || source == PGC_S_FILE)
6736 {
6737 /*
6738 * To avoid cluttering the log, only the postmaster bleats loudly
6739 * about problems with the config file.
6740 */
6741 elevel = IsUnderPostmaster ? DEBUG3 : LOG;
6742 }
6743 else if (source == PGC_S_GLOBAL ||
6744 source == PGC_S_DATABASE ||
6745 source == PGC_S_USER ||
6746 source == PGC_S_DATABASE_USER)
6747 elevel = WARNING;
6748 else
6749 elevel = ERROR;
6750 }
6751
6752 /*
6753 * GUC_ACTION_SAVE changes are acceptable during a parallel operation,
6754 * because the current worker will also pop the change. We're probably
6755 * dealing with a function having a proconfig entry. Only the function's
6756 * body should observe the change, and peer workers do not share in the
6757 * execution of a function call started by this worker.
6758 *
6759 * Other changes might need to affect other workers, so forbid them.
6760 */
6761 if (IsInParallelMode() && changeVal && action != GUC_ACTION_SAVE)
6762 ereport(elevel,
6763 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
6764 errmsg("cannot set parameters during a parallel operation")));
6765
6766 record = find_option(name, true, elevel);
6767 if (record == NULL)
6768 {
6769 ereport(elevel,
6770 (errcode(ERRCODE_UNDEFINED_OBJECT),
6771 errmsg("unrecognized configuration parameter \"%s\"", name)));
6772 return 0;
6773 }
6774
6775 /*
6776 * Check if the option can be set at this time. See guc.h for the precise
6777 * rules.
6778 */
6779 switch (record->context)
6780 {
6781 case PGC_INTERNAL:
6782 if (context != PGC_INTERNAL)
6783 {
6784 ereport(elevel,
6785 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
6786 errmsg("parameter \"%s\" cannot be changed",
6787 name)));
6788 return 0;
6789 }
6790 break;
6791 case PGC_POSTMASTER:
6792 if (context == PGC_SIGHUP)
6793 {
6794 /*
6795 * We are re-reading a PGC_POSTMASTER variable from
6796 * postgresql.conf. We can't change the setting, so we should
6797 * give a warning if the DBA tries to change it. However,
6798 * because of variant formats, canonicalization by check
6799 * hooks, etc, we can't just compare the given string directly
6800 * to what's stored. Set a flag to check below after we have
6801 * the final storable value.
6802 */
6803 prohibitValueChange = true;
6804 }
6805 else if (context != PGC_POSTMASTER)
6806 {
6807 ereport(elevel,
6808 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
6809 errmsg("parameter \"%s\" cannot be changed without restarting the server",
6810 name)));
6811 return 0;
6812 }
6813 break;
6814 case PGC_SIGHUP:
6815 if (context != PGC_SIGHUP && context != PGC_POSTMASTER)
6816 {
6817 ereport(elevel,
6818 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
6819 errmsg("parameter \"%s\" cannot be changed now",
6820 name)));
6821 return 0;
6822 }
6823
6824 /*
6825 * Hmm, the idea of the SIGHUP context is "ought to be global, but
6826 * can be changed after postmaster start". But there's nothing
6827 * that prevents a crafty administrator from sending SIGHUP
6828 * signals to individual backends only.
6829 */
6830 break;
6831 case PGC_SU_BACKEND:
6832 /* Reject if we're connecting but user is not superuser */
6833 if (context == PGC_BACKEND)
6834 {
6835 ereport(elevel,
6836 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
6837 errmsg("permission denied to set parameter \"%s\"",
6838 name)));
6839 return 0;
6840 }
6841 /* fall through to process the same as PGC_BACKEND */
6842 /* FALLTHROUGH */
6843 case PGC_BACKEND:
6844 if (context == PGC_SIGHUP)
6845 {
6846 /*
6847 * If a PGC_BACKEND or PGC_SU_BACKEND parameter is changed in
6848 * the config file, we want to accept the new value in the
6849 * postmaster (whence it will propagate to
6850 * subsequently-started backends), but ignore it in existing
6851 * backends. This is a tad klugy, but necessary because we
6852 * don't re-read the config file during backend start.
6853 *
6854 * In EXEC_BACKEND builds, this works differently: we load all
6855 * non-default settings from the CONFIG_EXEC_PARAMS file
6856 * during backend start. In that case we must accept
6857 * PGC_SIGHUP settings, so as to have the same value as if
6858 * we'd forked from the postmaster. This can also happen when
6859 * using RestoreGUCState() within a background worker that
6860 * needs to have the same settings as the user backend that
6861 * started it. is_reload will be true when either situation
6862 * applies.
6863 */
6864 if (IsUnderPostmaster && !is_reload)
6865 return -1;
6866 }
6867 else if (context != PGC_POSTMASTER &&
6868 context != PGC_BACKEND &&
6869 context != PGC_SU_BACKEND &&
6870 source != PGC_S_CLIENT)
6871 {
6872 ereport(elevel,
6873 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
6874 errmsg("parameter \"%s\" cannot be set after connection start",
6875 name)));
6876 return 0;
6877 }
6878 break;
6879 case PGC_SUSET:
6880 if (context == PGC_USERSET || context == PGC_BACKEND)
6881 {
6882 ereport(elevel,
6883 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
6884 errmsg("permission denied to set parameter \"%s\"",
6885 name)));
6886 return 0;
6887 }
6888 break;
6889 case PGC_USERSET:
6890 /* always okay */
6891 break;
6892 }
6893
6894 /*
6895 * Disallow changing GUC_NOT_WHILE_SEC_REST values if we are inside a
6896 * security restriction context. We can reject this regardless of the GUC
6897 * context or source, mainly because sources that it might be reasonable
6898 * to override for won't be seen while inside a function.
6899 *
6900 * Note: variables marked GUC_NOT_WHILE_SEC_REST should usually be marked
6901 * GUC_NO_RESET_ALL as well, because ResetAllOptions() doesn't check this.
6902 * An exception might be made if the reset value is assumed to be "safe".
6903 *
6904 * Note: this flag is currently used for "session_authorization" and
6905 * "role". We need to prohibit changing these inside a local userid
6906 * context because when we exit it, GUC won't be notified, leaving things
6907 * out of sync. (This could be fixed by forcing a new GUC nesting level,
6908 * but that would change behavior in possibly-undesirable ways.) Also, we
6909 * prohibit changing these in a security-restricted operation because
6910 * otherwise RESET could be used to regain the session user's privileges.
6911 */
6912 if (record->flags & GUC_NOT_WHILE_SEC_REST)
6913 {
6914 if (InLocalUserIdChange())
6915 {
6916 /*
6917 * Phrasing of this error message is historical, but it's the most
6918 * common case.
6919 */
6920 ereport(elevel,
6921 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
6922 errmsg("cannot set parameter \"%s\" within security-definer function",
6923 name)));
6924 return 0;
6925 }
6926 if (InSecurityRestrictedOperation())
6927 {
6928 ereport(elevel,
6929 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
6930 errmsg("cannot set parameter \"%s\" within security-restricted operation",
6931 name)));
6932 return 0;
6933 }
6934 }
6935
6936 /*
6937 * Should we set reset/stacked values? (If so, the behavior is not
6938 * transactional.) This is done either when we get a default value from
6939 * the database's/user's/client's default settings or when we reset a
6940 * value to its default.
6941 */
6942 makeDefault = changeVal && (source <= PGC_S_OVERRIDE) &&
6943 ((value != NULL) || source == PGC_S_DEFAULT);
6944
6945 /*
6946 * Ignore attempted set if overridden by previously processed setting.
6947 * However, if changeVal is false then plow ahead anyway since we are
6948 * trying to find out if the value is potentially good, not actually use
6949 * it. Also keep going if makeDefault is true, since we may want to set
6950 * the reset/stacked values even if we can't set the variable itself.
6951 */
6952 if (record->source > source)
6953 {
6954 if (changeVal && !makeDefault)
6955 {
6956 elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
6957 name);
6958 return -1;
6959 }
6960 changeVal = false;
6961 }
6962
6963 /*
6964 * Evaluate value and set variable.
6965 */
6966 switch (record->vartype)
6967 {
6968 case PGC_BOOL:
6969 {
6970 struct config_bool *conf = (struct config_bool *) record;
6971
6972#define newval (newval_union.boolval)
6973
6974 if (value)
6975 {
6976 if (!parse_and_validate_value(record, name, value,
6977 source, elevel,
6978 &newval_union, &newextra))
6979 return 0;
6980 }
6981 else if (source == PGC_S_DEFAULT)
6982 {
6983 newval = conf->boot_val;
6984 if (!call_bool_check_hook(conf, &newval, &newextra,
6985 source, elevel))
6986 return 0;
6987 }
6988 else
6989 {
6990 newval = conf->reset_val;
6991 newextra = conf->reset_extra;
6992 source = conf->gen.reset_source;
6993 context = conf->gen.reset_scontext;
6994 }
6995
6996 if (prohibitValueChange)
6997 {
6998 if (*conf->variable != newval)
6999 {
7000 record->status |= GUC_PENDING_RESTART;
7001 ereport(elevel,
7002 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
7003 errmsg("parameter \"%s\" cannot be changed without restarting the server",
7004 name)));
7005 return 0;
7006 }
7007 record->status &= ~GUC_PENDING_RESTART;
7008 return -1;
7009 }
7010
7011 if (changeVal)
7012 {
7013 /* Save old value to support transaction abort */
7014 if (!makeDefault)
7015 push_old_value(&conf->gen, action);
7016
7017 if (conf->assign_hook)
7018 conf->assign_hook(newval, newextra);
7019 *conf->variable = newval;
7020 set_extra_field(&conf->gen, &conf->gen.extra,
7021 newextra);
7022 conf->gen.source = source;
7023 conf->gen.scontext = context;
7024 }
7025 if (makeDefault)
7026 {
7027 GucStack *stack;
7028
7029 if (conf->gen.reset_source <= source)
7030 {
7031 conf->reset_val = newval;
7032 set_extra_field(&conf->gen, &conf->reset_extra,
7033 newextra);
7034 conf->gen.reset_source = source;
7035 conf->gen.reset_scontext = context;
7036 }
7037 for (stack = conf->gen.stack; stack; stack = stack->prev)
7038 {
7039 if (stack->source <= source)
7040 {
7041 stack->prior.val.boolval = newval;
7042 set_extra_field(&conf->gen, &stack->prior.extra,
7043 newextra);
7044 stack->source = source;
7045 stack->scontext = context;
7046 }
7047 }
7048 }
7049
7050 /* Perhaps we didn't install newextra anywhere */
7051 if (newextra && !extra_field_used(&conf->gen, newextra))
7052 free(newextra);
7053 break;
7054
7055#undef newval
7056 }
7057
7058 case PGC_INT:
7059 {
7060 struct config_int *conf = (struct config_int *) record;
7061
7062#define newval (newval_union.intval)
7063
7064 if (value)
7065 {
7066 if (!parse_and_validate_value(record, name, value,
7067 source, elevel,
7068 &newval_union, &newextra))
7069 return 0;
7070 }
7071 else if (source == PGC_S_DEFAULT)
7072 {
7073 newval = conf->boot_val;
7074 if (!call_int_check_hook(conf, &newval, &newextra,
7075 source, elevel))
7076 return 0;
7077 }
7078 else
7079 {
7080 newval = conf->reset_val;
7081 newextra = conf->reset_extra;
7082 source = conf->gen.reset_source;
7083 context = conf->gen.reset_scontext;
7084 }
7085
7086 if (prohibitValueChange)
7087 {
7088 if (*conf->variable != newval)
7089 {
7090 record->status |= GUC_PENDING_RESTART;
7091 ereport(elevel,
7092 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
7093 errmsg("parameter \"%s\" cannot be changed without restarting the server",
7094 name)));
7095 return 0;
7096 }
7097 record->status &= ~GUC_PENDING_RESTART;
7098 return -1;
7099 }
7100
7101 if (changeVal)
7102 {
7103 /* Save old value to support transaction abort */
7104 if (!makeDefault)
7105 push_old_value(&conf->gen, action);
7106
7107 if (conf->assign_hook)
7108 conf->assign_hook(newval, newextra);
7109 *conf->variable = newval;
7110 set_extra_field(&conf->gen, &conf->gen.extra,
7111 newextra);
7112 conf->gen.source = source;
7113 conf->gen.scontext = context;
7114 }
7115 if (makeDefault)
7116 {
7117 GucStack *stack;
7118
7119 if (conf->gen.reset_source <= source)
7120 {
7121 conf->reset_val = newval;
7122 set_extra_field(&conf->gen, &conf->reset_extra,
7123 newextra);
7124 conf->gen.reset_source = source;
7125 conf->gen.reset_scontext = context;
7126 }
7127 for (stack = conf->gen.stack; stack; stack = stack->prev)
7128 {
7129 if (stack->source <= source)
7130 {
7131 stack->prior.val.intval = newval;
7132 set_extra_field(&conf->gen, &stack->prior.extra,
7133 newextra);
7134 stack->source = source;
7135 stack->scontext = context;
7136 }
7137 }
7138 }
7139
7140 /* Perhaps we didn't install newextra anywhere */
7141 if (newextra && !extra_field_used(&conf->gen, newextra))
7142 free(newextra);
7143 break;
7144
7145#undef newval
7146 }
7147
7148 case PGC_REAL:
7149 {
7150 struct config_real *conf = (struct config_real *) record;
7151
7152#define newval (newval_union.realval)
7153
7154 if (value)
7155 {
7156 if (!parse_and_validate_value(record, name, value,
7157 source, elevel,
7158 &newval_union, &newextra))
7159 return 0;
7160 }
7161 else if (source == PGC_S_DEFAULT)
7162 {
7163 newval = conf->boot_val;
7164 if (!call_real_check_hook(conf, &newval, &newextra,
7165 source, elevel))
7166 return 0;
7167 }
7168 else
7169 {
7170 newval = conf->reset_val;
7171 newextra = conf->reset_extra;
7172 source = conf->gen.reset_source;
7173 context = conf->gen.reset_scontext;
7174 }
7175
7176 if (prohibitValueChange)
7177 {
7178 if (*conf->variable != newval)
7179 {
7180 record->status |= GUC_PENDING_RESTART;
7181 ereport(elevel,
7182 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
7183 errmsg("parameter \"%s\" cannot be changed without restarting the server",
7184 name)));
7185 return 0;
7186 }
7187 record->status &= ~GUC_PENDING_RESTART;
7188 return -1;
7189 }
7190
7191 if (changeVal)
7192 {
7193 /* Save old value to support transaction abort */
7194 if (!makeDefault)
7195 push_old_value(&conf->gen, action);
7196
7197 if (conf->assign_hook)
7198 conf->assign_hook(newval, newextra);
7199 *conf->variable = newval;
7200 set_extra_field(&conf->gen, &conf->gen.extra,
7201 newextra);
7202 conf->gen.source = source;
7203 conf->gen.scontext = context;
7204 }
7205 if (makeDefault)
7206 {
7207 GucStack *stack;
7208
7209 if (conf->gen.reset_source <= source)
7210 {
7211 conf->reset_val = newval;
7212 set_extra_field(&conf->gen, &conf->reset_extra,
7213 newextra);
7214 conf->gen.reset_source = source;
7215 conf->gen.reset_scontext = context;
7216 }
7217 for (stack = conf->gen.stack; stack; stack = stack->prev)
7218 {
7219 if (stack->source <= source)
7220 {
7221 stack->prior.val.realval = newval;
7222 set_extra_field(&conf->gen, &stack->prior.extra,
7223 newextra);
7224 stack->source = source;
7225 stack->scontext = context;
7226 }
7227 }
7228 }
7229
7230 /* Perhaps we didn't install newextra anywhere */
7231 if (newextra && !extra_field_used(&conf->gen, newextra))
7232 free(newextra);
7233 break;
7234
7235#undef newval
7236 }
7237
7238 case PGC_STRING:
7239 {
7240 struct config_string *conf = (struct config_string *) record;
7241
7242#define newval (newval_union.stringval)
7243
7244 if (value)
7245 {
7246 if (!parse_and_validate_value(record, name, value,
7247 source, elevel,
7248 &newval_union, &newextra))
7249 return 0;
7250 }
7251 else if (source == PGC_S_DEFAULT)
7252 {
7253 /* non-NULL boot_val must always get strdup'd */
7254 if (conf->boot_val != NULL)
7255 {
7256 newval = guc_strdup(elevel, conf->boot_val);
7257 if (newval == NULL)
7258 return 0;
7259 }
7260 else
7261 newval = NULL;
7262
7263 if (!call_string_check_hook(conf, &newval, &newextra,
7264 source, elevel))
7265 {
7266 free(newval);
7267 return 0;
7268 }
7269 }
7270 else
7271 {
7272 /*
7273 * strdup not needed, since reset_val is already under
7274 * guc.c's control
7275 */
7276 newval = conf->reset_val;
7277 newextra = conf->reset_extra;
7278 source = conf->gen.reset_source;
7279 context = conf->gen.reset_scontext;
7280 }
7281
7282 if (prohibitValueChange)
7283 {
7284 /* newval shouldn't be NULL, so we're a bit sloppy here */
7285 if (*conf->variable == NULL || newval == NULL ||
7286 strcmp(*conf->variable, newval) != 0)
7287 {
7288 record->status |= GUC_PENDING_RESTART;
7289 ereport(elevel,
7290 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
7291 errmsg("parameter \"%s\" cannot be changed without restarting the server",
7292 name)));
7293 return 0;
7294 }
7295 record->status &= ~GUC_PENDING_RESTART;
7296 return -1;
7297 }
7298
7299 if (changeVal)
7300 {
7301 /* Save old value to support transaction abort */
7302 if (!makeDefault)
7303 push_old_value(&conf->gen, action);
7304
7305 if (conf->assign_hook)
7306 conf->assign_hook(newval, newextra);
7307 set_string_field(conf, conf->variable, newval);
7308 set_extra_field(&conf->gen, &conf->gen.extra,
7309 newextra);
7310 conf->gen.source = source;
7311 conf->gen.scontext = context;
7312 }
7313
7314 if (makeDefault)
7315 {
7316 GucStack *stack;
7317
7318 if (conf->gen.reset_source <= source)
7319 {
7320 set_string_field(conf, &conf->reset_val, newval);
7321 set_extra_field(&conf->gen, &conf->reset_extra,
7322 newextra);
7323 conf->gen.reset_source = source;
7324 conf->gen.reset_scontext = context;
7325 }
7326 for (stack = conf->gen.stack; stack; stack = stack->prev)
7327 {
7328 if (stack->source <= source)
7329 {
7330 set_string_field(conf, &stack->prior.val.stringval,
7331 newval);
7332 set_extra_field(&conf->gen, &stack->prior.extra,
7333 newextra);
7334 stack->source = source;
7335 stack->scontext = context;
7336 }
7337 }
7338 }
7339
7340 /* Perhaps we didn't install newval anywhere */
7341 if (newval && !string_field_used(conf, newval))
7342 free(newval);
7343 /* Perhaps we didn't install newextra anywhere */
7344 if (newextra && !extra_field_used(&conf->gen, newextra))
7345 free(newextra);
7346 break;
7347
7348#undef newval
7349 }
7350
7351 case PGC_ENUM:
7352 {
7353 struct config_enum *conf = (struct config_enum *) record;
7354
7355#define newval (newval_union.enumval)
7356
7357 if (value)
7358 {
7359 if (!parse_and_validate_value(record, name, value,
7360 source, elevel,
7361 &newval_union, &newextra))
7362 return 0;
7363 }
7364 else if (source == PGC_S_DEFAULT)
7365 {
7366 newval = conf->boot_val;
7367 if (!call_enum_check_hook(conf, &newval, &newextra,
7368 source, elevel))
7369 return 0;
7370 }
7371 else
7372 {
7373 newval = conf->reset_val;
7374 newextra = conf->reset_extra;
7375 source = conf->gen.reset_source;
7376 context = conf->gen.reset_scontext;
7377 }
7378
7379 if (prohibitValueChange)
7380 {
7381 if (*conf->variable != newval)
7382 {
7383 record->status |= GUC_PENDING_RESTART;
7384 ereport(elevel,
7385 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
7386 errmsg("parameter \"%s\" cannot be changed without restarting the server",
7387 name)));
7388 return 0;
7389 }
7390 record->status &= ~GUC_PENDING_RESTART;
7391 return -1;
7392 }
7393
7394 if (changeVal)
7395 {
7396 /* Save old value to support transaction abort */
7397 if (!makeDefault)
7398 push_old_value(&conf->gen, action);
7399
7400 if (conf->assign_hook)
7401 conf->assign_hook(newval, newextra);
7402 *conf->variable = newval;
7403 set_extra_field(&conf->gen, &conf->gen.extra,
7404 newextra);
7405 conf->gen.source = source;
7406 conf->gen.scontext = context;
7407 }
7408 if (makeDefault)
7409 {
7410 GucStack *stack;
7411
7412 if (conf->gen.reset_source <= source)
7413 {
7414 conf->reset_val = newval;
7415 set_extra_field(&conf->gen, &conf->reset_extra,
7416 newextra);
7417 conf->gen.reset_source = source;
7418 conf->gen.reset_scontext = context;
7419 }
7420 for (stack = conf->gen.stack; stack; stack = stack->prev)
7421 {
7422 if (stack->source <= source)
7423 {
7424 stack->prior.val.enumval = newval;
7425 set_extra_field(&conf->gen, &stack->prior.extra,
7426 newextra);
7427 stack->source = source;
7428 stack->scontext = context;
7429 }
7430 }
7431 }
7432
7433 /* Perhaps we didn't install newextra anywhere */
7434 if (newextra && !extra_field_used(&conf->gen, newextra))
7435 free(newextra);
7436 break;
7437
7438#undef newval
7439 }
7440 }
7441
7442 if (changeVal && (record->flags & GUC_REPORT))
7443 ReportGUCOption(record);
7444
7445 return changeVal ? 1 : -1;
7446}
7447
7448
7449/*
7450 * Set the fields for source file and line number the setting came from.
7451 */
7452static void
7453set_config_sourcefile(const char *name, char *sourcefile, int sourceline)
7454{
7455 struct config_generic *record;
7456 int elevel;
7457
7458 /*
7459 * To avoid cluttering the log, only the postmaster bleats loudly about
7460 * problems with the config file.
7461 */
7462 elevel = IsUnderPostmaster ? DEBUG3 : LOG;
7463
7464 record = find_option(name, true, elevel);
7465 /* should not happen */
7466 if (record == NULL)
7467 elog(ERROR, "unrecognized configuration parameter \"%s\"", name);
7468
7469 sourcefile = guc_strdup(elevel, sourcefile);
7470 if (record->sourcefile)
7471 free(record->sourcefile);
7472 record->sourcefile = sourcefile;
7473 record->sourceline = sourceline;
7474}
7475
7476/*
7477 * Set a config option to the given value.
7478 *
7479 * See also set_config_option; this is just the wrapper to be called from
7480 * outside GUC. (This function should be used when possible, because its API
7481 * is more stable than set_config_option's.)
7482 *
7483 * Note: there is no support here for setting source file/line, as it
7484 * is currently not needed.
7485 */
7486void
7487SetConfigOption(const char *name, const char *value,
7488 GucContext context, GucSource source)
7489{
7490 (void) set_config_option(name, value, context, source,
7491 GUC_ACTION_SET, true, 0, false);
7492}
7493
7494
7495
7496/*
7497 * Fetch the current value of the option `name', as a string.
7498 *
7499 * If the option doesn't exist, return NULL if missing_ok is true (NOTE that
7500 * this cannot be distinguished from a string variable with a NULL value!),
7501 * otherwise throw an ereport and don't return.
7502 *
7503 * If restrict_privileged is true, we also enforce that only superusers and
7504 * members of the pg_read_all_settings role can see GUC_SUPERUSER_ONLY
7505 * variables. This should only be passed as true in user-driven calls.
7506 *
7507 * The string is *not* allocated for modification and is really only
7508 * valid until the next call to configuration related functions.
7509 */
7510const char *
7511GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
7512{
7513 struct config_generic *record;
7514 static char buffer[256];
7515
7516 record = find_option(name, false, ERROR);
7517 if (record == NULL)
7518 {
7519 if (missing_ok)
7520 return NULL;
7521 ereport(ERROR,
7522 (errcode(ERRCODE_UNDEFINED_OBJECT),
7523 errmsg("unrecognized configuration parameter \"%s\"",
7524 name)));
7525 }
7526 if (restrict_privileged &&
7527 (record->flags & GUC_SUPERUSER_ONLY) &&
7528 !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))
7529 ereport(ERROR,
7530 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
7531 errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"",
7532 name)));
7533
7534 switch (record->vartype)
7535 {
7536 case PGC_BOOL:
7537 return *((struct config_bool *) record)->variable ? "on" : "off";
7538
7539 case PGC_INT:
7540 snprintf(buffer, sizeof(buffer), "%d",
7541 *((struct config_int *) record)->variable);
7542 return buffer;
7543
7544 case PGC_REAL:
7545 snprintf(buffer, sizeof(buffer), "%g",
7546 *((struct config_real *) record)->variable);
7547 return buffer;
7548
7549 case PGC_STRING:
7550 return *((struct config_string *) record)->variable;
7551
7552 case PGC_ENUM:
7553 return config_enum_lookup_by_value((struct config_enum *) record,
7554 *((struct config_enum *) record)->variable);
7555 }
7556 return NULL;
7557}
7558
7559/*
7560 * Get the RESET value associated with the given option.
7561 *
7562 * Note: this is not re-entrant, due to use of static result buffer;
7563 * not to mention that a string variable could have its reset_val changed.
7564 * Beware of assuming the result value is good for very long.
7565 */
7566const char *
7567GetConfigOptionResetString(const char *name)
7568{
7569 struct config_generic *record;
7570 static char buffer[256];
7571
7572 record = find_option(name, false, ERROR);
7573 if (record == NULL)
7574 ereport(ERROR,
7575 (errcode(ERRCODE_UNDEFINED_OBJECT),
7576 errmsg("unrecognized configuration parameter \"%s\"", name)));
7577 if ((record->flags & GUC_SUPERUSER_ONLY) &&
7578 !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))
7579 ereport(ERROR,
7580 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
7581 errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"",
7582 name)));
7583
7584 switch (record->vartype)
7585 {
7586 case PGC_BOOL:
7587 return ((struct config_bool *) record)->reset_val ? "on" : "off";
7588
7589 case PGC_INT:
7590 snprintf(buffer, sizeof(buffer), "%d",
7591 ((struct config_int *) record)->reset_val);
7592 return buffer;
7593
7594 case PGC_REAL:
7595 snprintf(buffer, sizeof(buffer), "%g",
7596 ((struct config_real *) record)->reset_val);
7597 return buffer;
7598
7599 case PGC_STRING:
7600 return ((struct config_string *) record)->reset_val;
7601
7602 case PGC_ENUM:
7603 return config_enum_lookup_by_value((struct config_enum *) record,
7604 ((struct config_enum *) record)->reset_val);
7605 }
7606 return NULL;
7607}
7608
7609/*
7610 * Get the GUC flags associated with the given option.
7611 *
7612 * If the option doesn't exist, return 0 if missing_ok is true,
7613 * otherwise throw an ereport and don't return.
7614 */
7615int
7616GetConfigOptionFlags(const char *name, bool missing_ok)
7617{
7618 struct config_generic *record;
7619
7620 record = find_option(name, false, WARNING);
7621 if (record == NULL)
7622 {
7623 if (missing_ok)
7624 return 0;
7625 ereport(ERROR,
7626 (errcode(ERRCODE_UNDEFINED_OBJECT),
7627 errmsg("unrecognized configuration parameter \"%s\"",
7628 name)));
7629 }
7630 return record->flags;
7631}
7632
7633
7634/*
7635 * flatten_set_variable_args
7636 * Given a parsenode List as emitted by the grammar for SET,
7637 * convert to the flat string representation used by GUC.
7638 *
7639 * We need to be told the name of the variable the args are for, because
7640 * the flattening rules vary (ugh).
7641 *
7642 * The result is NULL if args is NIL (i.e., SET ... TO DEFAULT), otherwise
7643 * a palloc'd string.
7644 */
7645static char *
7646flatten_set_variable_args(const char *name, List *args)
7647{
7648 struct config_generic *record;
7649 int flags;
7650 StringInfoData buf;
7651 ListCell *l;
7652
7653 /* Fast path if just DEFAULT */
7654 if (args == NIL)
7655 return NULL;
7656
7657 /*
7658 * Get flags for the variable; if it's not known, use default flags.
7659 * (Caller might throw error later, but not our business to do so here.)
7660 */
7661 record = find_option(name, false, WARNING);
7662 if (record)
7663 flags = record->flags;
7664 else
7665 flags = 0;
7666
7667 /* Complain if list input and non-list variable */
7668 if ((flags & GUC_LIST_INPUT) == 0 &&
7669 list_length(args) != 1)
7670 ereport(ERROR,
7671 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7672 errmsg("SET %s takes only one argument", name)));
7673
7674 initStringInfo(&buf);
7675
7676 /*
7677 * Each list member may be a plain A_Const node, or an A_Const within a
7678 * TypeCast; the latter case is supported only for ConstInterval arguments
7679 * (for SET TIME ZONE).
7680 */
7681 foreach(l, args)
7682 {
7683 Node *arg = (Node *) lfirst(l);
7684 char *val;
7685 TypeName *typeName = NULL;
7686 A_Const *con;
7687
7688 if (l != list_head(args))
7689 appendStringInfoString(&buf, ", ");
7690
7691 if (IsA(arg, TypeCast))
7692 {
7693 TypeCast *tc = (TypeCast *) arg;
7694
7695 arg = tc->arg;
7696 typeName = tc->typeName;
7697 }
7698
7699 if (!IsA(arg, A_Const))
7700 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
7701 con = (A_Const *) arg;
7702
7703 switch (nodeTag(&con->val))
7704 {
7705 case T_Integer:
7706 appendStringInfo(&buf, "%d", intVal(&con->val));
7707 break;
7708 case T_Float:
7709 /* represented as a string, so just copy it */
7710 appendStringInfoString(&buf, strVal(&con->val));
7711 break;
7712 case T_String:
7713 val = strVal(&con->val);
7714 if (typeName != NULL)
7715 {
7716 /*
7717 * Must be a ConstInterval argument for TIME ZONE. Coerce
7718 * to interval and back to normalize the value and account
7719 * for any typmod.
7720 */
7721 Oid typoid;
7722 int32 typmod;
7723 Datum interval;
7724 char *intervalout;
7725
7726 typenameTypeIdAndMod(NULL, typeName, &typoid, &typmod);
7727 Assert(typoid == INTERVALOID);
7728
7729 interval =
7730 DirectFunctionCall3(interval_in,
7731 CStringGetDatum(val),
7732 ObjectIdGetDatum(InvalidOid),
7733 Int32GetDatum(typmod));
7734
7735 intervalout =
7736 DatumGetCString(DirectFunctionCall1(interval_out,
7737 interval));
7738 appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
7739 }
7740 else
7741 {
7742 /*
7743 * Plain string literal or identifier. For quote mode,
7744 * quote it if it's not a vanilla identifier.
7745 */
7746 if (flags & GUC_LIST_QUOTE)
7747 appendStringInfoString(&buf, quote_identifier(val));
7748 else
7749 appendStringInfoString(&buf, val);
7750 }
7751 break;
7752 default:
7753 elog(ERROR, "unrecognized node type: %d",
7754 (int) nodeTag(&con->val));
7755 break;
7756 }
7757 }
7758
7759 return buf.data;
7760}
7761
7762/*
7763 * Write updated configuration parameter values into a temporary file.
7764 * This function traverses the list of parameters and quotes the string
7765 * values before writing them.
7766 */
7767static void
7768write_auto_conf_file(int fd, const char *filename, ConfigVariable *head)
7769{
7770 StringInfoData buf;
7771 ConfigVariable *item;
7772
7773 initStringInfo(&buf);
7774
7775 /* Emit file header containing warning comment */
7776 appendStringInfoString(&buf, "# Do not edit this file manually!\n");
7777 appendStringInfoString(&buf, "# It will be overwritten by the ALTER SYSTEM command.\n");
7778
7779 errno = 0;
7780 if (write(fd, buf.data, buf.len) != buf.len)
7781 {
7782 /* if write didn't set errno, assume problem is no disk space */
7783 if (errno == 0)
7784 errno = ENOSPC;
7785 ereport(ERROR,
7786 (errcode_for_file_access(),
7787 errmsg("could not write to file \"%s\": %m", filename)));
7788 }
7789
7790 /* Emit each parameter, properly quoting the value */
7791 for (item = head; item != NULL; item = item->next)
7792 {
7793 char *escaped;
7794
7795 resetStringInfo(&buf);
7796
7797 appendStringInfoString(&buf, item->name);
7798 appendStringInfoString(&buf, " = '");
7799
7800 escaped = escape_single_quotes_ascii(item->value);
7801 if (!escaped)
7802 ereport(ERROR,
7803 (errcode(ERRCODE_OUT_OF_MEMORY),
7804 errmsg("out of memory")));
7805 appendStringInfoString(&buf, escaped);
7806 free(escaped);
7807
7808 appendStringInfoString(&buf, "'\n");
7809
7810 errno = 0;
7811 if (write(fd, buf.data, buf.len) != buf.len)
7812 {
7813 /* if write didn't set errno, assume problem is no disk space */
7814 if (errno == 0)
7815 errno = ENOSPC;
7816 ereport(ERROR,
7817 (errcode_for_file_access(),
7818 errmsg("could not write to file \"%s\": %m", filename)));
7819 }
7820 }
7821
7822 /* fsync before considering the write to be successful */
7823 if (pg_fsync(fd) != 0)
7824 ereport(ERROR,
7825 (errcode_for_file_access(),
7826 errmsg("could not fsync file \"%s\": %m", filename)));
7827
7828 pfree(buf.data);
7829}
7830
7831/*
7832 * Update the given list of configuration parameters, adding, replacing
7833 * or deleting the entry for item "name" (delete if "value" == NULL).
7834 */
7835static void
7836replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
7837 const char *name, const char *value)
7838{
7839 ConfigVariable *item,
7840 *next,
7841 *prev = NULL;
7842
7843 /*
7844 * Remove any existing match(es) for "name". Normally there'd be at most
7845 * one, but if external tools have modified the config file, there could
7846 * be more.
7847 */
7848 for (item = *head_p; item != NULL; item = next)
7849 {
7850 next = item->next;
7851 if (guc_name_compare(item->name, name) == 0)
7852 {
7853 /* found a match, delete it */
7854 if (prev)
7855 prev->next = next;
7856 else
7857 *head_p = next;
7858 if (next == NULL)
7859 *tail_p = prev;
7860
7861 pfree(item->name);
7862 pfree(item->value);
7863 pfree(item->filename);
7864 pfree(item);
7865 }
7866 else
7867 prev = item;
7868 }
7869
7870 /* Done if we're trying to delete it */
7871 if (value == NULL)
7872 return;
7873
7874 /* OK, append a new entry */
7875 item = palloc(sizeof *item);
7876 item->name = pstrdup(name);
7877 item->value = pstrdup(value);
7878 item->errmsg = NULL;
7879 item->filename = pstrdup(""); /* new item has no location */
7880 item->sourceline = 0;
7881 item->ignore = false;
7882 item->applied = false;
7883 item->next = NULL;
7884
7885 if (*head_p == NULL)
7886 *head_p = item;
7887 else
7888 (*tail_p)->next = item;
7889 *tail_p = item;
7890}
7891
7892
7893/*
7894 * Execute ALTER SYSTEM statement.
7895 *
7896 * Read the old PG_AUTOCONF_FILENAME file, merge in the new variable value,
7897 * and write out an updated file. If the command is ALTER SYSTEM RESET ALL,
7898 * we can skip reading the old file and just write an empty file.
7899 *
7900 * An LWLock is used to serialize updates of the configuration file.
7901 *
7902 * In case of an error, we leave the original automatic
7903 * configuration file (PG_AUTOCONF_FILENAME) intact.
7904 */
7905void
7906AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
7907{
7908 char *name;
7909 char *value;
7910 bool resetall = false;
7911 ConfigVariable *head = NULL;
7912 ConfigVariable *tail = NULL;
7913 volatile int Tmpfd;
7914 char AutoConfFileName[MAXPGPATH];
7915 char AutoConfTmpFileName[MAXPGPATH];
7916
7917 if (!superuser())
7918 ereport(ERROR,
7919 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
7920 (errmsg("must be superuser to execute ALTER SYSTEM command"))));
7921
7922 /*
7923 * Extract statement arguments
7924 */
7925 name = altersysstmt->setstmt->name;
7926
7927 switch (altersysstmt->setstmt->kind)
7928 {
7929 case VAR_SET_VALUE:
7930 value = ExtractSetVariableArgs(altersysstmt->setstmt);
7931 break;
7932
7933 case VAR_SET_DEFAULT:
7934 case VAR_RESET:
7935 value = NULL;
7936 break;
7937
7938 case VAR_RESET_ALL:
7939 value = NULL;
7940 resetall = true;
7941 break;
7942
7943 default:
7944 elog(ERROR, "unrecognized alter system stmt type: %d",
7945 altersysstmt->setstmt->kind);
7946 break;
7947 }
7948
7949 /*
7950 * Unless it's RESET_ALL, validate the target variable and value
7951 */
7952 if (!resetall)
7953 {
7954 struct config_generic *record;
7955
7956 record = find_option(name, false, ERROR);
7957 if (record == NULL)
7958 ereport(ERROR,
7959 (errcode(ERRCODE_UNDEFINED_OBJECT),
7960 errmsg("unrecognized configuration parameter \"%s\"",
7961 name)));
7962
7963 /*
7964 * Don't allow parameters that can't be set in configuration files to
7965 * be set in PG_AUTOCONF_FILENAME file.
7966 */
7967 if ((record->context == PGC_INTERNAL) ||
7968 (record->flags & GUC_DISALLOW_IN_FILE) ||
7969 (record->flags & GUC_DISALLOW_IN_AUTO_FILE))
7970 ereport(ERROR,
7971 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
7972 errmsg("parameter \"%s\" cannot be changed",
7973 name)));
7974
7975 /*
7976 * If a value is specified, verify that it's sane.
7977 */
7978 if (value)
7979 {
7980 union config_var_val newval;
7981 void *newextra = NULL;
7982
7983 /* Check that it's acceptable for the indicated parameter */
7984 if (!parse_and_validate_value(record, name, value,
7985 PGC_S_FILE, ERROR,
7986 &newval, &newextra))
7987 ereport(ERROR,
7988 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
7989 errmsg("invalid value for parameter \"%s\": \"%s\"",
7990 name, value)));
7991
7992 if (record->vartype == PGC_STRING && newval.stringval != NULL)
7993 free(newval.stringval);
7994 if (newextra)
7995 free(newextra);
7996
7997 /*
7998 * We must also reject values containing newlines, because the
7999 * grammar for config files doesn't support embedded newlines in
8000 * string literals.
8001 */
8002 if (strchr(value, '\n'))
8003 ereport(ERROR,
8004 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8005 errmsg("parameter value for ALTER SYSTEM must not contain a newline")));
8006 }
8007 }
8008
8009 /*
8010 * PG_AUTOCONF_FILENAME and its corresponding temporary file are always in
8011 * the data directory, so we can reference them by simple relative paths.
8012 */
8013 snprintf(AutoConfFileName, sizeof(AutoConfFileName), "%s",
8014 PG_AUTOCONF_FILENAME);
8015 snprintf(AutoConfTmpFileName, sizeof(AutoConfTmpFileName), "%s.%s",
8016 AutoConfFileName,
8017 "tmp");
8018
8019 /*
8020 * Only one backend is allowed to operate on PG_AUTOCONF_FILENAME at a
8021 * time. Use AutoFileLock to ensure that. We must hold the lock while
8022 * reading the old file contents.
8023 */
8024 LWLockAcquire(AutoFileLock, LW_EXCLUSIVE);
8025
8026 /*
8027 * If we're going to reset everything, then no need to open or parse the
8028 * old file. We'll just write out an empty list.
8029 */
8030 if (!resetall)
8031 {
8032 struct stat st;
8033
8034 if (stat(AutoConfFileName, &st) == 0)
8035 {
8036 /* open old file PG_AUTOCONF_FILENAME */
8037 FILE *infile;
8038
8039 infile = AllocateFile(AutoConfFileName, "r");
8040 if (infile == NULL)
8041 ereport(ERROR,
8042 (errcode_for_file_access(),
8043 errmsg("could not open file \"%s\": %m",
8044 AutoConfFileName)));
8045
8046 /* parse it */
8047 if (!ParseConfigFp(infile, AutoConfFileName, 0, LOG, &head, &tail))
8048 ereport(ERROR,
8049 (errcode(ERRCODE_CONFIG_FILE_ERROR),
8050 errmsg("could not parse contents of file \"%s\"",
8051 AutoConfFileName)));
8052
8053 FreeFile(infile);
8054 }
8055
8056 /*
8057 * Now, replace any existing entry with the new value, or add it if
8058 * not present.
8059 */
8060 replace_auto_config_value(&head, &tail, name, value);
8061 }
8062
8063 /*
8064 * To ensure crash safety, first write the new file data to a temp file,
8065 * then atomically rename it into place.
8066 *
8067 * If there is a temp file left over due to a previous crash, it's okay to
8068 * truncate and reuse it.
8069 */
8070 Tmpfd = BasicOpenFile(AutoConfTmpFileName,
8071 O_CREAT | O_RDWR | O_TRUNC);
8072 if (Tmpfd < 0)
8073 ereport(ERROR,
8074 (errcode_for_file_access(),
8075 errmsg("could not open file \"%s\": %m",
8076 AutoConfTmpFileName)));
8077
8078 /*
8079 * Use a TRY block to clean up the file if we fail. Since we need a TRY
8080 * block anyway, OK to use BasicOpenFile rather than OpenTransientFile.
8081 */
8082 PG_TRY();
8083 {
8084 /* Write and sync the new contents to the temporary file */
8085 write_auto_conf_file(Tmpfd, AutoConfTmpFileName, head);
8086
8087 /* Close before renaming; may be required on some platforms */
8088 close(Tmpfd);
8089 Tmpfd = -1;
8090
8091 /*
8092 * As the rename is atomic operation, if any problem occurs after this
8093 * at worst it can lose the parameters set by last ALTER SYSTEM
8094 * command.
8095 */
8096 durable_rename(AutoConfTmpFileName, AutoConfFileName, ERROR);
8097 }
8098 PG_CATCH();
8099 {
8100 /* Close file first, else unlink might fail on some platforms */
8101 if (Tmpfd >= 0)
8102 close(Tmpfd);
8103
8104 /* Unlink, but ignore any error */
8105 (void) unlink(AutoConfTmpFileName);
8106
8107 PG_RE_THROW();
8108 }
8109 PG_END_TRY();
8110
8111 FreeConfigVariables(head);
8112
8113 LWLockRelease(AutoFileLock);
8114}
8115
8116/*
8117 * SET command
8118 */
8119void
8120ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
8121{
8122 GucAction action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
8123
8124 /*
8125 * Workers synchronize these parameters at the start of the parallel
8126 * operation; then, we block SET during the operation.
8127 */
8128 if (IsInParallelMode())
8129 ereport(ERROR,
8130 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
8131 errmsg("cannot set parameters during a parallel operation")));
8132
8133 switch (stmt->kind)
8134 {
8135 case VAR_SET_VALUE:
8136 case VAR_SET_CURRENT:
8137 if (stmt->is_local)
8138 WarnNoTransactionBlock(isTopLevel, "SET LOCAL");
8139 (void) set_config_option(stmt->name,
8140 ExtractSetVariableArgs(stmt),
8141 (superuser() ? PGC_SUSET : PGC_USERSET),
8142 PGC_S_SESSION,
8143 action, true, 0, false);
8144 break;
8145 case VAR_SET_MULTI:
8146
8147 /*
8148 * Special-case SQL syntaxes. The TRANSACTION and SESSION
8149 * CHARACTERISTICS cases effectively set more than one variable
8150 * per statement. TRANSACTION SNAPSHOT only takes one argument,
8151 * but we put it here anyway since it's a special case and not
8152 * related to any GUC variable.
8153 */
8154 if (strcmp(stmt->name, "TRANSACTION") == 0)
8155 {
8156 ListCell *head;
8157
8158 WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
8159
8160 foreach(head, stmt->args)
8161 {
8162 DefElem *item = (DefElem *) lfirst(head);
8163
8164 if (strcmp(item->defname, "transaction_isolation") == 0)
8165 SetPGVariable("transaction_isolation",
8166 list_make1(item->arg), stmt->is_local);
8167 else if (strcmp(item->defname, "transaction_read_only") == 0)
8168 SetPGVariable("transaction_read_only",
8169 list_make1(item->arg), stmt->is_local);
8170 else if (strcmp(item->defname, "transaction_deferrable") == 0)
8171 SetPGVariable("transaction_deferrable",
8172 list_make1(item->arg), stmt->is_local);
8173 else
8174 elog(ERROR, "unexpected SET TRANSACTION element: %s",
8175 item->defname);
8176 }
8177 }
8178 else if (strcmp(stmt->name, "SESSION CHARACTERISTICS") == 0)
8179 {
8180 ListCell *head;
8181
8182 foreach(head, stmt->args)
8183 {
8184 DefElem *item = (DefElem *) lfirst(head);
8185
8186 if (strcmp(item->defname, "transaction_isolation") == 0)
8187 SetPGVariable("default_transaction_isolation",
8188 list_make1(item->arg), stmt->is_local);
8189 else if (strcmp(item->defname, "transaction_read_only") == 0)
8190 SetPGVariable("default_transaction_read_only",
8191 list_make1(item->arg), stmt->is_local);
8192 else if (strcmp(item->defname, "transaction_deferrable") == 0)
8193 SetPGVariable("default_transaction_deferrable",
8194 list_make1(item->arg), stmt->is_local);
8195 else
8196 elog(ERROR, "unexpected SET SESSION element: %s",
8197 item->defname);
8198 }
8199 }
8200 else if (strcmp(stmt->name, "TRANSACTION SNAPSHOT") == 0)
8201 {
8202 A_Const *con = linitial_node(A_Const, stmt->args);
8203
8204 if (stmt->is_local)
8205 ereport(ERROR,
8206 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8207 errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
8208
8209 WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
8210 Assert(nodeTag(&con->val) == T_String);
8211 ImportSnapshot(strVal(&con->val));
8212 }
8213 else
8214 elog(ERROR, "unexpected SET MULTI element: %s",
8215 stmt->name);
8216 break;
8217 case VAR_SET_DEFAULT:
8218 if (stmt->is_local)
8219 WarnNoTransactionBlock(isTopLevel, "SET LOCAL");
8220 /* fall through */
8221 case VAR_RESET:
8222 if (strcmp(stmt->name, "transaction_isolation") == 0)
8223 WarnNoTransactionBlock(isTopLevel, "RESET TRANSACTION");
8224
8225 (void) set_config_option(stmt->name,
8226 NULL,
8227 (superuser() ? PGC_SUSET : PGC_USERSET),
8228 PGC_S_SESSION,
8229 action, true, 0, false);
8230 break;
8231 case VAR_RESET_ALL:
8232 ResetAllOptions();
8233 break;
8234 }
8235}
8236
8237/*
8238 * Get the value to assign for a VariableSetStmt, or NULL if it's RESET.
8239 * The result is palloc'd.
8240 *
8241 * This is exported for use by actions such as ALTER ROLE SET.
8242 */
8243char *
8244ExtractSetVariableArgs(VariableSetStmt *stmt)
8245{
8246 switch (stmt->kind)
8247 {
8248 case VAR_SET_VALUE:
8249 return flatten_set_variable_args(stmt->name, stmt->args);
8250 case VAR_SET_CURRENT:
8251 return GetConfigOptionByName(stmt->name, NULL, false);
8252 default:
8253 return NULL;
8254 }
8255}
8256
8257/*
8258 * SetPGVariable - SET command exported as an easily-C-callable function.
8259 *
8260 * This provides access to SET TO value, as well as SET TO DEFAULT (expressed
8261 * by passing args == NIL), but not SET FROM CURRENT functionality.
8262 */
8263void
8264SetPGVariable(const char *name, List *args, bool is_local)
8265{
8266 char *argstring = flatten_set_variable_args(name, args);
8267
8268 /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
8269 (void) set_config_option(name,
8270 argstring,
8271 (superuser() ? PGC_SUSET : PGC_USERSET),
8272 PGC_S_SESSION,
8273 is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
8274 true, 0, false);
8275}
8276
8277/*
8278 * SET command wrapped as a SQL callable function.
8279 */
8280Datum
8281set_config_by_name(PG_FUNCTION_ARGS)
8282{
8283 char *name;
8284 char *value;
8285 char *new_value;
8286 bool is_local;
8287
8288 if (PG_ARGISNULL(0))
8289 ereport(ERROR,
8290 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
8291 errmsg("SET requires parameter name")));
8292
8293 /* Get the GUC variable name */
8294 name = TextDatumGetCString(PG_GETARG_DATUM(0));
8295
8296 /* Get the desired value or set to NULL for a reset request */
8297 if (PG_ARGISNULL(1))
8298 value = NULL;
8299 else
8300 value = TextDatumGetCString(PG_GETARG_DATUM(1));
8301
8302 /*
8303 * Get the desired state of is_local. Default to false if provided value
8304 * is NULL
8305 */
8306 if (PG_ARGISNULL(2))
8307 is_local = false;
8308 else
8309 is_local = PG_GETARG_BOOL(2);
8310
8311 /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
8312 (void) set_config_option(name,
8313 value,
8314 (superuser() ? PGC_SUSET : PGC_USERSET),
8315 PGC_S_SESSION,
8316 is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
8317 true, 0, false);
8318
8319 /* get the new current value */
8320 new_value = GetConfigOptionByName(name, NULL, false);
8321
8322 /* Convert return string to text */
8323 PG_RETURN_TEXT_P(cstring_to_text(new_value));
8324}
8325
8326
8327/*
8328 * Common code for DefineCustomXXXVariable subroutines: allocate the
8329 * new variable's config struct and fill in generic fields.
8330 */
8331static struct config_generic *
8332init_custom_variable(const char *name,
8333 const char *short_desc,
8334 const char *long_desc,
8335 GucContext context,
8336 int flags,
8337 enum config_type type,
8338 size_t sz)
8339{
8340 struct config_generic *gen;
8341
8342 /*
8343 * Only allow custom PGC_POSTMASTER variables to be created during shared
8344 * library preload; any later than that, we can't ensure that the value
8345 * doesn't change after startup. This is a fatal elog if it happens; just
8346 * erroring out isn't safe because we don't know what the calling loadable
8347 * module might already have hooked into.
8348 */
8349 if (context == PGC_POSTMASTER &&
8350 !process_shared_preload_libraries_in_progress)
8351 elog(FATAL, "cannot create PGC_POSTMASTER variables after startup");
8352
8353 /*
8354 * We can't support custom GUC_LIST_QUOTE variables, because the wrong
8355 * things would happen if such a variable were set or pg_dump'd when the
8356 * defining extension isn't loaded. Again, treat this as fatal because
8357 * the loadable module may be partly initialized already.
8358 */
8359 if (flags & GUC_LIST_QUOTE)
8360 elog(FATAL, "extensions cannot define GUC_LIST_QUOTE variables");
8361
8362 /*
8363 * Before pljava commit 398f3b876ed402bdaec8bc804f29e2be95c75139
8364 * (2015-12-15), two of that module's PGC_USERSET variables facilitated
8365 * trivial escalation to superuser privileges. Restrict the variables to
8366 * protect sites that have yet to upgrade pljava.
8367 */
8368 if (context == PGC_USERSET &&
8369 (strcmp(name, "pljava.classpath") == 0 ||
8370 strcmp(name, "pljava.vmoptions") == 0))
8371 context = PGC_SUSET;
8372
8373 gen = (struct config_generic *) guc_malloc(ERROR, sz);
8374 memset(gen, 0, sz);
8375
8376 gen->name = guc_strdup(ERROR, name);
8377 gen->context = context;
8378 gen->group = CUSTOM_OPTIONS;
8379 gen->short_desc = short_desc;
8380 gen->long_desc = long_desc;
8381 gen->flags = flags;
8382 gen->vartype = type;
8383
8384 return gen;
8385}
8386
8387/*
8388 * Common code for DefineCustomXXXVariable subroutines: insert the new
8389 * variable into the GUC variable array, replacing any placeholder.
8390 */
8391static void
8392define_custom_variable(struct config_generic *variable)
8393{
8394 const char *name = variable->name;
8395 const char **nameAddr = &name;
8396 struct config_string *pHolder;
8397 struct config_generic **res;
8398
8399 /*
8400 * See if there's a placeholder by the same name.
8401 */
8402 res = (struct config_generic **) bsearch((void *) &nameAddr,
8403 (void *) guc_variables,
8404 num_guc_variables,
8405 sizeof(struct config_generic *),
8406 guc_var_compare);
8407 if (res == NULL)
8408 {
8409 /*
8410 * No placeholder to replace, so we can just add it ... but first,
8411 * make sure it's initialized to its default value.
8412 */
8413 InitializeOneGUCOption(variable);
8414 add_guc_variable(variable, ERROR);
8415 return;
8416 }
8417
8418 /*
8419 * This better be a placeholder
8420 */
8421 if (((*res)->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
8422 ereport(ERROR,
8423 (errcode(ERRCODE_INTERNAL_ERROR),
8424 errmsg("attempt to redefine parameter \"%s\"", name)));
8425
8426 Assert((*res)->vartype == PGC_STRING);
8427 pHolder = (struct config_string *) (*res);
8428
8429 /*
8430 * First, set the variable to its default value. We must do this even
8431 * though we intend to immediately apply a new value, since it's possible
8432 * that the new value is invalid.
8433 */
8434 InitializeOneGUCOption(variable);
8435
8436 /*
8437 * Replace the placeholder. We aren't changing the name, so no re-sorting
8438 * is necessary
8439 */
8440 *res = variable;
8441
8442 /*
8443 * Assign the string value(s) stored in the placeholder to the real
8444 * variable. Essentially, we need to duplicate all the active and stacked
8445 * values, but with appropriate validation and datatype adjustment.
8446 *
8447 * If an assignment fails, we report a WARNING and keep going. We don't
8448 * want to throw ERROR for bad values, because it'd bollix the add-on
8449 * module that's presumably halfway through getting loaded. In such cases
8450 * the default or previous state will become active instead.
8451 */
8452
8453 /* First, apply the reset value if any */
8454 if (pHolder->reset_val)
8455 (void) set_config_option(name, pHolder->reset_val,
8456 pHolder->gen.reset_scontext,
8457 pHolder->gen.reset_source,
8458 GUC_ACTION_SET, true, WARNING, false);
8459 /* That should not have resulted in stacking anything */
8460 Assert(variable->stack == NULL);
8461
8462 /* Now, apply current and stacked values, in the order they were stacked */
8463 reapply_stacked_values(variable, pHolder, pHolder->gen.stack,
8464 *(pHolder->variable),
8465 pHolder->gen.scontext, pHolder->gen.source);
8466
8467 /* Also copy over any saved source-location information */
8468 if (pHolder->gen.sourcefile)
8469 set_config_sourcefile(name, pHolder->gen.sourcefile,
8470 pHolder->gen.sourceline);
8471
8472 /*
8473 * Free up as much as we conveniently can of the placeholder structure.
8474 * (This neglects any stack items, so it's possible for some memory to be
8475 * leaked. Since this can only happen once per session per variable, it
8476 * doesn't seem worth spending much code on.)
8477 */
8478 set_string_field(pHolder, pHolder->variable, NULL);
8479 set_string_field(pHolder, &pHolder->reset_val, NULL);
8480
8481 free(pHolder);
8482}
8483
8484/*
8485 * Recursive subroutine for define_custom_variable: reapply non-reset values
8486 *
8487 * We recurse so that the values are applied in the same order as originally.
8488 * At each recursion level, apply the upper-level value (passed in) in the
8489 * fashion implied by the stack entry.
8490 */
8491static void
8492reapply_stacked_values(struct config_generic *variable,
8493 struct config_string *pHolder,
8494 GucStack *stack,
8495 const char *curvalue,
8496 GucContext curscontext, GucSource cursource)
8497{
8498 const char *name = variable->name;
8499 GucStack *oldvarstack = variable->stack;
8500
8501 if (stack != NULL)
8502 {
8503 /* First, recurse, so that stack items are processed bottom to top */
8504 reapply_stacked_values(variable, pHolder, stack->prev,
8505 stack->prior.val.stringval,
8506 stack->scontext, stack->source);
8507
8508 /* See how to apply the passed-in value */
8509 switch (stack->state)
8510 {
8511 case GUC_SAVE:
8512 (void) set_config_option(name, curvalue,
8513 curscontext, cursource,
8514 GUC_ACTION_SAVE, true,
8515 WARNING, false);
8516 break;
8517
8518 case GUC_SET:
8519 (void) set_config_option(name, curvalue,
8520 curscontext, cursource,
8521 GUC_ACTION_SET, true,
8522 WARNING, false);
8523 break;
8524
8525 case GUC_LOCAL:
8526 (void) set_config_option(name, curvalue,
8527 curscontext, cursource,
8528 GUC_ACTION_LOCAL, true,
8529 WARNING, false);
8530 break;
8531
8532 case GUC_SET_LOCAL:
8533 /* first, apply the masked value as SET */
8534 (void) set_config_option(name, stack->masked.val.stringval,
8535 stack->masked_scontext, PGC_S_SESSION,
8536 GUC_ACTION_SET, true,
8537 WARNING, false);
8538 /* then apply the current value as LOCAL */
8539 (void) set_config_option(name, curvalue,
8540 curscontext, cursource,
8541 GUC_ACTION_LOCAL, true,
8542 WARNING, false);
8543 break;
8544 }
8545
8546 /* If we successfully made a stack entry, adjust its nest level */
8547 if (variable->stack != oldvarstack)
8548 variable->stack->nest_level = stack->nest_level;
8549 }
8550 else
8551 {
8552 /*
8553 * We are at the end of the stack. If the active/previous value is
8554 * different from the reset value, it must represent a previously
8555 * committed session value. Apply it, and then drop the stack entry
8556 * that set_config_option will have created under the impression that
8557 * this is to be just a transactional assignment. (We leak the stack
8558 * entry.)
8559 */
8560 if (curvalue != pHolder->reset_val ||
8561 curscontext != pHolder->gen.reset_scontext ||
8562 cursource != pHolder->gen.reset_source)
8563 {
8564 (void) set_config_option(name, curvalue,
8565 curscontext, cursource,
8566 GUC_ACTION_SET, true, WARNING, false);
8567 variable->stack = NULL;
8568 }
8569 }
8570}
8571
8572void
8573DefineCustomBoolVariable(const char *name,
8574 const char *short_desc,
8575 const char *long_desc,
8576 bool *valueAddr,
8577 bool bootValue,
8578 GucContext context,
8579 int flags,
8580 GucBoolCheckHook check_hook,
8581 GucBoolAssignHook assign_hook,
8582 GucShowHook show_hook)
8583{
8584 struct config_bool *var;
8585
8586 var = (struct config_bool *)
8587 init_custom_variable(name, short_desc, long_desc, context, flags,
8588 PGC_BOOL, sizeof(struct config_bool));
8589 var->variable = valueAddr;
8590 var->boot_val = bootValue;
8591 var->reset_val = bootValue;
8592 var->check_hook = check_hook;
8593 var->assign_hook = assign_hook;
8594 var->show_hook = show_hook;
8595 define_custom_variable(&var->gen);
8596}
8597
8598void
8599DefineCustomIntVariable(const char *name,
8600 const char *short_desc,
8601 const char *long_desc,
8602 int *valueAddr,
8603 int bootValue,
8604 int minValue,
8605 int maxValue,
8606 GucContext context,
8607 int flags,
8608 GucIntCheckHook check_hook,
8609 GucIntAssignHook assign_hook,
8610 GucShowHook show_hook)
8611{
8612 struct config_int *var;
8613
8614 var = (struct config_int *)
8615 init_custom_variable(name, short_desc, long_desc, context, flags,
8616 PGC_INT, sizeof(struct config_int));
8617 var->variable = valueAddr;
8618 var->boot_val = bootValue;
8619 var->reset_val = bootValue;
8620 var->min = minValue;
8621 var->max = maxValue;
8622 var->check_hook = check_hook;
8623 var->assign_hook = assign_hook;
8624 var->show_hook = show_hook;
8625 define_custom_variable(&var->gen);
8626}
8627
8628void
8629DefineCustomRealVariable(const char *name,
8630 const char *short_desc,
8631 const char *long_desc,
8632 double *valueAddr,
8633 double bootValue,
8634 double minValue,
8635 double maxValue,
8636 GucContext context,
8637 int flags,
8638 GucRealCheckHook check_hook,
8639 GucRealAssignHook assign_hook,
8640 GucShowHook show_hook)
8641{
8642 struct config_real *var;
8643
8644 var = (struct config_real *)
8645 init_custom_variable(name, short_desc, long_desc, context, flags,
8646 PGC_REAL, sizeof(struct config_real));
8647 var->variable = valueAddr;
8648 var->boot_val = bootValue;
8649 var->reset_val = bootValue;
8650 var->min = minValue;
8651 var->max = maxValue;
8652 var->check_hook = check_hook;
8653 var->assign_hook = assign_hook;
8654 var->show_hook = show_hook;
8655 define_custom_variable(&var->gen);
8656}
8657
8658void
8659DefineCustomStringVariable(const char *name,
8660 const char *short_desc,
8661 const char *long_desc,
8662 char **valueAddr,
8663 const char *bootValue,
8664 GucContext context,
8665 int flags,
8666 GucStringCheckHook check_hook,
8667 GucStringAssignHook assign_hook,
8668 GucShowHook show_hook)
8669{
8670 struct config_string *var;
8671
8672 var = (struct config_string *)
8673 init_custom_variable(name, short_desc, long_desc, context, flags,
8674 PGC_STRING, sizeof(struct config_string));
8675 var->variable = valueAddr;
8676 var->boot_val = bootValue;
8677 var->check_hook = check_hook;
8678 var->assign_hook = assign_hook;
8679 var->show_hook = show_hook;
8680 define_custom_variable(&var->gen);
8681}
8682
8683void
8684DefineCustomEnumVariable(const char *name,
8685 const char *short_desc,
8686 const char *long_desc,
8687 int *valueAddr,
8688 int bootValue,
8689 const struct config_enum_entry *options,
8690 GucContext context,
8691 int flags,
8692 GucEnumCheckHook check_hook,
8693 GucEnumAssignHook assign_hook,
8694 GucShowHook show_hook)
8695{
8696 struct config_enum *var;
8697
8698 var = (struct config_enum *)
8699 init_custom_variable(name, short_desc, long_desc, context, flags,
8700 PGC_ENUM, sizeof(struct config_enum));
8701 var->variable = valueAddr;
8702 var->boot_val = bootValue;
8703 var->reset_val = bootValue;
8704 var->options = options;
8705 var->check_hook = check_hook;
8706 var->assign_hook = assign_hook;
8707 var->show_hook = show_hook;
8708 define_custom_variable(&var->gen);
8709}
8710
8711void
8712EmitWarningsOnPlaceholders(const char *className)
8713{
8714 int classLen = strlen(className);
8715 int i;
8716
8717 for (i = 0; i < num_guc_variables; i++)
8718 {
8719 struct config_generic *var = guc_variables[i];
8720
8721 if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
8722 strncmp(className, var->name, classLen) == 0 &&
8723 var->name[classLen] == GUC_QUALIFIER_SEPARATOR)
8724 {
8725 ereport(WARNING,
8726 (errcode(ERRCODE_UNDEFINED_OBJECT),
8727 errmsg("unrecognized configuration parameter \"%s\"",
8728 var->name)));
8729 }
8730 }
8731}
8732
8733
8734/*
8735 * SHOW command
8736 */
8737void
8738GetPGVariable(const char *name, DestReceiver *dest)
8739{
8740 if (guc_name_compare(name, "all") == 0)
8741 ShowAllGUCConfig(dest);
8742 else
8743 ShowGUCConfigOption(name, dest);
8744}
8745
8746TupleDesc
8747GetPGVariableResultDesc(const char *name)
8748{
8749 TupleDesc tupdesc;
8750
8751 if (guc_name_compare(name, "all") == 0)
8752 {
8753 /* need a tuple descriptor representing three TEXT columns */
8754 tupdesc = CreateTemplateTupleDesc(3);
8755 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
8756 TEXTOID, -1, 0);
8757 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
8758 TEXTOID, -1, 0);
8759 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
8760 TEXTOID, -1, 0);
8761 }
8762 else
8763 {
8764 const char *varname;
8765
8766 /* Get the canonical spelling of name */
8767 (void) GetConfigOptionByName(name, &varname, false);
8768
8769 /* need a tuple descriptor representing a single TEXT column */
8770 tupdesc = CreateTemplateTupleDesc(1);
8771 TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
8772 TEXTOID, -1, 0);
8773 }
8774 return tupdesc;
8775}
8776
8777
8778/*
8779 * SHOW command
8780 */
8781static void
8782ShowGUCConfigOption(const char *name, DestReceiver *dest)
8783{
8784 TupOutputState *tstate;
8785 TupleDesc tupdesc;
8786 const char *varname;
8787 char *value;
8788
8789 /* Get the value and canonical spelling of name */
8790 value = GetConfigOptionByName(name, &varname, false);
8791
8792 /* need a tuple descriptor representing a single TEXT column */
8793 tupdesc = CreateTemplateTupleDesc(1);
8794 TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, varname,
8795 TEXTOID, -1, 0);
8796
8797 /* prepare for projection of tuples */
8798 tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
8799
8800 /* Send it */
8801 do_text_output_oneline(tstate, value);
8802
8803 end_tup_output(tstate);
8804}
8805
8806/*
8807 * SHOW ALL command
8808 */
8809static void
8810ShowAllGUCConfig(DestReceiver *dest)
8811{
8812 int i;
8813 TupOutputState *tstate;
8814 TupleDesc tupdesc;
8815 Datum values[3];
8816 bool isnull[3] = {false, false, false};
8817
8818 /* need a tuple descriptor representing three TEXT columns */
8819 tupdesc = CreateTemplateTupleDesc(3);
8820 TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "name",
8821 TEXTOID, -1, 0);
8822 TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "setting",
8823 TEXTOID, -1, 0);
8824 TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "description",
8825 TEXTOID, -1, 0);
8826
8827 /* prepare for projection of tuples */
8828 tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
8829
8830 for (i = 0; i < num_guc_variables; i++)
8831 {
8832 struct config_generic *conf = guc_variables[i];
8833 char *setting;
8834
8835 if ((conf->flags & GUC_NO_SHOW_ALL) ||
8836 ((conf->flags & GUC_SUPERUSER_ONLY) &&
8837 !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)))
8838 continue;
8839
8840 /* assign to the values array */
8841 values[0] = PointerGetDatum(cstring_to_text(conf->name));
8842
8843 setting = _ShowOption(conf, true);
8844 if (setting)
8845 {
8846 values[1] = PointerGetDatum(cstring_to_text(setting));
8847 isnull[1] = false;
8848 }
8849 else
8850 {
8851 values[1] = PointerGetDatum(NULL);
8852 isnull[1] = true;
8853 }
8854
8855 values[2] = PointerGetDatum(cstring_to_text(conf->short_desc));
8856
8857 /* send it to dest */
8858 do_tup_output(tstate, values, isnull);
8859
8860 /* clean up */
8861 pfree(DatumGetPointer(values[0]));
8862 if (setting)
8863 {
8864 pfree(setting);
8865 pfree(DatumGetPointer(values[1]));
8866 }
8867 pfree(DatumGetPointer(values[2]));
8868 }
8869
8870 end_tup_output(tstate);
8871}
8872
8873/*
8874 * Returns an array of modified GUC options to show in EXPLAIN. Only options
8875 * related to query planning (marked with GUC_EXPLAIN), with values different
8876 * from built-in defaults.
8877 */
8878struct config_generic **
8879get_explain_guc_options(int *num)
8880{
8881 int i;
8882 struct config_generic **result;
8883
8884 *num = 0;
8885
8886 /*
8887 * Allocate enough space to fit all GUC_EXPLAIN options. We may not need
8888 * all the space, but there are fairly few such options so we don't waste
8889 * a lot of memory.
8890 */
8891 result = palloc(sizeof(struct config_generic *) * num_guc_explain_variables);
8892
8893 for (i = 0; i < num_guc_variables; i++)
8894 {
8895 bool modified;
8896 struct config_generic *conf = guc_variables[i];
8897
8898 /* return only options visible to the user */
8899 if ((conf->flags & GUC_NO_SHOW_ALL) ||
8900 ((conf->flags & GUC_SUPERUSER_ONLY) &&
8901 !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)))
8902 continue;
8903
8904 /* only parameters explicitly marked for inclusion in explain */
8905 if (!(conf->flags & GUC_EXPLAIN))
8906 continue;
8907
8908 /* return only options that were modified (w.r.t. config file) */
8909 modified = false;
8910
8911 switch (conf->vartype)
8912 {
8913 case PGC_BOOL:
8914 {
8915 struct config_bool *lconf = (struct config_bool *) conf;
8916
8917 modified = (lconf->boot_val != *(lconf->variable));
8918 }
8919 break;
8920
8921 case PGC_INT:
8922 {
8923 struct config_int *lconf = (struct config_int *) conf;
8924
8925 modified = (lconf->boot_val != *(lconf->variable));
8926 }
8927 break;
8928
8929 case PGC_REAL:
8930 {
8931 struct config_real *lconf = (struct config_real *) conf;
8932
8933 modified = (lconf->boot_val != *(lconf->variable));
8934 }
8935 break;
8936
8937 case PGC_STRING:
8938 {
8939 struct config_string *lconf = (struct config_string *) conf;
8940
8941 modified = (strcmp(lconf->boot_val, *(lconf->variable)) != 0);
8942 }
8943 break;
8944
8945 case PGC_ENUM:
8946 {
8947 struct config_enum *lconf = (struct config_enum *) conf;
8948
8949 modified = (lconf->boot_val != *(lconf->variable));
8950 }
8951 break;
8952
8953 default:
8954 elog(ERROR, "unexpected GUC type: %d", conf->vartype);
8955 }
8956
8957 /* skip GUC variables that match the built-in default */
8958 if (!modified)
8959 continue;
8960
8961 /* assign to the values array */
8962 result[*num] = conf;
8963 *num = *num + 1;
8964
8965 Assert(*num <= num_guc_explain_variables);
8966 }
8967
8968 return result;
8969}
8970
8971/*
8972 * Return GUC variable value by name; optionally return canonical form of
8973 * name. If the GUC is unset, then throw an error unless missing_ok is true,
8974 * in which case return NULL. Return value is palloc'd (but *varname isn't).
8975 */
8976char *
8977GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
8978{
8979 struct config_generic *record;
8980
8981 record = find_option(name, false, ERROR);
8982 if (record == NULL)
8983 {
8984 if (missing_ok)
8985 {
8986 if (varname)
8987 *varname = NULL;
8988 return NULL;
8989 }
8990
8991 ereport(ERROR,
8992 (errcode(ERRCODE_UNDEFINED_OBJECT),
8993 errmsg("unrecognized configuration parameter \"%s\"", name)));
8994 }
8995
8996 if ((record->flags & GUC_SUPERUSER_ONLY) &&
8997 !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))
8998 ereport(ERROR,
8999 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
9000 errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"",
9001 name)));
9002
9003 if (varname)
9004 *varname = record->name;
9005
9006 return _ShowOption(record, true);
9007}
9008
9009/*
9010 * Return GUC variable value by variable number; optionally return canonical
9011 * form of name. Return value is palloc'd.
9012 */
9013void
9014GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
9015{
9016 char buffer[256];
9017 struct config_generic *conf;
9018
9019 /* check requested variable number valid */
9020 Assert((varnum >= 0) && (varnum < num_guc_variables));
9021
9022 conf = guc_variables[varnum];
9023
9024 if (noshow)
9025 {
9026 if ((conf->flags & GUC_NO_SHOW_ALL) ||
9027 ((conf->flags & GUC_SUPERUSER_ONLY) &&
9028 !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)))
9029 *noshow = true;
9030 else
9031 *noshow = false;
9032 }
9033
9034 /* first get the generic attributes */
9035
9036 /* name */
9037 values[0] = conf->name;
9038
9039 /* setting: use _ShowOption in order to avoid duplicating the logic */
9040 values[1] = _ShowOption(conf, false);
9041
9042 /* unit, if any (NULL is fine) */
9043 values[2] = get_config_unit_name(conf->flags);
9044
9045 /* group */
9046 values[3] = _(config_group_names[conf->group]);
9047
9048 /* short_desc */
9049 values[4] = _(conf->short_desc);
9050
9051 /* extra_desc */
9052 values[5] = _(conf->long_desc);
9053
9054 /* context */
9055 values[6] = GucContext_Names[conf->context];
9056
9057 /* vartype */
9058 values[7] = config_type_names[conf->vartype];
9059
9060 /* source */
9061 values[8] = GucSource_Names[conf->source];
9062
9063 /* now get the type specific attributes */
9064 switch (conf->vartype)
9065 {
9066 case PGC_BOOL:
9067 {
9068 struct config_bool *lconf = (struct config_bool *) conf;
9069
9070 /* min_val */
9071 values[9] = NULL;
9072
9073 /* max_val */
9074 values[10] = NULL;
9075
9076 /* enumvals */
9077 values[11] = NULL;
9078
9079 /* boot_val */
9080 values[12] = pstrdup(lconf->boot_val ? "on" : "off");
9081
9082 /* reset_val */
9083 values[13] = pstrdup(lconf->reset_val ? "on" : "off");
9084 }
9085 break;
9086
9087 case PGC_INT:
9088 {
9089 struct config_int *lconf = (struct config_int *) conf;
9090
9091 /* min_val */
9092 snprintf(buffer, sizeof(buffer), "%d", lconf->min);
9093 values[9] = pstrdup(buffer);
9094
9095 /* max_val */
9096 snprintf(buffer, sizeof(buffer), "%d", lconf->max);
9097 values[10] = pstrdup(buffer);
9098
9099 /* enumvals */
9100 values[11] = NULL;
9101
9102 /* boot_val */
9103 snprintf(buffer, sizeof(buffer), "%d", lconf->boot_val);
9104 values[12] = pstrdup(buffer);
9105
9106 /* reset_val */
9107 snprintf(buffer, sizeof(buffer), "%d", lconf->reset_val);
9108 values[13] = pstrdup(buffer);
9109 }
9110 break;
9111
9112 case PGC_REAL:
9113 {
9114 struct config_real *lconf = (struct config_real *) conf;
9115
9116 /* min_val */
9117 snprintf(buffer, sizeof(buffer), "%g", lconf->min);
9118 values[9] = pstrdup(buffer);
9119
9120 /* max_val */
9121 snprintf(buffer, sizeof(buffer), "%g", lconf->max);
9122 values[10] = pstrdup(buffer);
9123
9124 /* enumvals */
9125 values[11] = NULL;
9126
9127 /* boot_val */
9128 snprintf(buffer, sizeof(buffer), "%g", lconf->boot_val);
9129 values[12] = pstrdup(buffer);
9130
9131 /* reset_val */
9132 snprintf(buffer, sizeof(buffer), "%g", lconf->reset_val);
9133 values[13] = pstrdup(buffer);
9134 }
9135 break;
9136
9137 case PGC_STRING:
9138 {
9139 struct config_string *lconf = (struct config_string *) conf;
9140
9141 /* min_val */
9142 values[9] = NULL;
9143
9144 /* max_val */
9145 values[10] = NULL;
9146
9147 /* enumvals */
9148 values[11] = NULL;
9149
9150 /* boot_val */
9151 if (lconf->boot_val == NULL)
9152 values[12] = NULL;
9153 else
9154 values[12] = pstrdup(lconf->boot_val);
9155
9156 /* reset_val */
9157 if (lconf->reset_val == NULL)
9158 values[13] = NULL;
9159 else
9160 values[13] = pstrdup(lconf->reset_val);
9161 }
9162 break;
9163
9164 case PGC_ENUM:
9165 {
9166 struct config_enum *lconf = (struct config_enum *) conf;
9167
9168 /* min_val */
9169 values[9] = NULL;
9170
9171 /* max_val */
9172 values[10] = NULL;
9173
9174 /* enumvals */
9175
9176 /*
9177 * NOTE! enumvals with double quotes in them are not
9178 * supported!
9179 */
9180 values[11] = config_enum_get_options((struct config_enum *) conf,
9181 "{\"", "\"}", "\",\"");
9182
9183 /* boot_val */
9184 values[12] = pstrdup(config_enum_lookup_by_value(lconf,
9185 lconf->boot_val));
9186
9187 /* reset_val */
9188 values[13] = pstrdup(config_enum_lookup_by_value(lconf,
9189 lconf->reset_val));
9190 }
9191 break;
9192
9193 default:
9194 {
9195 /*
9196 * should never get here, but in case we do, set 'em to NULL
9197 */
9198
9199 /* min_val */
9200 values[9] = NULL;
9201
9202 /* max_val */
9203 values[10] = NULL;
9204
9205 /* enumvals */
9206 values[11] = NULL;
9207
9208 /* boot_val */
9209 values[12] = NULL;
9210
9211 /* reset_val */
9212 values[13] = NULL;
9213 }
9214 break;
9215 }
9216
9217 /*
9218 * If the setting came from a config file, set the source location. For
9219 * security reasons, we don't show source file/line number for
9220 * insufficiently-privileged users.
9221 */
9222 if (conf->source == PGC_S_FILE &&
9223 is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))
9224 {
9225 values[14] = conf->sourcefile;
9226 snprintf(buffer, sizeof(buffer), "%d", conf->sourceline);
9227 values[15] = pstrdup(buffer);
9228 }
9229 else
9230 {
9231 values[14] = NULL;
9232 values[15] = NULL;
9233 }
9234
9235 values[16] = (conf->status & GUC_PENDING_RESTART) ? "t" : "f";
9236}
9237
9238/*
9239 * Return the total number of GUC variables
9240 */
9241int
9242GetNumConfigOptions(void)
9243{
9244 return num_guc_variables;
9245}
9246
9247/*
9248 * show_config_by_name - equiv to SHOW X command but implemented as
9249 * a function.
9250 */
9251Datum
9252show_config_by_name(PG_FUNCTION_ARGS)
9253{
9254 char *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
9255 char *varval;
9256
9257 /* Get the value */
9258 varval = GetConfigOptionByName(varname, NULL, false);
9259
9260 /* Convert to text */
9261 PG_RETURN_TEXT_P(cstring_to_text(varval));
9262}
9263
9264/*
9265 * show_config_by_name_missing_ok - equiv to SHOW X command but implemented as
9266 * a function. If X does not exist, suppress the error and just return NULL
9267 * if missing_ok is true.
9268 */
9269Datum
9270show_config_by_name_missing_ok(PG_FUNCTION_ARGS)
9271{
9272 char *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
9273 bool missing_ok = PG_GETARG_BOOL(1);
9274 char *varval;
9275
9276 /* Get the value */
9277 varval = GetConfigOptionByName(varname, NULL, missing_ok);
9278
9279 /* return NULL if no such variable */
9280 if (varval == NULL)
9281 PG_RETURN_NULL();
9282
9283 /* Convert to text */
9284 PG_RETURN_TEXT_P(cstring_to_text(varval));
9285}
9286
9287/*
9288 * show_all_settings - equiv to SHOW ALL command but implemented as
9289 * a Table Function.
9290 */
9291#define NUM_PG_SETTINGS_ATTS 17
9292
9293Datum
9294show_all_settings(PG_FUNCTION_ARGS)
9295{
9296 FuncCallContext *funcctx;
9297 TupleDesc tupdesc;
9298 int call_cntr;
9299 int max_calls;
9300 AttInMetadata *attinmeta;
9301 MemoryContext oldcontext;
9302
9303 /* stuff done only on the first call of the function */
9304 if (SRF_IS_FIRSTCALL())
9305 {
9306 /* create a function context for cross-call persistence */
9307 funcctx = SRF_FIRSTCALL_INIT();
9308
9309 /*
9310 * switch to memory context appropriate for multiple function calls
9311 */
9312 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
9313
9314 /*
9315 * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
9316 * of the appropriate types
9317 */
9318 tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS);
9319 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
9320 TEXTOID, -1, 0);
9321 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
9322 TEXTOID, -1, 0);
9323 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit",
9324 TEXTOID, -1, 0);
9325 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category",
9326 TEXTOID, -1, 0);
9327 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc",
9328 TEXTOID, -1, 0);
9329 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc",
9330 TEXTOID, -1, 0);
9331 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context",
9332 TEXTOID, -1, 0);
9333 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype",
9334 TEXTOID, -1, 0);
9335 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source",
9336 TEXTOID, -1, 0);
9337 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val",
9338 TEXTOID, -1, 0);
9339 TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
9340 TEXTOID, -1, 0);
9341 TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
9342 TEXTARRAYOID, -1, 0);
9343 TupleDescInitEntry(tupdesc, (AttrNumber) 13, "boot_val",
9344 TEXTOID, -1, 0);
9345 TupleDescInitEntry(tupdesc, (AttrNumber) 14, "reset_val",
9346 TEXTOID, -1, 0);
9347 TupleDescInitEntry(tupdesc, (AttrNumber) 15, "sourcefile",
9348 TEXTOID, -1, 0);
9349 TupleDescInitEntry(tupdesc, (AttrNumber) 16, "sourceline",
9350 INT4OID, -1, 0);
9351 TupleDescInitEntry(tupdesc, (AttrNumber) 17, "pending_restart",
9352 BOOLOID, -1, 0);
9353
9354 /*
9355 * Generate attribute metadata needed later to produce tuples from raw
9356 * C strings
9357 */
9358 attinmeta = TupleDescGetAttInMetadata(tupdesc);
9359 funcctx->attinmeta = attinmeta;
9360
9361 /* total number of tuples to be returned */
9362 funcctx->max_calls = GetNumConfigOptions();
9363
9364 MemoryContextSwitchTo(oldcontext);
9365 }
9366
9367 /* stuff done on every call of the function */
9368 funcctx = SRF_PERCALL_SETUP();
9369
9370 call_cntr = funcctx->call_cntr;
9371 max_calls = funcctx->max_calls;
9372 attinmeta = funcctx->attinmeta;
9373
9374 if (call_cntr < max_calls) /* do when there is more left to send */
9375 {
9376 char *values[NUM_PG_SETTINGS_ATTS];
9377 bool noshow;
9378 HeapTuple tuple;
9379 Datum result;
9380
9381 /*
9382 * Get the next visible GUC variable name and value
9383 */
9384 do
9385 {
9386 GetConfigOptionByNum(call_cntr, (const char **) values, &noshow);
9387 if (noshow)
9388 {
9389 /* bump the counter and get the next config setting */
9390 call_cntr = ++funcctx->call_cntr;
9391
9392 /* make sure we haven't gone too far now */
9393 if (call_cntr >= max_calls)
9394 SRF_RETURN_DONE(funcctx);
9395 }
9396 } while (noshow);
9397
9398 /* build a tuple */
9399 tuple = BuildTupleFromCStrings(attinmeta, values);
9400
9401 /* make the tuple into a datum */
9402 result = HeapTupleGetDatum(tuple);
9403
9404 SRF_RETURN_NEXT(funcctx, result);
9405 }
9406 else
9407 {
9408 /* do when there is no more left */
9409 SRF_RETURN_DONE(funcctx);
9410 }
9411}
9412
9413/*
9414 * show_all_file_settings
9415 *
9416 * Returns a table of all parameter settings in all configuration files
9417 * which includes the config file pathname, the line number, a sequence number
9418 * indicating the order in which the settings were encountered, the parameter
9419 * name and value, a bool showing if the value could be applied, and possibly
9420 * an associated error message. (For problems such as syntax errors, the
9421 * parameter name/value might be NULL.)
9422 *
9423 * Note: no filtering is done here, instead we depend on the GRANT system
9424 * to prevent unprivileged users from accessing this function or the view
9425 * built on top of it.
9426 */
9427Datum
9428show_all_file_settings(PG_FUNCTION_ARGS)
9429{
9430#define NUM_PG_FILE_SETTINGS_ATTS 7
9431 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
9432 TupleDesc tupdesc;
9433 Tuplestorestate *tupstore;
9434 ConfigVariable *conf;
9435 int seqno;
9436 MemoryContext per_query_ctx;
9437 MemoryContext oldcontext;
9438
9439 /* Check to see if caller supports us returning a tuplestore */
9440 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
9441 ereport(ERROR,
9442 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9443 errmsg("set-valued function called in context that cannot accept a set")));
9444 if (!(rsinfo->allowedModes & SFRM_Materialize))
9445 ereport(ERROR,
9446 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9447 errmsg("materialize mode required, but it is not " \
9448 "allowed in this context")));
9449
9450 /* Scan the config files using current context as workspace */
9451 conf = ProcessConfigFileInternal(PGC_SIGHUP, false, DEBUG3);
9452
9453 /* Switch into long-lived context to construct returned data structures */
9454 per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
9455 oldcontext = MemoryContextSwitchTo(per_query_ctx);
9456
9457 /* Build a tuple descriptor for our result type */
9458 tupdesc = CreateTemplateTupleDesc(NUM_PG_FILE_SETTINGS_ATTS);
9459 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "sourcefile",
9460 TEXTOID, -1, 0);
9461 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "sourceline",
9462 INT4OID, -1, 0);
9463 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "seqno",
9464 INT4OID, -1, 0);
9465 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "name",
9466 TEXTOID, -1, 0);
9467 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "setting",
9468 TEXTOID, -1, 0);
9469 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "applied",
9470 BOOLOID, -1, 0);
9471 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "error",
9472 TEXTOID, -1, 0);
9473
9474 /* Build a tuplestore to return our results in */
9475 tupstore = tuplestore_begin_heap(true, false, work_mem);
9476 rsinfo->returnMode = SFRM_Materialize;
9477 rsinfo->setResult = tupstore;
9478 rsinfo->setDesc = tupdesc;
9479
9480 /* The rest can be done in short-lived context */
9481 MemoryContextSwitchTo(oldcontext);
9482
9483 /* Process the results and create a tuplestore */
9484 for (seqno = 1; conf != NULL; conf = conf->next, seqno++)
9485 {
9486 Datum values[NUM_PG_FILE_SETTINGS_ATTS];
9487 bool nulls[NUM_PG_FILE_SETTINGS_ATTS];
9488
9489 memset(values, 0, sizeof(values));
9490 memset(nulls, 0, sizeof(nulls));
9491
9492 /* sourcefile */
9493 if (conf->filename)
9494 values[0] = PointerGetDatum(cstring_to_text(conf->filename));
9495 else
9496 nulls[0] = true;
9497
9498 /* sourceline (not meaningful if no sourcefile) */
9499 if (conf->filename)
9500 values[1] = Int32GetDatum(conf->sourceline);
9501 else
9502 nulls[1] = true;
9503
9504 /* seqno */
9505 values[2] = Int32GetDatum(seqno);
9506
9507 /* name */
9508 if (conf->name)
9509 values[3] = PointerGetDatum(cstring_to_text(conf->name));
9510 else
9511 nulls[3] = true;
9512
9513 /* setting */
9514 if (conf->value)
9515 values[4] = PointerGetDatum(cstring_to_text(conf->value));
9516 else
9517 nulls[4] = true;
9518
9519 /* applied */
9520 values[5] = BoolGetDatum(conf->applied);
9521
9522 /* error */
9523 if (conf->errmsg)
9524 values[6] = PointerGetDatum(cstring_to_text(conf->errmsg));
9525 else
9526 nulls[6] = true;
9527
9528 /* shove row into tuplestore */
9529 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
9530 }
9531
9532 tuplestore_donestoring(tupstore);
9533
9534 return (Datum) 0;
9535}
9536
9537static char *
9538_ShowOption(struct config_generic *record, bool use_units)
9539{
9540 char buffer[256];
9541 const char *val;
9542
9543 switch (record->vartype)
9544 {
9545 case PGC_BOOL:
9546 {
9547 struct config_bool *conf = (struct config_bool *) record;
9548
9549 if (conf->show_hook)
9550 val = conf->show_hook();
9551 else
9552 val = *conf->variable ? "on" : "off";
9553 }
9554 break;
9555
9556 case PGC_INT:
9557 {
9558 struct config_int *conf = (struct config_int *) record;
9559
9560 if (conf->show_hook)
9561 val = conf->show_hook();
9562 else
9563 {
9564 /*
9565 * Use int64 arithmetic to avoid overflows in units
9566 * conversion.
9567 */
9568 int64 result = *conf->variable;
9569 const char *unit;
9570
9571 if (use_units && result > 0 && (record->flags & GUC_UNIT))
9572 convert_int_from_base_unit(result,
9573 record->flags & GUC_UNIT,
9574 &result, &unit);
9575 else
9576 unit = "";
9577
9578 snprintf(buffer, sizeof(buffer), INT64_FORMAT "%s",
9579 result, unit);
9580 val = buffer;
9581 }
9582 }
9583 break;
9584
9585 case PGC_REAL:
9586 {
9587 struct config_real *conf = (struct config_real *) record;
9588
9589 if (conf->show_hook)
9590 val = conf->show_hook();
9591 else
9592 {
9593 double result = *conf->variable;
9594 const char *unit;
9595
9596 if (use_units && result > 0 && (record->flags & GUC_UNIT))
9597 convert_real_from_base_unit(result,
9598 record->flags & GUC_UNIT,
9599 &result, &unit);
9600 else
9601 unit = "";
9602
9603 snprintf(buffer, sizeof(buffer), "%g%s",
9604 result, unit);
9605 val = buffer;
9606 }
9607 }
9608 break;
9609
9610 case PGC_STRING:
9611 {
9612 struct config_string *conf = (struct config_string *) record;
9613
9614 if (conf->show_hook)
9615 val = conf->show_hook();
9616 else if (*conf->variable && **conf->variable)
9617 val = *conf->variable;
9618 else
9619 val = "";
9620 }
9621 break;
9622
9623 case PGC_ENUM:
9624 {
9625 struct config_enum *conf = (struct config_enum *) record;
9626
9627 if (conf->show_hook)
9628 val = conf->show_hook();
9629 else
9630 val = config_enum_lookup_by_value(conf, *conf->variable);
9631 }
9632 break;
9633
9634 default:
9635 /* just to keep compiler quiet */
9636 val = "???";
9637 break;
9638 }
9639
9640 return pstrdup(val);
9641}
9642
9643
9644#ifdef EXEC_BACKEND
9645
9646/*
9647 * These routines dump out all non-default GUC options into a binary
9648 * file that is read by all exec'ed backends. The format is:
9649 *
9650 * variable name, string, null terminated
9651 * variable value, string, null terminated
9652 * variable sourcefile, string, null terminated (empty if none)
9653 * variable sourceline, integer
9654 * variable source, integer
9655 * variable scontext, integer
9656 */
9657static void
9658write_one_nondefault_variable(FILE *fp, struct config_generic *gconf)
9659{
9660 if (gconf->source == PGC_S_DEFAULT)
9661 return;
9662
9663 fprintf(fp, "%s", gconf->name);
9664 fputc(0, fp);
9665
9666 switch (gconf->vartype)
9667 {
9668 case PGC_BOOL:
9669 {
9670 struct config_bool *conf = (struct config_bool *) gconf;
9671
9672 if (*conf->variable)
9673 fprintf(fp, "true");
9674 else
9675 fprintf(fp, "false");
9676 }
9677 break;
9678
9679 case PGC_INT:
9680 {
9681 struct config_int *conf = (struct config_int *) gconf;
9682
9683 fprintf(fp, "%d", *conf->variable);
9684 }
9685 break;
9686
9687 case PGC_REAL:
9688 {
9689 struct config_real *conf = (struct config_real *) gconf;
9690
9691 fprintf(fp, "%.17g", *conf->variable);
9692 }
9693 break;
9694
9695 case PGC_STRING:
9696 {
9697 struct config_string *conf = (struct config_string *) gconf;
9698
9699 fprintf(fp, "%s", *conf->variable);
9700 }
9701 break;
9702
9703 case PGC_ENUM:
9704 {
9705 struct config_enum *conf = (struct config_enum *) gconf;
9706
9707 fprintf(fp, "%s",
9708 config_enum_lookup_by_value(conf, *conf->variable));
9709 }
9710 break;
9711 }
9712
9713 fputc(0, fp);
9714
9715 if (gconf->sourcefile)
9716 fprintf(fp, "%s", gconf->sourcefile);
9717 fputc(0, fp);
9718
9719 fwrite(&gconf->sourceline, 1, sizeof(gconf->sourceline), fp);
9720 fwrite(&gconf->source, 1, sizeof(gconf->source), fp);
9721 fwrite(&gconf->scontext, 1, sizeof(gconf->scontext), fp);
9722}
9723
9724void
9725write_nondefault_variables(GucContext context)
9726{
9727 int elevel;
9728 FILE *fp;
9729 int i;
9730
9731 Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
9732
9733 elevel = (context == PGC_SIGHUP) ? LOG : ERROR;
9734
9735 /*
9736 * Open file
9737 */
9738 fp = AllocateFile(CONFIG_EXEC_PARAMS_NEW, "w");
9739 if (!fp)
9740 {
9741 ereport(elevel,
9742 (errcode_for_file_access(),
9743 errmsg("could not write to file \"%s\": %m",
9744 CONFIG_EXEC_PARAMS_NEW)));
9745 return;
9746 }
9747
9748 for (i = 0; i < num_guc_variables; i++)
9749 {
9750 write_one_nondefault_variable(fp, guc_variables[i]);
9751 }
9752
9753 if (FreeFile(fp))
9754 {
9755 ereport(elevel,
9756 (errcode_for_file_access(),
9757 errmsg("could not write to file \"%s\": %m",
9758 CONFIG_EXEC_PARAMS_NEW)));
9759 return;
9760 }
9761
9762 /*
9763 * Put new file in place. This could delay on Win32, but we don't hold
9764 * any exclusive locks.
9765 */
9766 rename(CONFIG_EXEC_PARAMS_NEW, CONFIG_EXEC_PARAMS);
9767}
9768
9769
9770/*
9771 * Read string, including null byte from file
9772 *
9773 * Return NULL on EOF and nothing read
9774 */
9775static char *
9776read_string_with_null(FILE *fp)
9777{
9778 int i = 0,
9779 ch,
9780 maxlen = 256;
9781 char *str = NULL;
9782
9783 do
9784 {
9785 if ((ch = fgetc(fp)) == EOF)
9786 {
9787 if (i == 0)
9788 return NULL;
9789 else
9790 elog(FATAL, "invalid format of exec config params file");
9791 }
9792 if (i == 0)
9793 str = guc_malloc(FATAL, maxlen);
9794 else if (i == maxlen)
9795 str = guc_realloc(FATAL, str, maxlen *= 2);
9796 str[i++] = ch;
9797 } while (ch != 0);
9798
9799 return str;
9800}
9801
9802
9803/*
9804 * This routine loads a previous postmaster dump of its non-default
9805 * settings.
9806 */
9807void
9808read_nondefault_variables(void)
9809{
9810 FILE *fp;
9811 char *varname,
9812 *varvalue,
9813 *varsourcefile;
9814 int varsourceline;
9815 GucSource varsource;
9816 GucContext varscontext;
9817
9818 /*
9819 * Assert that PGC_BACKEND/PGC_SU_BACKEND case in set_config_option() will
9820 * do the right thing.
9821 */
9822 Assert(IsInitProcessingMode());
9823
9824 /*
9825 * Open file
9826 */
9827 fp = AllocateFile(CONFIG_EXEC_PARAMS, "r");
9828 if (!fp)
9829 {
9830 /* File not found is fine */
9831 if (errno != ENOENT)
9832 ereport(FATAL,
9833 (errcode_for_file_access(),
9834 errmsg("could not read from file \"%s\": %m",
9835 CONFIG_EXEC_PARAMS)));
9836 return;
9837 }
9838
9839 for (;;)
9840 {
9841 struct config_generic *record;
9842
9843 if ((varname = read_string_with_null(fp)) == NULL)
9844 break;
9845
9846 if ((record = find_option(varname, true, FATAL)) == NULL)
9847 elog(FATAL, "failed to locate variable \"%s\" in exec config params file", varname);
9848
9849 if ((varvalue = read_string_with_null(fp)) == NULL)
9850 elog(FATAL, "invalid format of exec config params file");
9851 if ((varsourcefile = read_string_with_null(fp)) == NULL)
9852 elog(FATAL, "invalid format of exec config params file");
9853 if (fread(&varsourceline, 1, sizeof(varsourceline), fp) != sizeof(varsourceline))
9854 elog(FATAL, "invalid format of exec config params file");
9855 if (fread(&varsource, 1, sizeof(varsource), fp) != sizeof(varsource))
9856 elog(FATAL, "invalid format of exec config params file");
9857 if (fread(&varscontext, 1, sizeof(varscontext), fp) != sizeof(varscontext))
9858 elog(FATAL, "invalid format of exec config params file");
9859
9860 (void) set_config_option(varname, varvalue,
9861 varscontext, varsource,
9862 GUC_ACTION_SET, true, 0, true);
9863 if (varsourcefile[0])
9864 set_config_sourcefile(varname, varsourcefile, varsourceline);
9865
9866 free(varname);
9867 free(varvalue);
9868 free(varsourcefile);
9869 }
9870
9871 FreeFile(fp);
9872}
9873#endif /* EXEC_BACKEND */
9874
9875/*
9876 * can_skip_gucvar:
9877 * When serializing, determine whether to skip this GUC. When restoring, the
9878 * negation of this test determines whether to restore the compiled-in default
9879 * value before processing serialized values.
9880 *
9881 * A PGC_S_DEFAULT setting on the serialize side will typically match new
9882 * postmaster children, but that can be false when got_SIGHUP == true and the
9883 * pending configuration change modifies this setting. Nonetheless, we omit
9884 * PGC_S_DEFAULT settings from serialization and make up for that by restoring
9885 * defaults before applying serialized values.
9886 *
9887 * PGC_POSTMASTER variables always have the same value in every child of a
9888 * particular postmaster. Most PGC_INTERNAL variables are compile-time
9889 * constants; a few, like server_encoding and lc_ctype, are handled specially
9890 * outside the serialize/restore procedure. Therefore, SerializeGUCState()
9891 * never sends these, and RestoreGUCState() never changes them.
9892 *
9893 * Role is a special variable in the sense that its current value can be an
9894 * invalid value and there are multiple ways by which that can happen (like
9895 * after setting the role, someone drops it). So we handle it outside of
9896 * serialize/restore machinery.
9897 */
9898static bool
9899can_skip_gucvar(struct config_generic *gconf)
9900{
9901 return gconf->context == PGC_POSTMASTER ||
9902 gconf->context == PGC_INTERNAL || gconf->source == PGC_S_DEFAULT ||
9903 strcmp(gconf->name, "role") == 0;
9904}
9905
9906/*
9907 * estimate_variable_size:
9908 * Compute space needed for dumping the given GUC variable.
9909 *
9910 * It's OK to overestimate, but not to underestimate.
9911 */
9912static Size
9913estimate_variable_size(struct config_generic *gconf)
9914{
9915 Size size;
9916 Size valsize = 0;
9917
9918 if (can_skip_gucvar(gconf))
9919 return 0;
9920
9921 /* Name, plus trailing zero byte. */
9922 size = strlen(gconf->name) + 1;
9923
9924 /* Get the maximum display length of the GUC value. */
9925 switch (gconf->vartype)
9926 {
9927 case PGC_BOOL:
9928 {
9929 valsize = 5; /* max(strlen('true'), strlen('false')) */
9930 }
9931 break;
9932
9933 case PGC_INT:
9934 {
9935 struct config_int *conf = (struct config_int *) gconf;
9936
9937 /*
9938 * Instead of getting the exact display length, use max
9939 * length. Also reduce the max length for typical ranges of
9940 * small values. Maximum value is 2147483647, i.e. 10 chars.
9941 * Include one byte for sign.
9942 */
9943 if (Abs(*conf->variable) < 1000)
9944 valsize = 3 + 1;
9945 else
9946 valsize = 10 + 1;
9947 }
9948 break;
9949
9950 case PGC_REAL:
9951 {
9952 /*
9953 * We are going to print it with %e with REALTYPE_PRECISION
9954 * fractional digits. Account for sign, leading digit,
9955 * decimal point, and exponent with up to 3 digits. E.g.
9956 * -3.99329042340000021e+110
9957 */
9958 valsize = 1 + 1 + 1 + REALTYPE_PRECISION + 5;
9959 }
9960 break;
9961
9962 case PGC_STRING:
9963 {
9964 struct config_string *conf = (struct config_string *) gconf;
9965
9966 /*
9967 * If the value is NULL, we transmit it as an empty string.
9968 * Although this is not physically the same value, GUC
9969 * generally treats a NULL the same as empty string.
9970 */
9971 if (*conf->variable)
9972 valsize = strlen(*conf->variable);
9973 else
9974 valsize = 0;
9975 }
9976 break;
9977
9978 case PGC_ENUM:
9979 {
9980 struct config_enum *conf = (struct config_enum *) gconf;
9981
9982 valsize = strlen(config_enum_lookup_by_value(conf, *conf->variable));
9983 }
9984 break;
9985 }
9986
9987 /* Allow space for terminating zero-byte for value */
9988 size = add_size(size, valsize + 1);
9989
9990 if (gconf->sourcefile)
9991 size = add_size(size, strlen(gconf->sourcefile));
9992
9993 /* Allow space for terminating zero-byte for sourcefile */
9994 size = add_size(size, 1);
9995
9996 /* Include line whenever file is nonempty. */
9997 if (gconf->sourcefile && gconf->sourcefile[0])
9998 size = add_size(size, sizeof(gconf->sourceline));
9999
10000 size = add_size(size, sizeof(gconf->source));
10001 size = add_size(size, sizeof(gconf->scontext));
10002
10003 return size;
10004}
10005
10006/*
10007 * EstimateGUCStateSpace:
10008 * Returns the size needed to store the GUC state for the current process
10009 */
10010Size
10011EstimateGUCStateSpace(void)
10012{
10013 Size size;
10014 int i;
10015
10016 /* Add space reqd for saving the data size of the guc state */
10017 size = sizeof(Size);
10018
10019 /* Add up the space needed for each GUC variable */
10020 for (i = 0; i < num_guc_variables; i++)
10021 size = add_size(size,
10022 estimate_variable_size(guc_variables[i]));
10023
10024 return size;
10025}
10026
10027/*
10028 * do_serialize:
10029 * Copies the formatted string into the destination. Moves ahead the
10030 * destination pointer, and decrements the maxbytes by that many bytes. If
10031 * maxbytes is not sufficient to copy the string, error out.
10032 */
10033static void
10034do_serialize(char **destptr, Size *maxbytes, const char *fmt,...)
10035{
10036 va_list vargs;
10037 int n;
10038
10039 if (*maxbytes <= 0)
10040 elog(ERROR, "not enough space to serialize GUC state");
10041
10042 va_start(vargs, fmt);
10043 n = vsnprintf(*destptr, *maxbytes, fmt, vargs);
10044 va_end(vargs);
10045
10046 if (n < 0)
10047 {
10048 /* Shouldn't happen. Better show errno description. */
10049 elog(ERROR, "vsnprintf failed: %m with format string \"%s\"", fmt);
10050 }
10051 if (n >= *maxbytes)
10052 {
10053 /* This shouldn't happen either, really. */
10054 elog(ERROR, "not enough space to serialize GUC state");
10055 }
10056
10057 /* Shift the destptr ahead of the null terminator */
10058 *destptr += n + 1;
10059 *maxbytes -= n + 1;
10060}
10061
10062/* Binary copy version of do_serialize() */
10063static void
10064do_serialize_binary(char **destptr, Size *maxbytes, void *val, Size valsize)
10065{
10066 if (valsize > *maxbytes)
10067 elog(ERROR, "not enough space to serialize GUC state");
10068
10069 memcpy(*destptr, val, valsize);
10070 *destptr += valsize;
10071 *maxbytes -= valsize;
10072}
10073
10074/*
10075 * serialize_variable:
10076 * Dumps name, value and other information of a GUC variable into destptr.
10077 */
10078static void
10079serialize_variable(char **destptr, Size *maxbytes,
10080 struct config_generic *gconf)
10081{
10082 if (can_skip_gucvar(gconf))
10083 return;
10084
10085 do_serialize(destptr, maxbytes, "%s", gconf->name);
10086
10087 switch (gconf->vartype)
10088 {
10089 case PGC_BOOL:
10090 {
10091 struct config_bool *conf = (struct config_bool *) gconf;
10092
10093 do_serialize(destptr, maxbytes,
10094 (*conf->variable ? "true" : "false"));
10095 }
10096 break;
10097
10098 case PGC_INT:
10099 {
10100 struct config_int *conf = (struct config_int *) gconf;
10101
10102 do_serialize(destptr, maxbytes, "%d", *conf->variable);
10103 }
10104 break;
10105
10106 case PGC_REAL:
10107 {
10108 struct config_real *conf = (struct config_real *) gconf;
10109
10110 do_serialize(destptr, maxbytes, "%.*e",
10111 REALTYPE_PRECISION, *conf->variable);
10112 }
10113 break;
10114
10115 case PGC_STRING:
10116 {
10117 struct config_string *conf = (struct config_string *) gconf;
10118
10119 /* NULL becomes empty string, see estimate_variable_size() */
10120 do_serialize(destptr, maxbytes, "%s",
10121 *conf->variable ? *conf->variable : "");
10122 }
10123 break;
10124
10125 case PGC_ENUM:
10126 {
10127 struct config_enum *conf = (struct config_enum *) gconf;
10128
10129 do_serialize(destptr, maxbytes, "%s",
10130 config_enum_lookup_by_value(conf, *conf->variable));
10131 }
10132 break;
10133 }
10134
10135 do_serialize(destptr, maxbytes, "%s",
10136 (gconf->sourcefile ? gconf->sourcefile : ""));
10137
10138 if (gconf->sourcefile && gconf->sourcefile[0])
10139 do_serialize_binary(destptr, maxbytes, &gconf->sourceline,
10140 sizeof(gconf->sourceline));
10141
10142 do_serialize_binary(destptr, maxbytes, &gconf->source,
10143 sizeof(gconf->source));
10144 do_serialize_binary(destptr, maxbytes, &gconf->scontext,
10145 sizeof(gconf->scontext));
10146}
10147
10148/*
10149 * SerializeGUCState:
10150 * Dumps the complete GUC state onto the memory location at start_address.
10151 */
10152void
10153SerializeGUCState(Size maxsize, char *start_address)
10154{
10155 char *curptr;
10156 Size actual_size;
10157 Size bytes_left;
10158 int i;
10159
10160 /* Reserve space for saving the actual size of the guc state */
10161 Assert(maxsize > sizeof(actual_size));
10162 curptr = start_address + sizeof(actual_size);
10163 bytes_left = maxsize - sizeof(actual_size);
10164
10165 for (i = 0; i < num_guc_variables; i++)
10166 serialize_variable(&curptr, &bytes_left, guc_variables[i]);
10167
10168 /* Store actual size without assuming alignment of start_address. */
10169 actual_size = maxsize - bytes_left - sizeof(actual_size);
10170 memcpy(start_address, &actual_size, sizeof(actual_size));
10171}
10172
10173/*
10174 * read_gucstate:
10175 * Actually it does not read anything, just returns the srcptr. But it does
10176 * move the srcptr past the terminating zero byte, so that the caller is ready
10177 * to read the next string.
10178 */
10179static char *
10180read_gucstate(char **srcptr, char *srcend)
10181{
10182 char *retptr = *srcptr;
10183 char *ptr;
10184
10185 if (*srcptr >= srcend)
10186 elog(ERROR, "incomplete GUC state");
10187
10188 /* The string variables are all null terminated */
10189 for (ptr = *srcptr; ptr < srcend && *ptr != '\0'; ptr++)
10190 ;
10191
10192 if (ptr >= srcend)
10193 elog(ERROR, "could not find null terminator in GUC state");
10194
10195 /* Set the new position to the byte following the terminating NUL */
10196 *srcptr = ptr + 1;
10197
10198 return retptr;
10199}
10200
10201/* Binary read version of read_gucstate(). Copies into dest */
10202static void
10203read_gucstate_binary(char **srcptr, char *srcend, void *dest, Size size)
10204{
10205 if (*srcptr + size > srcend)
10206 elog(ERROR, "incomplete GUC state");
10207
10208 memcpy(dest, *srcptr, size);
10209 *srcptr += size;
10210}
10211
10212/*
10213 * RestoreGUCState:
10214 * Reads the GUC state at the specified address and updates the GUCs with the
10215 * values read from the GUC state.
10216 */
10217void
10218RestoreGUCState(void *gucstate)
10219{
10220 char *varname,
10221 *varvalue,
10222 *varsourcefile;
10223 int varsourceline;
10224 GucSource varsource;
10225 GucContext varscontext;
10226 char *srcptr = (char *) gucstate;
10227 char *srcend;
10228 Size len;
10229 int i;
10230
10231 /* See comment at can_skip_gucvar(). */
10232 for (i = 0; i < num_guc_variables; i++)
10233 if (!can_skip_gucvar(guc_variables[i]))
10234 InitializeOneGUCOption(guc_variables[i]);
10235
10236 /* First item is the length of the subsequent data */
10237 memcpy(&len, gucstate, sizeof(len));
10238
10239 srcptr += sizeof(len);
10240 srcend = srcptr + len;
10241
10242 while (srcptr < srcend)
10243 {
10244 int result;
10245
10246 varname = read_gucstate(&srcptr, srcend);
10247 varvalue = read_gucstate(&srcptr, srcend);
10248 varsourcefile = read_gucstate(&srcptr, srcend);
10249 if (varsourcefile[0])
10250 read_gucstate_binary(&srcptr, srcend,
10251 &varsourceline, sizeof(varsourceline));
10252 else
10253 varsourceline = 0;
10254 read_gucstate_binary(&srcptr, srcend,
10255 &varsource, sizeof(varsource));
10256 read_gucstate_binary(&srcptr, srcend,
10257 &varscontext, sizeof(varscontext));
10258
10259 result = set_config_option(varname, varvalue, varscontext, varsource,
10260 GUC_ACTION_SET, true, ERROR, true);
10261 if (result <= 0)
10262 ereport(ERROR,
10263 (errcode(ERRCODE_INTERNAL_ERROR),
10264 errmsg("parameter \"%s\" could not be set", varname)));
10265 if (varsourcefile[0])
10266 set_config_sourcefile(varname, varsourcefile, varsourceline);
10267 }
10268}
10269
10270/*
10271 * A little "long argument" simulation, although not quite GNU
10272 * compliant. Takes a string of the form "some-option=some value" and
10273 * returns name = "some_option" and value = "some value" in malloc'ed
10274 * storage. Note that '-' is converted to '_' in the option name. If
10275 * there is no '=' in the input string then value will be NULL.
10276 */
10277void
10278ParseLongOption(const char *string, char **name, char **value)
10279{
10280 size_t equal_pos;
10281 char *cp;
10282
10283 AssertArg(string);
10284 AssertArg(name);
10285 AssertArg(value);
10286
10287 equal_pos = strcspn(string, "=");
10288
10289 if (string[equal_pos] == '=')
10290 {
10291 *name = guc_malloc(FATAL, equal_pos + 1);
10292 strlcpy(*name, string, equal_pos + 1);
10293
10294 *value = guc_strdup(FATAL, &string[equal_pos + 1]);
10295 }
10296 else
10297 {
10298 /* no equal sign in string */
10299 *name = guc_strdup(FATAL, string);
10300 *value = NULL;
10301 }
10302
10303 for (cp = *name; *cp; cp++)
10304 if (*cp == '-')
10305 *cp = '_';
10306}
10307
10308
10309/*
10310 * Handle options fetched from pg_db_role_setting.setconfig,
10311 * pg_proc.proconfig, etc. Caller must specify proper context/source/action.
10312 *
10313 * The array parameter must be an array of TEXT (it must not be NULL).
10314 */
10315void
10316ProcessGUCArray(ArrayType *array,
10317 GucContext context, GucSource source, GucAction action)
10318{
10319 int i;
10320
10321 Assert(array != NULL);
10322 Assert(ARR_ELEMTYPE(array) == TEXTOID);
10323 Assert(ARR_NDIM(array) == 1);
10324 Assert(ARR_LBOUND(array)[0] == 1);
10325
10326 for (i = 1; i <= ARR_DIMS(array)[0]; i++)
10327 {
10328 Datum d;
10329 bool isnull;
10330 char *s;
10331 char *name;
10332 char *value;
10333
10334 d = array_ref(array, 1, &i,
10335 -1 /* varlenarray */ ,
10336 -1 /* TEXT's typlen */ ,
10337 false /* TEXT's typbyval */ ,
10338 'i' /* TEXT's typalign */ ,
10339 &isnull);
10340
10341 if (isnull)
10342 continue;
10343
10344 s = TextDatumGetCString(d);
10345
10346 ParseLongOption(s, &name, &value);
10347 if (!value)
10348 {
10349 ereport(WARNING,
10350 (errcode(ERRCODE_SYNTAX_ERROR),
10351 errmsg("could not parse setting for parameter \"%s\"",
10352 name)));
10353 free(name);
10354 continue;
10355 }
10356
10357 (void) set_config_option(name, value,
10358 context, source,
10359 action, true, 0, false);
10360
10361 free(name);
10362 if (value)
10363 free(value);
10364 pfree(s);
10365 }
10366}
10367
10368
10369/*
10370 * Add an entry to an option array. The array parameter may be NULL
10371 * to indicate the current table entry is NULL.
10372 */
10373ArrayType *
10374GUCArrayAdd(ArrayType *array, const char *name, const char *value)
10375{
10376 struct config_generic *record;
10377 Datum datum;
10378 char *newval;
10379 ArrayType *a;
10380
10381 Assert(name);
10382 Assert(value);
10383
10384 /* test if the option is valid and we're allowed to set it */
10385 (void) validate_option_array_item(name, value, false);
10386
10387 /* normalize name (converts obsolete GUC names to modern spellings) */
10388 record = find_option(name, false, WARNING);
10389 if (record)
10390 name = record->name;
10391
10392 /* build new item for array */
10393 newval = psprintf("%s=%s", name, value);
10394 datum = CStringGetTextDatum(newval);
10395
10396 if (array)
10397 {
10398 int index;
10399 bool isnull;
10400 int i;
10401
10402 Assert(ARR_ELEMTYPE(array) == TEXTOID);
10403 Assert(ARR_NDIM(array) == 1);
10404 Assert(ARR_LBOUND(array)[0] == 1);
10405
10406 index = ARR_DIMS(array)[0] + 1; /* add after end */
10407
10408 for (i = 1; i <= ARR_DIMS(array)[0]; i++)
10409 {
10410 Datum d;
10411 char *current;
10412
10413 d = array_ref(array, 1, &i,
10414 -1 /* varlenarray */ ,
10415 -1 /* TEXT's typlen */ ,
10416 false /* TEXT's typbyval */ ,
10417 'i' /* TEXT's typalign */ ,
10418 &isnull);
10419 if (isnull)
10420 continue;
10421 current = TextDatumGetCString(d);
10422
10423 /* check for match up through and including '=' */
10424 if (strncmp(current, newval, strlen(name) + 1) == 0)
10425 {
10426 index = i;
10427 break;
10428 }
10429 }
10430
10431 a = array_set(array, 1, &index,
10432 datum,
10433 false,
10434 -1 /* varlena array */ ,
10435 -1 /* TEXT's typlen */ ,
10436 false /* TEXT's typbyval */ ,
10437 'i' /* TEXT's typalign */ );
10438 }
10439 else
10440 a = construct_array(&datum, 1,
10441 TEXTOID,
10442 -1, false, 'i');
10443
10444 return a;
10445}
10446
10447
10448/*
10449 * Delete an entry from an option array. The array parameter may be NULL
10450 * to indicate the current table entry is NULL. Also, if the return value
10451 * is NULL then a null should be stored.
10452 */
10453ArrayType *
10454GUCArrayDelete(ArrayType *array, const char *name)
10455{
10456 struct config_generic *record;
10457 ArrayType *newarray;
10458 int i;
10459 int index;
10460
10461 Assert(name);
10462
10463 /* test if the option is valid and we're allowed to set it */
10464 (void) validate_option_array_item(name, NULL, false);
10465
10466 /* normalize name (converts obsolete GUC names to modern spellings) */
10467 record = find_option(name, false, WARNING);
10468 if (record)
10469 name = record->name;
10470
10471 /* if array is currently null, then surely nothing to delete */
10472 if (!array)
10473 return NULL;
10474
10475 newarray = NULL;
10476 index = 1;
10477
10478 for (i = 1; i <= ARR_DIMS(array)[0]; i++)
10479 {
10480 Datum d;
10481 char *val;
10482 bool isnull;
10483
10484 d = array_ref(array, 1, &i,
10485 -1 /* varlenarray */ ,
10486 -1 /* TEXT's typlen */ ,
10487 false /* TEXT's typbyval */ ,
10488 'i' /* TEXT's typalign */ ,
10489 &isnull);
10490 if (isnull)
10491 continue;
10492 val = TextDatumGetCString(d);
10493
10494 /* ignore entry if it's what we want to delete */
10495 if (strncmp(val, name, strlen(name)) == 0
10496 && val[strlen(name)] == '=')
10497 continue;
10498
10499 /* else add it to the output array */
10500 if (newarray)
10501 newarray = array_set(newarray, 1, &index,
10502 d,
10503 false,
10504 -1 /* varlenarray */ ,
10505 -1 /* TEXT's typlen */ ,
10506 false /* TEXT's typbyval */ ,
10507 'i' /* TEXT's typalign */ );
10508 else
10509 newarray = construct_array(&d, 1,
10510 TEXTOID,
10511 -1, false, 'i');
10512
10513 index++;
10514 }
10515
10516 return newarray;
10517}
10518
10519
10520/*
10521 * Given a GUC array, delete all settings from it that our permission
10522 * level allows: if superuser, delete them all; if regular user, only
10523 * those that are PGC_USERSET
10524 */
10525ArrayType *
10526GUCArrayReset(ArrayType *array)
10527{
10528 ArrayType *newarray;
10529 int i;
10530 int index;
10531
10532 /* if array is currently null, nothing to do */
10533 if (!array)
10534 return NULL;
10535
10536 /* if we're superuser, we can delete everything, so just do it */
10537 if (superuser())
10538 return NULL;
10539
10540 newarray = NULL;
10541 index = 1;
10542
10543 for (i = 1; i <= ARR_DIMS(array)[0]; i++)
10544 {
10545 Datum d;
10546 char *val;
10547 char *eqsgn;
10548 bool isnull;
10549
10550 d = array_ref(array, 1, &i,
10551 -1 /* varlenarray */ ,
10552 -1 /* TEXT's typlen */ ,
10553 false /* TEXT's typbyval */ ,
10554 'i' /* TEXT's typalign */ ,
10555 &isnull);
10556 if (isnull)
10557 continue;
10558 val = TextDatumGetCString(d);
10559
10560 eqsgn = strchr(val, '=');
10561 *eqsgn = '\0';
10562
10563 /* skip if we have permission to delete it */
10564 if (validate_option_array_item(val, NULL, true))
10565 continue;
10566
10567 /* else add it to the output array */
10568 if (newarray)
10569 newarray = array_set(newarray, 1, &index,
10570 d,
10571 false,
10572 -1 /* varlenarray */ ,
10573 -1 /* TEXT's typlen */ ,
10574 false /* TEXT's typbyval */ ,
10575 'i' /* TEXT's typalign */ );
10576 else
10577 newarray = construct_array(&d, 1,
10578 TEXTOID,
10579 -1, false, 'i');
10580
10581 index++;
10582 pfree(val);
10583 }
10584
10585 return newarray;
10586}
10587
10588/*
10589 * Validate a proposed option setting for GUCArrayAdd/Delete/Reset.
10590 *
10591 * name is the option name. value is the proposed value for the Add case,
10592 * or NULL for the Delete/Reset cases. If skipIfNoPermissions is true, it's
10593 * not an error to have no permissions to set the option.
10594 *
10595 * Returns true if OK, false if skipIfNoPermissions is true and user does not
10596 * have permission to change this option (all other error cases result in an
10597 * error being thrown).
10598 */
10599static bool
10600validate_option_array_item(const char *name, const char *value,
10601 bool skipIfNoPermissions)
10602
10603{
10604 struct config_generic *gconf;
10605
10606 /*
10607 * There are three cases to consider:
10608 *
10609 * name is a known GUC variable. Check the value normally, check
10610 * permissions normally (i.e., allow if variable is USERSET, or if it's
10611 * SUSET and user is superuser).
10612 *
10613 * name is not known, but exists or can be created as a placeholder (i.e.,
10614 * it has a prefixed name). We allow this case if you're a superuser,
10615 * otherwise not. Superusers are assumed to know what they're doing. We
10616 * can't allow it for other users, because when the placeholder is
10617 * resolved it might turn out to be a SUSET variable;
10618 * define_custom_variable assumes we checked that.
10619 *
10620 * name is not known and can't be created as a placeholder. Throw error,
10621 * unless skipIfNoPermissions is true, in which case return false.
10622 */
10623 gconf = find_option(name, true, WARNING);
10624 if (!gconf)
10625 {
10626 /* not known, failed to make a placeholder */
10627 if (skipIfNoPermissions)
10628 return false;
10629 ereport(ERROR,
10630 (errcode(ERRCODE_UNDEFINED_OBJECT),
10631 errmsg("unrecognized configuration parameter \"%s\"",
10632 name)));
10633 }
10634
10635 if (gconf->flags & GUC_CUSTOM_PLACEHOLDER)
10636 {
10637 /*
10638 * We cannot do any meaningful check on the value, so only permissions
10639 * are useful to check.
10640 */
10641 if (superuser())
10642 return true;
10643 if (skipIfNoPermissions)
10644 return false;
10645 ereport(ERROR,
10646 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
10647 errmsg("permission denied to set parameter \"%s\"", name)));
10648 }
10649
10650 /* manual permissions check so we can avoid an error being thrown */
10651 if (gconf->context == PGC_USERSET)
10652 /* ok */ ;
10653 else if (gconf->context == PGC_SUSET && superuser())
10654 /* ok */ ;
10655 else if (skipIfNoPermissions)
10656 return false;
10657 /* if a permissions error should be thrown, let set_config_option do it */
10658
10659 /* test for permissions and valid option value */
10660 (void) set_config_option(name, value,
10661 superuser() ? PGC_SUSET : PGC_USERSET,
10662 PGC_S_TEST, GUC_ACTION_SET, false, 0, false);
10663
10664 return true;
10665}
10666
10667
10668/*
10669 * Called by check_hooks that want to override the normal
10670 * ERRCODE_INVALID_PARAMETER_VALUE SQLSTATE for check hook failures.
10671 *
10672 * Note that GUC_check_errmsg() etc are just macros that result in a direct
10673 * assignment to the associated variables. That is ugly, but forced by the
10674 * limitations of C's macro mechanisms.
10675 */
10676void
10677GUC_check_errcode(int sqlerrcode)
10678{
10679 GUC_check_errcode_value = sqlerrcode;
10680}
10681
10682
10683/*
10684 * Convenience functions to manage calling a variable's check_hook.
10685 * These mostly take care of the protocol for letting check hooks supply
10686 * portions of the error report on failure.
10687 */
10688
10689static bool
10690call_bool_check_hook(struct config_bool *conf, bool *newval, void **extra,
10691 GucSource source, int elevel)
10692{
10693 /* Quick success if no hook */
10694 if (!conf->check_hook)
10695 return true;
10696
10697 /* Reset variables that might be set by hook */
10698 GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
10699 GUC_check_errmsg_string = NULL;
10700 GUC_check_errdetail_string = NULL;
10701 GUC_check_errhint_string = NULL;
10702
10703 if (!conf->check_hook(newval, extra, source))
10704 {
10705 ereport(elevel,
10706 (errcode(GUC_check_errcode_value),
10707 GUC_check_errmsg_string ?
10708 errmsg_internal("%s", GUC_check_errmsg_string) :
10709 errmsg("invalid value for parameter \"%s\": %d",
10710 conf->gen.name, (int) *newval),
10711 GUC_check_errdetail_string ?
10712 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
10713 GUC_check_errhint_string ?
10714 errhint("%s", GUC_check_errhint_string) : 0));
10715 /* Flush any strings created in ErrorContext */
10716 FlushErrorState();
10717 return false;
10718 }
10719
10720 return true;
10721}
10722
10723static bool
10724call_int_check_hook(struct config_int *conf, int *newval, void **extra,
10725 GucSource source, int elevel)
10726{
10727 /* Quick success if no hook */
10728 if (!conf->check_hook)
10729 return true;
10730
10731 /* Reset variables that might be set by hook */
10732 GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
10733 GUC_check_errmsg_string = NULL;
10734 GUC_check_errdetail_string = NULL;
10735 GUC_check_errhint_string = NULL;
10736
10737 if (!conf->check_hook(newval, extra, source))
10738 {
10739 ereport(elevel,
10740 (errcode(GUC_check_errcode_value),
10741 GUC_check_errmsg_string ?
10742 errmsg_internal("%s", GUC_check_errmsg_string) :
10743 errmsg("invalid value for parameter \"%s\": %d",
10744 conf->gen.name, *newval),
10745 GUC_check_errdetail_string ?
10746 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
10747 GUC_check_errhint_string ?
10748 errhint("%s", GUC_check_errhint_string) : 0));
10749 /* Flush any strings created in ErrorContext */
10750 FlushErrorState();
10751 return false;
10752 }
10753
10754 return true;
10755}
10756
10757static bool
10758call_real_check_hook(struct config_real *conf, double *newval, void **extra,
10759 GucSource source, int elevel)
10760{
10761 /* Quick success if no hook */
10762 if (!conf->check_hook)
10763 return true;
10764
10765 /* Reset variables that might be set by hook */
10766 GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
10767 GUC_check_errmsg_string = NULL;
10768 GUC_check_errdetail_string = NULL;
10769 GUC_check_errhint_string = NULL;
10770
10771 if (!conf->check_hook(newval, extra, source))
10772 {
10773 ereport(elevel,
10774 (errcode(GUC_check_errcode_value),
10775 GUC_check_errmsg_string ?
10776 errmsg_internal("%s", GUC_check_errmsg_string) :
10777 errmsg("invalid value for parameter \"%s\": %g",
10778 conf->gen.name, *newval),
10779 GUC_check_errdetail_string ?
10780 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
10781 GUC_check_errhint_string ?
10782 errhint("%s", GUC_check_errhint_string) : 0));
10783 /* Flush any strings created in ErrorContext */
10784 FlushErrorState();
10785 return false;
10786 }
10787
10788 return true;
10789}
10790
10791static bool
10792call_string_check_hook(struct config_string *conf, char **newval, void **extra,
10793 GucSource source, int elevel)
10794{
10795 /* Quick success if no hook */
10796 if (!conf->check_hook)
10797 return true;
10798
10799 /* Reset variables that might be set by hook */
10800 GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
10801 GUC_check_errmsg_string = NULL;
10802 GUC_check_errdetail_string = NULL;
10803 GUC_check_errhint_string = NULL;
10804
10805 if (!conf->check_hook(newval, extra, source))
10806 {
10807 ereport(elevel,
10808 (errcode(GUC_check_errcode_value),
10809 GUC_check_errmsg_string ?
10810 errmsg_internal("%s", GUC_check_errmsg_string) :
10811 errmsg("invalid value for parameter \"%s\": \"%s\"",
10812 conf->gen.name, *newval ? *newval : ""),
10813 GUC_check_errdetail_string ?
10814 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
10815 GUC_check_errhint_string ?
10816 errhint("%s", GUC_check_errhint_string) : 0));
10817 /* Flush any strings created in ErrorContext */
10818 FlushErrorState();
10819 return false;
10820 }
10821
10822 return true;
10823}
10824
10825static bool
10826call_enum_check_hook(struct config_enum *conf, int *newval, void **extra,
10827 GucSource source, int elevel)
10828{
10829 /* Quick success if no hook */
10830 if (!conf->check_hook)
10831 return true;
10832
10833 /* Reset variables that might be set by hook */
10834 GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
10835 GUC_check_errmsg_string = NULL;
10836 GUC_check_errdetail_string = NULL;
10837 GUC_check_errhint_string = NULL;
10838
10839 if (!conf->check_hook(newval, extra, source))
10840 {
10841 ereport(elevel,
10842 (errcode(GUC_check_errcode_value),
10843 GUC_check_errmsg_string ?
10844 errmsg_internal("%s", GUC_check_errmsg_string) :
10845 errmsg("invalid value for parameter \"%s\": \"%s\"",
10846 conf->gen.name,
10847 config_enum_lookup_by_value(conf, *newval)),
10848 GUC_check_errdetail_string ?
10849 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
10850 GUC_check_errhint_string ?
10851 errhint("%s", GUC_check_errhint_string) : 0));
10852 /* Flush any strings created in ErrorContext */
10853 FlushErrorState();
10854 return false;
10855 }
10856
10857 return true;
10858}
10859
10860
10861/*
10862 * check_hook, assign_hook and show_hook subroutines
10863 */
10864
10865static bool
10866check_wal_consistency_checking(char **newval, void **extra, GucSource source)
10867{
10868 char *rawstring;
10869 List *elemlist;
10870 ListCell *l;
10871 bool newwalconsistency[RM_MAX_ID + 1];
10872
10873 /* Initialize the array */
10874 MemSet(newwalconsistency, 0, (RM_MAX_ID + 1) * sizeof(bool));
10875
10876 /* Need a modifiable copy of string */
10877 rawstring = pstrdup(*newval);
10878
10879 /* Parse string into list of identifiers */
10880 if (!SplitIdentifierString(rawstring, ',', &elemlist))
10881 {
10882 /* syntax error in list */
10883 GUC_check_errdetail("List syntax is invalid.");
10884 pfree(rawstring);
10885 list_free(elemlist);
10886 return false;
10887 }
10888
10889 foreach(l, elemlist)
10890 {
10891 char *tok = (char *) lfirst(l);
10892 bool found = false;
10893 RmgrId rmid;
10894
10895 /* Check for 'all'. */
10896 if (pg_strcasecmp(tok, "all") == 0)
10897 {
10898 for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
10899 if (RmgrTable[rmid].rm_mask != NULL)
10900 newwalconsistency[rmid] = true;
10901 found = true;
10902 }
10903 else
10904 {
10905 /*
10906 * Check if the token matches with any individual resource
10907 * manager.
10908 */
10909 for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
10910 {
10911 if (pg_strcasecmp(tok, RmgrTable[rmid].rm_name) == 0 &&
10912 RmgrTable[rmid].rm_mask != NULL)
10913 {
10914 newwalconsistency[rmid] = true;
10915 found = true;
10916 }
10917 }
10918 }
10919
10920 /* If a valid resource manager is found, check for the next one. */
10921 if (!found)
10922 {
10923 GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
10924 pfree(rawstring);
10925 list_free(elemlist);
10926 return false;
10927 }
10928 }
10929
10930 pfree(rawstring);
10931 list_free(elemlist);
10932
10933 /* assign new value */
10934 *extra = guc_malloc(ERROR, (RM_MAX_ID + 1) * sizeof(bool));
10935 memcpy(*extra, newwalconsistency, (RM_MAX_ID + 1) * sizeof(bool));
10936 return true;
10937}
10938
10939static void
10940assign_wal_consistency_checking(const char *newval, void *extra)
10941{
10942 wal_consistency_checking = (bool *) extra;
10943}
10944
10945static bool
10946check_log_destination(char **newval, void **extra, GucSource source)
10947{
10948 char *rawstring;
10949 List *elemlist;
10950 ListCell *l;
10951 int newlogdest = 0;
10952 int *myextra;
10953
10954 /* Need a modifiable copy of string */
10955 rawstring = pstrdup(*newval);
10956
10957 /* Parse string into list of identifiers */
10958 if (!SplitIdentifierString(rawstring, ',', &elemlist))
10959 {
10960 /* syntax error in list */
10961 GUC_check_errdetail("List syntax is invalid.");
10962 pfree(rawstring);
10963 list_free(elemlist);
10964 return false;
10965 }
10966
10967 foreach(l, elemlist)
10968 {
10969 char *tok = (char *) lfirst(l);
10970
10971 if (pg_strcasecmp(tok, "stderr") == 0)
10972 newlogdest |= LOG_DESTINATION_STDERR;
10973 else if (pg_strcasecmp(tok, "csvlog") == 0)
10974 newlogdest |= LOG_DESTINATION_CSVLOG;
10975#ifdef HAVE_SYSLOG
10976 else if (pg_strcasecmp(tok, "syslog") == 0)
10977 newlogdest |= LOG_DESTINATION_SYSLOG;
10978#endif
10979#ifdef WIN32
10980 else if (pg_strcasecmp(tok, "eventlog") == 0)
10981 newlogdest |= LOG_DESTINATION_EVENTLOG;
10982#endif
10983 else
10984 {
10985 GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
10986 pfree(rawstring);
10987 list_free(elemlist);
10988 return false;
10989 }
10990 }
10991
10992 pfree(rawstring);
10993 list_free(elemlist);
10994
10995 myextra = (int *) guc_malloc(ERROR, sizeof(int));
10996 *myextra = newlogdest;
10997 *extra = (void *) myextra;
10998
10999 return true;
11000}
11001
11002static void
11003assign_log_destination(const char *newval, void *extra)
11004{
11005 Log_destination = *((int *) extra);
11006}
11007
11008static void
11009assign_syslog_facility(int newval, void *extra)
11010{
11011#ifdef HAVE_SYSLOG
11012 set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
11013 newval);
11014#endif
11015 /* Without syslog support, just ignore it */
11016}
11017
11018static void
11019assign_syslog_ident(const char *newval, void *extra)
11020{
11021#ifdef HAVE_SYSLOG
11022 set_syslog_parameters(newval, syslog_facility);
11023#endif
11024 /* Without syslog support, it will always be set to "none", so ignore */
11025}
11026
11027
11028static void
11029assign_session_replication_role(int newval, void *extra)
11030{
11031 /*
11032 * Must flush the plan cache when changing replication role; but don't
11033 * flush unnecessarily.
11034 */
11035 if (SessionReplicationRole != newval)
11036 ResetPlanCache();
11037}
11038
11039static bool
11040check_temp_buffers(int *newval, void **extra, GucSource source)
11041{
11042 /*
11043 * Once local buffers have been initialized, it's too late to change this.
11044 */
11045 if (NLocBuffer && NLocBuffer != *newval)
11046 {
11047 GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session.");
11048 return false;
11049 }
11050 return true;
11051}
11052
11053static bool
11054check_bonjour(bool *newval, void **extra, GucSource source)
11055{
11056#ifndef USE_BONJOUR
11057 if (*newval)
11058 {
11059 GUC_check_errmsg("Bonjour is not supported by this build");
11060 return false;
11061 }
11062#endif
11063 return true;
11064}
11065
11066static bool
11067check_ssl(bool *newval, void **extra, GucSource source)
11068{
11069#ifndef USE_SSL
11070 if (*newval)
11071 {
11072 GUC_check_errmsg("SSL is not supported by this build");
11073 return false;
11074 }
11075#endif
11076 return true;
11077}
11078
11079static bool
11080check_stage_log_stats(bool *newval, void **extra, GucSource source)
11081{
11082 if (*newval && log_statement_stats)
11083 {
11084 GUC_check_errdetail("Cannot enable parameter when \"log_statement_stats\" is true.");
11085 return false;
11086 }
11087 return true;
11088}
11089
11090static bool
11091check_log_stats(bool *newval, void **extra, GucSource source)
11092{
11093 if (*newval &&
11094 (log_parser_stats || log_planner_stats || log_executor_stats))
11095 {
11096 GUC_check_errdetail("Cannot enable \"log_statement_stats\" when "
11097 "\"log_parser_stats\", \"log_planner_stats\", "
11098 "or \"log_executor_stats\" is true.");
11099 return false;
11100 }
11101 return true;
11102}
11103
11104static bool
11105check_canonical_path(char **newval, void **extra, GucSource source)
11106{
11107 /*
11108 * Since canonicalize_path never enlarges the string, we can just modify
11109 * newval in-place. But watch out for NULL, which is the default value
11110 * for external_pid_file.
11111 */
11112 if (*newval)
11113 canonicalize_path(*newval);
11114 return true;
11115}
11116
11117static bool
11118check_timezone_abbreviations(char **newval, void **extra, GucSource source)
11119{
11120 /*
11121 * The boot_val given above for timezone_abbreviations is NULL. When we
11122 * see this we just do nothing. If this value isn't overridden from the
11123 * config file then pg_timezone_abbrev_initialize() will eventually
11124 * replace it with "Default". This hack has two purposes: to avoid
11125 * wasting cycles loading values that might soon be overridden from the
11126 * config file, and to avoid trying to read the timezone abbrev files
11127 * during InitializeGUCOptions(). The latter doesn't work in an
11128 * EXEC_BACKEND subprocess because my_exec_path hasn't been set yet and so
11129 * we can't locate PGSHAREDIR.
11130 */
11131 if (*newval == NULL)
11132 {
11133 Assert(source == PGC_S_DEFAULT);
11134 return true;
11135 }
11136
11137 /* OK, load the file and produce a malloc'd TimeZoneAbbrevTable */
11138 *extra = load_tzoffsets(*newval);
11139
11140 /* tzparser.c returns NULL on failure, reporting via GUC_check_errmsg */
11141 if (!*extra)
11142 return false;
11143
11144 return true;
11145}
11146
11147static void
11148assign_timezone_abbreviations(const char *newval, void *extra)
11149{
11150 /* Do nothing for the boot_val default of NULL */
11151 if (!extra)
11152 return;
11153
11154 InstallTimeZoneAbbrevs((TimeZoneAbbrevTable *) extra);
11155}
11156
11157/*
11158 * pg_timezone_abbrev_initialize --- set default value if not done already
11159 *
11160 * This is called after initial loading of postgresql.conf. If no
11161 * timezone_abbreviations setting was found therein, select default.
11162 * If a non-default value is already installed, nothing will happen.
11163 *
11164 * This can also be called from ProcessConfigFile to establish the default
11165 * value after a postgresql.conf entry for it is removed.
11166 */
11167static void
11168pg_timezone_abbrev_initialize(void)
11169{
11170 SetConfigOption("timezone_abbreviations", "Default",
11171 PGC_POSTMASTER, PGC_S_DYNAMIC_DEFAULT);
11172}
11173
11174static const char *
11175show_archive_command(void)
11176{
11177 if (XLogArchivingActive())
11178 return XLogArchiveCommand;
11179 else
11180 return "(disabled)";
11181}
11182
11183static void
11184assign_tcp_keepalives_idle(int newval, void *extra)
11185{
11186 /*
11187 * The kernel API provides no way to test a value without setting it; and
11188 * once we set it we might fail to unset it. So there seems little point
11189 * in fully implementing the check-then-assign GUC API for these
11190 * variables. Instead we just do the assignment on demand. pqcomm.c
11191 * reports any problems via elog(LOG).
11192 *
11193 * This approach means that the GUC value might have little to do with the
11194 * actual kernel value, so we use a show_hook that retrieves the kernel
11195 * value rather than trusting GUC's copy.
11196 */
11197 (void) pq_setkeepalivesidle(newval, MyProcPort);
11198}
11199
11200static const char *
11201show_tcp_keepalives_idle(void)
11202{
11203 /* See comments in assign_tcp_keepalives_idle */
11204 static char nbuf[16];
11205
11206 snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
11207 return nbuf;
11208}
11209
11210static void
11211assign_tcp_keepalives_interval(int newval, void *extra)
11212{
11213 /* See comments in assign_tcp_keepalives_idle */
11214 (void) pq_setkeepalivesinterval(newval, MyProcPort);
11215}
11216
11217static const char *
11218show_tcp_keepalives_interval(void)
11219{
11220 /* See comments in assign_tcp_keepalives_idle */
11221 static char nbuf[16];
11222
11223 snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
11224 return nbuf;
11225}
11226
11227static void
11228assign_tcp_keepalives_count(int newval, void *extra)
11229{
11230 /* See comments in assign_tcp_keepalives_idle */
11231 (void) pq_setkeepalivescount(newval, MyProcPort);
11232}
11233
11234static const char *
11235show_tcp_keepalives_count(void)
11236{
11237 /* See comments in assign_tcp_keepalives_idle */
11238 static char nbuf[16];
11239
11240 snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
11241 return nbuf;
11242}
11243
11244static void
11245assign_tcp_user_timeout(int newval, void *extra)
11246{
11247 /* See comments in assign_tcp_keepalives_idle */
11248 (void) pq_settcpusertimeout(newval, MyProcPort);
11249}
11250
11251static const char *
11252show_tcp_user_timeout(void)
11253{
11254 /* See comments in assign_tcp_keepalives_idle */
11255 static char nbuf[16];
11256
11257 snprintf(nbuf, sizeof(nbuf), "%d", pq_gettcpusertimeout(MyProcPort));
11258 return nbuf;
11259}
11260
11261static bool
11262check_maxconnections(int *newval, void **extra, GucSource source)
11263{
11264 if (*newval + autovacuum_max_workers + 1 +
11265 max_worker_processes + max_wal_senders > MAX_BACKENDS)
11266 return false;
11267 return true;
11268}
11269
11270static bool
11271check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
11272{
11273 if (MaxConnections + *newval + 1 +
11274 max_worker_processes + max_wal_senders > MAX_BACKENDS)
11275 return false;
11276 return true;
11277}
11278
11279static bool
11280check_max_wal_senders(int *newval, void **extra, GucSource source)
11281{
11282 if (MaxConnections + autovacuum_max_workers + 1 +
11283 max_worker_processes + *newval > MAX_BACKENDS)
11284 return false;
11285 return true;
11286}
11287
11288static bool
11289check_autovacuum_work_mem(int *newval, void **extra, GucSource source)
11290{
11291 /*
11292 * -1 indicates fallback.
11293 *
11294 * If we haven't yet changed the boot_val default of -1, just let it be.
11295 * Autovacuum will look to maintenance_work_mem instead.
11296 */
11297 if (*newval == -1)
11298 return true;
11299
11300 /*
11301 * We clamp manually-set values to at least 1MB. Since
11302 * maintenance_work_mem is always set to at least this value, do the same
11303 * here.
11304 */
11305 if (*newval < 1024)
11306 *newval = 1024;
11307
11308 return true;
11309}
11310
11311static bool
11312check_max_worker_processes(int *newval, void **extra, GucSource source)
11313{
11314 if (MaxConnections + autovacuum_max_workers + 1 +
11315 *newval + max_wal_senders > MAX_BACKENDS)
11316 return false;
11317 return true;
11318}
11319
11320static bool
11321check_effective_io_concurrency(int *newval, void **extra, GucSource source)
11322{
11323#ifdef USE_PREFETCH
11324 double new_prefetch_pages;
11325
11326 if (ComputeIoConcurrency(*newval, &new_prefetch_pages))
11327 {
11328 int *myextra = (int *) guc_malloc(ERROR, sizeof(int));
11329
11330 *myextra = (int) rint(new_prefetch_pages);
11331 *extra = (void *) myextra;
11332
11333 return true;
11334 }
11335 else
11336 return false;
11337#else
11338 if (*newval != 0)
11339 {
11340 GUC_check_errdetail("effective_io_concurrency must be set to 0 on platforms that lack posix_fadvise().");
11341 return false;
11342 }
11343 return true;
11344#endif /* USE_PREFETCH */
11345}
11346
11347static void
11348assign_effective_io_concurrency(int newval, void *extra)
11349{
11350#ifdef USE_PREFETCH
11351 target_prefetch_pages = *((int *) extra);
11352#endif /* USE_PREFETCH */
11353}
11354
11355static void
11356assign_pgstat_temp_directory(const char *newval, void *extra)
11357{
11358 /* check_canonical_path already canonicalized newval for us */
11359 char *dname;
11360 char *tname;
11361 char *fname;
11362
11363 /* directory */
11364 dname = guc_malloc(ERROR, strlen(newval) + 1); /* runtime dir */
11365 sprintf(dname, "%s", newval);
11366
11367 /* global stats */
11368 tname = guc_malloc(ERROR, strlen(newval) + 12); /* /global.tmp */
11369 sprintf(tname, "%s/global.tmp", newval);
11370 fname = guc_malloc(ERROR, strlen(newval) + 13); /* /global.stat */
11371 sprintf(fname, "%s/global.stat", newval);
11372
11373 if (pgstat_stat_directory)
11374 free(pgstat_stat_directory);
11375 pgstat_stat_directory = dname;
11376 if (pgstat_stat_tmpname)
11377 free(pgstat_stat_tmpname);
11378 pgstat_stat_tmpname = tname;
11379 if (pgstat_stat_filename)
11380 free(pgstat_stat_filename);
11381 pgstat_stat_filename = fname;
11382}
11383
11384static bool
11385check_application_name(char **newval, void **extra, GucSource source)
11386{
11387 /* Only allow clean ASCII chars in the application name */
11388 pg_clean_ascii(*newval);
11389
11390 return true;
11391}
11392
11393static void
11394assign_application_name(const char *newval, void *extra)
11395{
11396 /* Update the pg_stat_activity view */
11397 pgstat_report_appname(newval);
11398}
11399
11400static bool
11401check_cluster_name(char **newval, void **extra, GucSource source)
11402{
11403 /* Only allow clean ASCII chars in the cluster name */
11404 pg_clean_ascii(*newval);
11405
11406 return true;
11407}
11408
11409static const char *
11410show_unix_socket_permissions(void)
11411{
11412 static char buf[12];
11413
11414 snprintf(buf, sizeof(buf), "%04o", Unix_socket_permissions);
11415 return buf;
11416}
11417
11418static const char *
11419show_log_file_mode(void)
11420{
11421 static char buf[12];
11422
11423 snprintf(buf, sizeof(buf), "%04o", Log_file_mode);
11424 return buf;
11425}
11426
11427static const char *
11428show_data_directory_mode(void)
11429{
11430 static char buf[12];
11431
11432 snprintf(buf, sizeof(buf), "%04o", data_directory_mode);
11433 return buf;
11434}
11435
11436static bool
11437check_recovery_target_timeline(char **newval, void **extra, GucSource source)
11438{
11439 RecoveryTargetTimeLineGoal rttg;
11440 RecoveryTargetTimeLineGoal *myextra;
11441
11442 if (strcmp(*newval, "current") == 0)
11443 rttg = RECOVERY_TARGET_TIMELINE_CONTROLFILE;
11444 else if (strcmp(*newval, "latest") == 0)
11445 rttg = RECOVERY_TARGET_TIMELINE_LATEST;
11446 else
11447 {
11448 rttg = RECOVERY_TARGET_TIMELINE_NUMERIC;
11449
11450 errno = 0;
11451 strtoul(*newval, NULL, 0);
11452 if (errno == EINVAL || errno == ERANGE)
11453 {
11454 GUC_check_errdetail("recovery_target_timeline is not a valid number.");
11455 return false;
11456 }
11457 }
11458
11459 myextra = (RecoveryTargetTimeLineGoal *) guc_malloc(ERROR, sizeof(RecoveryTargetTimeLineGoal));
11460 *myextra = rttg;
11461 *extra = (void *) myextra;
11462
11463 return true;
11464}
11465
11466static void
11467assign_recovery_target_timeline(const char *newval, void *extra)
11468{
11469 recoveryTargetTimeLineGoal = *((RecoveryTargetTimeLineGoal *) extra);
11470 if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_NUMERIC)
11471 recoveryTargetTLIRequested = (TimeLineID) strtoul(newval, NULL, 0);
11472 else
11473 recoveryTargetTLIRequested = 0;
11474}
11475
11476/*
11477 * Recovery target settings: Only one of the several recovery_target* settings
11478 * may be set. Setting a second one results in an error. The global variable
11479 * recoveryTarget tracks which kind of recovery target was chosen. Other
11480 * variables store the actual target value (for example a string or a xid).
11481 * The assign functions of the parameters check whether a competing parameter
11482 * was already set. But we want to allow setting the same parameter multiple
11483 * times. We also want to allow unsetting a parameter and setting a different
11484 * one, so we unset recoveryTarget when the parameter is set to an empty
11485 * string.
11486 */
11487
11488static void
11489pg_attribute_noreturn()
11490error_multiple_recovery_targets(void)
11491{
11492 ereport(ERROR,
11493 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11494 errmsg("multiple recovery targets specified"),
11495 errdetail("At most one of recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid may be set.")));
11496}
11497
11498static bool
11499check_recovery_target(char **newval, void **extra, GucSource source)
11500{
11501 if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
11502 {
11503 GUC_check_errdetail("The only allowed value is \"immediate\".");
11504 return false;
11505 }
11506 return true;
11507}
11508
11509static void
11510assign_recovery_target(const char *newval, void *extra)
11511{
11512 if (recoveryTarget != RECOVERY_TARGET_UNSET &&
11513 recoveryTarget != RECOVERY_TARGET_IMMEDIATE)
11514 error_multiple_recovery_targets();
11515
11516 if (newval && strcmp(newval, "") != 0)
11517 recoveryTarget = RECOVERY_TARGET_IMMEDIATE;
11518 else
11519 recoveryTarget = RECOVERY_TARGET_UNSET;
11520}
11521
11522static bool
11523check_recovery_target_xid(char **newval, void **extra, GucSource source)
11524{
11525 if (strcmp(*newval, "") != 0)
11526 {
11527 TransactionId xid;
11528 TransactionId *myextra;
11529
11530 errno = 0;
11531 xid = (TransactionId) strtoul(*newval, NULL, 0);
11532 if (errno == EINVAL || errno == ERANGE)
11533 return false;
11534
11535 myextra = (TransactionId *) guc_malloc(ERROR, sizeof(TransactionId));
11536 *myextra = xid;
11537 *extra = (void *) myextra;
11538 }
11539 return true;
11540}
11541
11542static void
11543assign_recovery_target_xid(const char *newval, void *extra)
11544{
11545 if (recoveryTarget != RECOVERY_TARGET_UNSET &&
11546 recoveryTarget != RECOVERY_TARGET_XID)
11547 error_multiple_recovery_targets();
11548
11549 if (newval && strcmp(newval, "") != 0)
11550 {
11551 recoveryTarget = RECOVERY_TARGET_XID;
11552 recoveryTargetXid = *((TransactionId *) extra);
11553 }
11554 else
11555 recoveryTarget = RECOVERY_TARGET_UNSET;
11556}
11557
11558/*
11559 * The interpretation of the recovery_target_time string can depend on the
11560 * time zone setting, so we need to wait until after all GUC processing is
11561 * done before we can do the final parsing of the string. This check function
11562 * only does a parsing pass to catch syntax errors, but we store the string
11563 * and parse it again when we need to use it.
11564 */
11565static bool
11566check_recovery_target_time(char **newval, void **extra, GucSource source)
11567{
11568 if (strcmp(*newval, "") != 0)
11569 {
11570 /* reject some special values */
11571 if (strcmp(*newval, "now") == 0 ||
11572 strcmp(*newval, "today") == 0 ||
11573 strcmp(*newval, "tomorrow") == 0 ||
11574 strcmp(*newval, "yesterday") == 0)
11575 {
11576 return false;
11577 }
11578
11579 /*
11580 * parse timestamp value (see also timestamptz_in())
11581 */
11582 {
11583 char *str = *newval;
11584 fsec_t fsec;
11585 struct pg_tm tt,
11586 *tm = &tt;
11587 int tz;
11588 int dtype;
11589 int nf;
11590 int dterr;
11591 char *field[MAXDATEFIELDS];
11592 int ftype[MAXDATEFIELDS];
11593 char workbuf[MAXDATELEN + MAXDATEFIELDS];
11594 TimestampTz timestamp;
11595
11596 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
11597 field, ftype, MAXDATEFIELDS, &nf);
11598 if (dterr == 0)
11599 dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz);
11600 if (dterr != 0)
11601 return false;
11602 if (dtype != DTK_DATE)
11603 return false;
11604
11605 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
11606 {
11607 GUC_check_errdetail("timestamp out of range: \"%s\"", str);
11608 return false;
11609 }
11610 }
11611 }
11612 return true;
11613}
11614
11615static void
11616assign_recovery_target_time(const char *newval, void *extra)
11617{
11618 if (recoveryTarget != RECOVERY_TARGET_UNSET &&
11619 recoveryTarget != RECOVERY_TARGET_TIME)
11620 error_multiple_recovery_targets();
11621
11622 if (newval && strcmp(newval, "") != 0)
11623 recoveryTarget = RECOVERY_TARGET_TIME;
11624 else
11625 recoveryTarget = RECOVERY_TARGET_UNSET;
11626}
11627
11628static bool
11629check_recovery_target_name(char **newval, void **extra, GucSource source)
11630{
11631 /* Use the value of newval directly */
11632 if (strlen(*newval) >= MAXFNAMELEN)
11633 {
11634 GUC_check_errdetail("%s is too long (maximum %d characters).",
11635 "recovery_target_name", MAXFNAMELEN - 1);
11636 return false;
11637 }
11638 return true;
11639}
11640
11641static void
11642assign_recovery_target_name(const char *newval, void *extra)
11643{
11644 if (recoveryTarget != RECOVERY_TARGET_UNSET &&
11645 recoveryTarget != RECOVERY_TARGET_NAME)
11646 error_multiple_recovery_targets();
11647
11648 if (newval && strcmp(newval, "") != 0)
11649 {
11650 recoveryTarget = RECOVERY_TARGET_NAME;
11651 recoveryTargetName = newval;
11652 }
11653 else
11654 recoveryTarget = RECOVERY_TARGET_UNSET;
11655}
11656
11657static bool
11658check_recovery_target_lsn(char **newval, void **extra, GucSource source)
11659{
11660 if (strcmp(*newval, "") != 0)
11661 {
11662 XLogRecPtr lsn;
11663 XLogRecPtr *myextra;
11664 bool have_error = false;
11665
11666 lsn = pg_lsn_in_internal(*newval, &have_error);
11667 if (have_error)
11668 return false;
11669
11670 myextra = (XLogRecPtr *) guc_malloc(ERROR, sizeof(XLogRecPtr));
11671 *myextra = lsn;
11672 *extra = (void *) myextra;
11673 }
11674 return true;
11675}
11676
11677static void
11678assign_recovery_target_lsn(const char *newval, void *extra)
11679{
11680 if (recoveryTarget != RECOVERY_TARGET_UNSET &&
11681 recoveryTarget != RECOVERY_TARGET_LSN)
11682 error_multiple_recovery_targets();
11683
11684 if (newval && strcmp(newval, "") != 0)
11685 {
11686 recoveryTarget = RECOVERY_TARGET_LSN;
11687 recoveryTargetLSN = *((XLogRecPtr *) extra);
11688 }
11689 else
11690 recoveryTarget = RECOVERY_TARGET_UNSET;
11691}
11692
11693static bool
11694check_primary_slot_name(char **newval, void **extra, GucSource source)
11695{
11696 if (*newval && strcmp(*newval, "") != 0 &&
11697 !ReplicationSlotValidateName(*newval, WARNING))
11698 return false;
11699
11700 return true;
11701}
11702
11703static bool
11704check_default_with_oids(bool *newval, void **extra, GucSource source)
11705{
11706 if (*newval)
11707 {
11708 /* check the GUC's definition for an explanation */
11709 GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
11710 GUC_check_errmsg("tables declared WITH OIDS are not supported");
11711
11712 return false;
11713 }
11714
11715 return true;
11716}
11717
11718#include "guc-file.c"
11719