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