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