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