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