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