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