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