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