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 "e_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 ¶llel_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 ¶llel_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 ¶llel_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, ×tamp) != 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