guc.c 166.4 KB
Newer Older
1 2 3 4 5
/*--------------------------------------------------------------------
 * guc.c
 *
 * Support for grand unified configuration scheme, including SET
 * command, configuration file, and command line options.
6
 * See src/backend/utils/misc/README for more information.
7 8
 *
 *
9
 * Copyright (c) 2000-2007, PostgreSQL Global Development Group
10
 * Written by Peter Eisentraut <peter_e@gmx.net>.
11 12
 *
 * IDENTIFICATION
13
 *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.391 2007/05/08 16:33:51 petere Exp $
14
 *
15 16 17 18
 *--------------------------------------------------------------------
 */
#include "postgres.h"

19
#include <ctype.h>
20 21 22
#include <float.h>
#include <limits.h>
#include <unistd.h>
23
#include <sys/stat.h>
24 25 26
#ifdef HAVE_SYSLOG
#include <syslog.h>
#endif
27 28


29
#include "access/gin.h"
30
#include "access/transam.h"
31
#include "access/twophase.h"
32
#include "access/xact.h"
33
#include "catalog/namespace.h"
34
#include "commands/async.h"
35
#include "commands/prepare.h"
36
#include "commands/vacuum.h"
37
#include "commands/variable.h"
38
#include "commands/trigger.h"
39
#include "funcapi.h"
40
#include "libpq/auth.h"
41
#include "libpq/pqformat.h"
42 43 44 45
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "optimizer/geqo.h"
#include "optimizer/paths.h"
46
#include "optimizer/planmain.h"
47
#include "parser/gramparse.h"
48
#include "parser/parse_expr.h"
49
#include "parser/parse_relation.h"
50
#include "parser/parse_type.h"
51
#include "parser/scansup.h"
52
#include "pgstat.h"
53
#include "postmaster/autovacuum.h"
54 55
#include "postmaster/bgwriter.h"
#include "postmaster/postmaster.h"
56
#include "postmaster/syslogger.h"
57
#include "storage/fd.h"
58
#include "storage/freespace.h"
59
#include "tcop/tcopprot.h"
60
#include "utils/builtins.h"
61
#include "utils/guc_tables.h"
62
#include "utils/memutils.h"
63
#include "utils/pg_locale.h"
64
#include "utils/plancache.h"
65
#include "utils/portal.h"
66
#include "utils/ps_status.h"
67
#include "utils/tzparser.h"
68
#include "utils/xml.h"
69

70 71 72
#ifndef PG_KRB_SRVTAB
#define PG_KRB_SRVTAB ""
#endif
B
 
Bruce Momjian 已提交
73 74 75
#ifndef PG_KRB_SRVNAM
#define PG_KRB_SRVNAM ""
#endif
76

B
Bruce Momjian 已提交
77
#define CONFIG_FILENAME "postgresql.conf"
78 79
#define HBA_FILENAME	"pg_hba.conf"
#define IDENT_FILENAME	"pg_ident.conf"
80

B
Bruce Momjian 已提交
81 82
#ifdef EXEC_BACKEND
#define CONFIG_EXEC_PARAMS "global/config_exec_params"
83
#define CONFIG_EXEC_PARAMS_NEW "global/config_exec_params.new"
B
Bruce Momjian 已提交
84
#endif
85

86 87 88 89 90 91 92
/* upper limit for GUC variables measured in kilobytes of memory */
#if SIZEOF_SIZE_T > 4
#define MAX_KILOBYTES	INT_MAX
#else
#define MAX_KILOBYTES	(INT_MAX / 1024)
#endif

93 94 95 96 97 98 99 100
#define KB_PER_MB (1024)
#define KB_PER_GB (1024*1024)

#define MS_PER_S 1000
#define MS_PER_MIN (1000 * 60)
#define MS_PER_H (1000 * 60 * 60)
#define MS_PER_D (1000 * 60 * 60 * 24)

101
/* XXX these should appear in other modules' header files */
102
extern bool Log_disconnections;
B
Bruce Momjian 已提交
103 104
extern int	CommitDelay;
extern int	CommitSiblings;
105
extern char *default_tablespace;
B
Bruce Momjian 已提交
106 107
extern bool fullPageWrites;

108
#ifdef TRACE_SORT
B
Bruce Momjian 已提交
109
extern bool trace_sort;
110
#endif
111 112 113
#ifdef DEBUG_BOUNDED_SORT
extern bool optimize_bounded_sort;
#endif
114

T
Tom Lane 已提交
115 116 117 118 119
#ifdef USE_SSL
extern char *SSLCipherSuites;
#endif


120
static const char *assign_log_destination(const char *value,
B
Bruce Momjian 已提交
121
					   bool doit, GucSource source);
122

T
Tatsuo Ishii 已提交
123
#ifdef HAVE_SYSLOG
124
static int	syslog_facility = LOG_LOCAL0;
125

126
static const char *assign_syslog_facility(const char *facility,
B
Bruce Momjian 已提交
127
					   bool doit, GucSource source);
128
static const char *assign_syslog_ident(const char *ident,
B
Bruce Momjian 已提交
129
					bool doit, GucSource source);
130
#endif
131

132 133
static const char *assign_defaultxactisolevel(const char *newval, bool doit,
						   GucSource source);
134 135
static const char *assign_session_replication_role(const char *newval, bool doit,
						   GucSource source);
136
static const char *assign_log_min_messages(const char *newval, bool doit,
B
Bruce Momjian 已提交
137
						GucSource source);
138
static const char *assign_client_min_messages(const char *newval,
139
						   bool doit, GucSource source);
140
static const char *assign_min_error_statement(const char *newval, bool doit,
141
						   GucSource source);
142
static const char *assign_msglvl(int *var, const char *newval, bool doit,
B
Bruce Momjian 已提交
143
			  GucSource source);
144
static const char *assign_log_error_verbosity(const char *newval, bool doit,
145
						   GucSource source);
146
static const char *assign_log_statement(const char *newval, bool doit,
B
Bruce Momjian 已提交
147
					 GucSource source);
148
static const char *show_num_temp_buffers(void);
149
static bool assign_phony_autocommit(bool newval, bool doit, GucSource source);
150
static const char *assign_custom_variable_classes(const char *newval, bool doit,
B
Bruce Momjian 已提交
151
							   GucSource source);
152
static bool assign_debug_assertions(bool newval, bool doit, GucSource source);
153
static bool assign_ssl(bool newval, bool doit, GucSource source);
154 155
static bool assign_stage_log_stats(bool newval, bool doit, GucSource source);
static bool assign_log_stats(bool newval, bool doit, GucSource source);
156
static bool assign_transaction_read_only(bool newval, bool doit, GucSource source);
157
static const char *assign_canonical_path(const char *newval, bool doit, GucSource source);
158
static const char *assign_backslash_quote(const char *newval, bool doit, GucSource source);
159
static const char *assign_timezone_abbreviations(const char *newval, bool doit, GucSource source);
160
static const char *assign_xmlbinary(const char *newval, bool doit, GucSource source);
161
static const char *assign_xmloption(const char *newval, bool doit, GucSource source);
162

163 164 165 166 167 168
static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_count(int newval, bool doit, GucSource source);
static const char *show_tcp_keepalives_idle(void);
static const char *show_tcp_keepalives_interval(void);
static const char *show_tcp_keepalives_count(void);
169 170
static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source);
static bool assign_maxconnections(int newval, bool doit, GucSource source);
171

172 173
/*
 * GUC option variables that are exported from this module
174
 */
175
#ifdef USE_ASSERT_CHECKING
B
Bruce Momjian 已提交
176
bool		assert_enabled = true;
177 178 179
#else
bool		assert_enabled = false;
#endif
B
Rename:  
Bruce Momjian 已提交
180
bool		log_duration = false;
B
Bruce Momjian 已提交
181 182 183 184
bool		Debug_print_plan = false;
bool		Debug_print_parse = false;
bool		Debug_print_rewritten = false;
bool		Debug_pretty_print = false;
185
bool		Explain_pretty_print = true;
186

B
Rename:  
Bruce Momjian 已提交
187 188 189
bool		log_parser_stats = false;
bool		log_planner_stats = false;
bool		log_executor_stats = false;
B
Bruce Momjian 已提交
190 191
bool		log_statement_stats = false;		/* this is sort of all three
												 * above together */
192
bool		log_btree_build_stats = false;
193

194 195
bool		check_function_bodies = true;
bool		default_with_oids = false;
B
Bruce Momjian 已提交
196
bool		SQL_inheritance = true;
197

198
bool		Password_encryption = true;
199

200
int			log_min_error_statement = ERROR;
201
int			log_min_messages = NOTICE;
202
int			client_min_messages = NOTICE;
203
int			log_min_duration_statement = -1;
204
int			log_temp_files = -1;
205

206 207
int			num_temp_buffers = 1000;

208 209 210 211
char	   *ConfigFileName;
char	   *HbaFileName;
char	   *IdentFileName;
char	   *external_pid_file;
212

B
Bruce Momjian 已提交
213 214 215
int			tcp_keepalives_idle;
int			tcp_keepalives_interval;
int			tcp_keepalives_count;
216

217 218 219 220 221
/*
 * These variables are all dummies that don't do anything, except in some
 * cases provide the value for SHOW to display.  The real state is elsewhere
 * and is kept in sync by assign_hooks.
 */
222
static char *client_min_messages_str;
223 224
static char *log_min_messages_str;
static char *log_error_verbosity_str;
225
static char *log_statement_str;
226
static char *log_min_error_statement_str;
227
static char *log_destination_string;
B
Bruce Momjian 已提交
228

229
#ifdef HAVE_SYSLOG
230 231
static char *syslog_facility_str;
static char *syslog_ident_str;
232
#endif
233
static bool phony_autocommit;
234
static bool session_auth_is_superuser;
235
static double phony_random_seed;
236
static char *backslash_quote_string;
237 238 239
static char *client_encoding_string;
static char *datestyle_string;
static char *default_iso_level_string;
240
static char *session_replication_role_string;
241 242
static char *locale_collate;
static char *locale_ctype;
243
static char *regex_flavor_string;
244
static char *server_encoding_string;
245
static char *server_version_string;
B
Bruce Momjian 已提交
246
static int	server_version_num;
247
static char *timezone_string;
248
static char *timezone_abbreviations_string;
249
static char *XactIsoLevel_string;
250
static char *data_directory;
251
static char *custom_variable_classes;
252
static char *xmlbinary_string;
253
static char *xmloption_string;
254 255 256 257
static int	max_function_args;
static int	max_index_keys;
static int	max_identifier_length;
static int	block_size;
B
Bruce Momjian 已提交
258
static bool integer_datetimes;
B
Bruce Momjian 已提交
259

260 261
/* should be static, but commands/variable.c needs to get at these */
char	   *role_string;
B
Bruce Momjian 已提交
262
char	   *session_authorization_string;
263

264

265
/*
266 267 268
 * Displayable names for context types (enum GucContext)
 *
 * Note: these strings are deliberately not localized.
269
 */
B
Bruce Momjian 已提交
270
const char *const GucContext_Names[] =
271
{
B
Bruce Momjian 已提交
272 273 274 275 276 277
	 /* PGC_INTERNAL */ "internal",
	 /* PGC_POSTMASTER */ "postmaster",
	 /* PGC_SIGHUP */ "sighup",
	 /* PGC_BACKEND */ "backend",
	 /* PGC_SUSET */ "superuser",
	 /* PGC_USERSET */ "user"
278 279 280 281 282 283
};

/*
 * Displayable names for source types (enum GucSource)
 *
 * Note: these strings are deliberately not localized.
B
Bruce Momjian 已提交
284 285
 */
const char *const GucSource_Names[] =
286
{
B
Bruce Momjian 已提交
287 288 289 290 291 292 293 294 295 296 297
	 /* PGC_S_DEFAULT */ "default",
	 /* PGC_S_ENV_VAR */ "environment variable",
	 /* PGC_S_FILE */ "configuration file",
	 /* PGC_S_ARGV */ "command line",
	 /* PGC_S_DATABASE */ "database",
	 /* PGC_S_USER */ "user",
	 /* PGC_S_CLIENT */ "client",
	 /* PGC_S_OVERRIDE */ "override",
	 /* PGC_S_INTERACTIVE */ "interactive",
	 /* PGC_S_TEST */ "test",
	 /* PGC_S_SESSION */ "session"
298 299 300 301 302 303 304 305
};

/*
 * Displayable names for the groupings defined in enum config_group
 */
const char *const config_group_names[] =
{
	/* UNGROUPED */
306
	gettext_noop("Ungrouped"),
307 308
	/* FILE_LOCATIONS */
	gettext_noop("File Locations"),
309
	/* CONN_AUTH */
310
	gettext_noop("Connections and Authentication"),
311
	/* CONN_AUTH_SETTINGS */
312
	gettext_noop("Connections and Authentication / Connection Settings"),
313
	/* CONN_AUTH_SECURITY */
314
	gettext_noop("Connections and Authentication / Security and Authentication"),
315
	/* RESOURCES */
316
	gettext_noop("Resource Usage"),
317
	/* RESOURCES_MEM */
318
	gettext_noop("Resource Usage / Memory"),
319
	/* RESOURCES_FSM */
320
	gettext_noop("Resource Usage / Free Space Map"),
321
	/* RESOURCES_KERNEL */
322
	gettext_noop("Resource Usage / Kernel Resources"),
323
	/* WAL */
324
	gettext_noop("Write-Ahead Log"),
325
	/* WAL_SETTINGS */
326
	gettext_noop("Write-Ahead Log / Settings"),
327
	/* WAL_CHECKPOINTS */
328
	gettext_noop("Write-Ahead Log / Checkpoints"),
329
	/* QUERY_TUNING */
330
	gettext_noop("Query Tuning"),
331
	/* QUERY_TUNING_METHOD */
332
	gettext_noop("Query Tuning / Planner Method Configuration"),
333
	/* QUERY_TUNING_COST */
334
	gettext_noop("Query Tuning / Planner Cost Constants"),
335
	/* QUERY_TUNING_GEQO */
336
	gettext_noop("Query Tuning / Genetic Query Optimizer"),
337
	/* QUERY_TUNING_OTHER */
338
	gettext_noop("Query Tuning / Other Planner Options"),
339
	/* LOGGING */
340
	gettext_noop("Reporting and Logging"),
341 342
	/* LOGGING_WHERE */
	gettext_noop("Reporting and Logging / Where to Log"),
343
	/* LOGGING_WHEN */
344
	gettext_noop("Reporting and Logging / When to Log"),
345
	/* LOGGING_WHAT */
346
	gettext_noop("Reporting and Logging / What to Log"),
347
	/* STATS */
348
	gettext_noop("Statistics"),
349
	/* STATS_MONITORING */
350
	gettext_noop("Statistics / Monitoring"),
351
	/* STATS_COLLECTOR */
352
	gettext_noop("Statistics / Query and Index Statistics Collector"),
353
	/* AUTOVACUUM */
354
	gettext_noop("Autovacuum"),
355
	/* CLIENT_CONN */
356
	gettext_noop("Client Connection Defaults"),
357
	/* CLIENT_CONN_STATEMENT */
358
	gettext_noop("Client Connection Defaults / Statement Behavior"),
359
	/* CLIENT_CONN_LOCALE */
360
	gettext_noop("Client Connection Defaults / Locale and Formatting"),
361
	/* CLIENT_CONN_OTHER */
362
	gettext_noop("Client Connection Defaults / Other Defaults"),
363
	/* LOCK_MANAGEMENT */
364
	gettext_noop("Lock Management"),
365
	/* COMPAT_OPTIONS */
366
	gettext_noop("Version and Platform Compatibility"),
367
	/* COMPAT_OPTIONS_PREVIOUS */
368
	gettext_noop("Version and Platform Compatibility / Previous PostgreSQL Versions"),
369
	/* COMPAT_OPTIONS_CLIENT */
370
	gettext_noop("Version and Platform Compatibility / Other Platforms and Clients"),
371 372 373 374
	/* PRESET_OPTIONS */
	gettext_noop("Preset Options"),
	/* CUSTOM_OPTIONS */
	gettext_noop("Customized Options"),
375
	/* DEVELOPER_OPTIONS */
376
	gettext_noop("Developer Options"),
377
	/* help_config wants this array to be null-terminated */
378 379 380
	NULL
};

381 382 383 384 385
/*
 * Displayable names for GUC variable types (enum config_type)
 *
 * Note: these strings are deliberately not localized.
 */
B
Bruce Momjian 已提交
386
const char *const config_type_names[] =
387
{
B
Bruce Momjian 已提交
388 389 390 391
	 /* PGC_BOOL */ "bool",
	 /* PGC_INT */ "integer",
	 /* PGC_REAL */ "real",
	 /* PGC_STRING */ "string"
392 393
};

394

395
/*
396 397 398 399
 * Contents of GUC tables
 *
 * See src/backend/utils/misc/README for design notes.
 *
400 401 402
 * TO ADD AN OPTION:
 *
 * 1. Declare a global variable of type bool, int, double, or char*
B
Bruce Momjian 已提交
403
 *	  and make use of it.
404 405
 *
 * 2. Decide at what times it's safe to set the option. See guc.h for
B
Bruce Momjian 已提交
406
 *	  details.
407 408
 *
 * 3. Decide on a name, a default value, upper and lower bounds (if
B
Bruce Momjian 已提交
409
 *	  applicable), etc.
410 411 412
 *
 * 4. Add a record below.
 *
413
 * 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
B
Bruce Momjian 已提交
414
 *	  appropriate
415
 *
416
 * 6. Add it to src/bin/psql/tab-complete.c, if it's a USERSET option.
417
 *
418
 * 7. Don't forget to document the option.
419 420
 *
 * 8. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure
B
Bruce Momjian 已提交
421
 *	  it is not single quoted at dump time.
422 423
 */

424

425
/******** option records follow ********/
426

427
static struct config_bool ConfigureNamesBool[] =
428
{
429
	{
430
		{"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
431
			gettext_noop("Enables the planner's use of sequential-scan plans."),
432 433 434
			NULL
		},
		&enable_seqscan,
435
		true, NULL, NULL
436
	},
437
	{
438
		{"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
439
			gettext_noop("Enables the planner's use of index-scan plans."),
440 441 442
			NULL
		},
		&enable_indexscan,
443
		true, NULL, NULL
444
	},
445 446 447 448 449 450 451 452
	{
		{"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
			gettext_noop("Enables the planner's use of bitmap-scan plans."),
			NULL
		},
		&enable_bitmapscan,
		true, NULL, NULL
	},
453
	{
454
		{"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
455
			gettext_noop("Enables the planner's use of TID scan plans."),
456 457 458
			NULL
		},
		&enable_tidscan,
459
		true, NULL, NULL
460 461
	},
	{
462
		{"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
463
			gettext_noop("Enables the planner's use of explicit sort steps."),
464 465 466
			NULL
		},
		&enable_sort,
467
		true, NULL, NULL
468
	},
469
	{
470
		{"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
471
			gettext_noop("Enables the planner's use of hashed aggregation plans."),
472 473 474
			NULL
		},
		&enable_hashagg,
475 476
		true, NULL, NULL
	},
477
	{
478
		{"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
479
			gettext_noop("Enables the planner's use of nested-loop join plans."),
480 481 482
			NULL
		},
		&enable_nestloop,
483
		true, NULL, NULL
484 485
	},
	{
486
		{"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
487
			gettext_noop("Enables the planner's use of merge join plans."),
488 489 490
			NULL
		},
		&enable_mergejoin,
491
		true, NULL, NULL
492 493
	},
	{
494
		{"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
495
			gettext_noop("Enables the planner's use of hash join plans."),
496 497 498
			NULL
		},
		&enable_hashjoin,
499
		true, NULL, NULL
500
	},
501
	{
502
		{"constraint_exclusion", PGC_USERSET, QUERY_TUNING_OTHER,
503 504
			gettext_noop("Enables the planner to use constraints to optimize queries."),
			gettext_noop("Child table scans will be skipped if their "
505
					   "constraints guarantee that no rows match the query.")
506
		},
507
		&constraint_exclusion,
508 509
		false, NULL, NULL
	},
510
	{
511
		{"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
512
			gettext_noop("Enables genetic query optimization."),
513
			gettext_noop("This algorithm attempts to do planning without "
514
						 "exhaustive searching.")
515 516
		},
		&enable_geqo,
517
		true, NULL, NULL
518
	},
519
	{
520 521
		/* Not for general use --- used by SET SESSION AUTHORIZATION */
		{"is_superuser", PGC_INTERNAL, UNGROUPED,
522
			gettext_noop("Shows whether the current user is a superuser."),
523 524 525
			NULL,
			GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
526 527 528
		&session_auth_is_superuser,
		false, NULL, NULL
	},
529
	{
530
		{"ssl", PGC_POSTMASTER, CONN_AUTH_SECURITY,
531
			gettext_noop("Enables SSL connections."),
532 533 534
			NULL
		},
		&EnableSSL,
535
		false, assign_ssl, NULL
536 537
	},
	{
538
		{"fsync", PGC_SIGHUP, WAL_SETTINGS,
539
			gettext_noop("Forces synchronization of updates to disk."),
540
			gettext_noop("The server will use the fsync() system call in several places to make "
541
			"sure that updates are physically written to disk. This insures "
542
						 "that a database cluster will recover to a consistent state after "
543
						 "an operating system or hardware crash.")
544 545
		},
		&enableFsync,
546
		true, NULL, NULL
547
	},
548
	{
549
		{"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
550
			gettext_noop("Continues processing past damaged page headers."),
551
			gettext_noop("Detection of a damaged page header normally causes PostgreSQL to "
B
Bruce Momjian 已提交
552
				"report an error, aborting the current transaction. Setting "
553 554
						 "zero_damaged_pages to true causes the system to instead report a "
						 "warning, zero out the damaged page, and continue processing. This "
555
						 "behavior will destroy data, namely all the rows on the damaged page."),
556
			GUC_NOT_IN_SAMPLE
557 558
		},
		&zero_damaged_pages,
559 560
		false, NULL, NULL
	},
561 562 563 564
	{
		{"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
			gettext_noop("Writes full pages to WAL when first modified after a checkpoint."),
			gettext_noop("A page write in process during an operating system crash might be "
B
Bruce Momjian 已提交
565
						 "only partially written to disk.  During recovery, the row changes "
566
			  "stored in WAL are not enough to recover.  This option writes "
567 568 569 570 571 572
						 "pages when first modified after a checkpoint to WAL so full recovery "
						 "is possible.")
		},
		&fullPageWrites,
		true, NULL, NULL
	},
573
	{
574
		{"silent_mode", PGC_POSTMASTER, LOGGING_WHEN,
575
			gettext_noop("Runs the server silently."),
576
			gettext_noop("If this parameter is set, the server will automatically run in the "
B
Bruce Momjian 已提交
577
				 "background and any controlling terminals are dissociated.")
578 579
		},
		&SilentMode,
580
		false, NULL, NULL
581 582
	},
	{
583
		{"log_connections", PGC_BACKEND, LOGGING_WHAT,
584
			gettext_noop("Logs each successful connection."),
585 586 587
			NULL
		},
		&Log_connections,
588
		false, NULL, NULL
589
	},
590 591
	{
		{"log_disconnections", PGC_BACKEND, LOGGING_WHAT,
P
Peter Eisentraut 已提交
592
			gettext_noop("Logs end of a session, including duration."),
B
Bruce Momjian 已提交
593
			NULL
594 595 596 597
		},
		&Log_disconnections,
		false, NULL, NULL
	},
598
	{
599
		{"debug_assertions", PGC_USERSET, DEVELOPER_OPTIONS,
600
			gettext_noop("Turns on various assertion checks."),
601
			gettext_noop("This is a debugging aid."),
602 603 604
			GUC_NOT_IN_SAMPLE
		},
		&assert_enabled,
605 606 607 608
#ifdef USE_ASSERT_CHECKING
		true,
#else
		false,
609
#endif
610 611
		assign_debug_assertions, NULL
	},
612 613
	{
		/* currently undocumented, so don't show in SHOW ALL */
614
		{"exit_on_error", PGC_USERSET, UNGROUPED,
615
			gettext_noop("No description available."),
616 617 618 619
			NULL,
			GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
		},
		&ExitOnAnyError,
620 621
		false, NULL, NULL
	},
622
	{
623 624
		{"log_duration", PGC_SUSET, LOGGING_WHAT,
			gettext_noop("Logs the duration of each completed SQL statement."),
625 626 627
			NULL
		},
		&log_duration,
628
		false, NULL, NULL
629 630
	},
	{
631
		{"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
632
			gettext_noop("Prints the parse tree to the server log."),
633
			NULL
634 635
		},
		&Debug_print_parse,
636
		false, NULL, NULL
637 638
	},
	{
639
		{"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
640
			gettext_noop("Prints the parse tree after rewriting to server log."),
641 642 643
			NULL
		},
		&Debug_print_rewritten,
644
		false, NULL, NULL
645 646
	},
	{
647
		{"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
648
			gettext_noop("Prints the execution plan to server log."),
649 650 651
			NULL
		},
		&Debug_print_plan,
652
		false, NULL, NULL
653 654
	},
	{
655
		{"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
656
			gettext_noop("Indents parse and plan tree displays."),
657 658 659
			NULL
		},
		&Debug_pretty_print,
660
		false, NULL, NULL
661 662
	},
	{
663
		{"log_parser_stats", PGC_SUSET, STATS_MONITORING,
664
			gettext_noop("Writes parser performance statistics to the server log."),
665 666 667
			NULL
		},
		&log_parser_stats,
668
		false, assign_stage_log_stats, NULL
669 670
	},
	{
671
		{"log_planner_stats", PGC_SUSET, STATS_MONITORING,
672
			gettext_noop("Writes planner performance statistics to the server log."),
673 674 675
			NULL
		},
		&log_planner_stats,
676
		false, assign_stage_log_stats, NULL
677 678
	},
	{
679
		{"log_executor_stats", PGC_SUSET, STATS_MONITORING,
680
			gettext_noop("Writes executor performance statistics to the server log."),
681 682 683
			NULL
		},
		&log_executor_stats,
684
		false, assign_stage_log_stats, NULL
685 686
	},
	{
687
		{"log_statement_stats", PGC_SUSET, STATS_MONITORING,
688
			gettext_noop("Writes cumulative performance statistics to the server log."),
689 690 691
			NULL
		},
		&log_statement_stats,
692
		false, assign_log_stats, NULL
693
	},
694
#ifdef BTREE_BUILD_STATS
695
	{
696
		{"log_btree_build_stats", PGC_SUSET, DEVELOPER_OPTIONS,
697
			gettext_noop("No description available."),
698 699 700 701
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&log_btree_build_stats,
702
		false, NULL, NULL
703
	},
704 705
#endif

706
	{
707
		{"explain_pretty_print", PGC_USERSET, CLIENT_CONN_OTHER,
708
			gettext_noop("Uses the indented output format for EXPLAIN VERBOSE."),
709 710 711
			NULL
		},
		&Explain_pretty_print,
712
		true, NULL, NULL
713
	},
714
	{
715
		{"stats_start_collector", PGC_POSTMASTER, STATS_COLLECTOR,
716
			gettext_noop("Starts the server statistics-collection subprocess."),
717 718 719
			NULL
		},
		&pgstat_collect_startcollector,
720
		true, NULL, NULL
721 722
	},
	{
723
		{"stats_reset_on_server_start", PGC_POSTMASTER, STATS_COLLECTOR,
724
			gettext_noop("Zeroes collected statistics on server restart."),
725 726 727
			NULL
		},
		&pgstat_collect_resetonpmstart,
728
		false, NULL, NULL
729 730
	},
	{
731
		{"stats_row_level", PGC_SUSET, STATS_COLLECTOR,
732
			gettext_noop("Collects row-level statistics on database activity."),
733 734 735
			NULL
		},
		&pgstat_collect_tuplelevel,
736
		true, NULL, NULL
737 738
	},
	{
739
		{"stats_block_level", PGC_SUSET, STATS_COLLECTOR,
740
			gettext_noop("Collects block-level statistics on database activity."),
741 742 743
			NULL
		},
		&pgstat_collect_blocklevel,
744
		false, NULL, NULL
745
	},
746

747 748 749 750 751 752 753 754
	{
		{"stats_command_string", PGC_SUSET, STATS_COLLECTOR,
			gettext_noop("Collects information about executing commands."),
			gettext_noop("Enables the collection of information on the currently "
					"executing command of each session, along with the time "
						 "at which that command began execution.")
		},
		&pgstat_collect_querystring,
755
		true, NULL, NULL
756 757
	},

758 759 760
	{
		{"update_process_title", PGC_SUSET, STATS_COLLECTOR,
			gettext_noop("Updates the process title to show the active SQL command."),
761
			gettext_noop("Enables updating of the process title every time a new SQL command is received by the server.")
762 763 764 765 766
		},
		&update_process_title,
		true, NULL, NULL
	},

767 768
	{
		{"autovacuum", PGC_SIGHUP, AUTOVACUUM,
P
Peter Eisentraut 已提交
769
			gettext_noop("Starts the autovacuum subprocess."),
770 771 772
			NULL
		},
		&autovacuum_start_daemon,
773
		true, NULL, NULL
774 775
	},

776
	{
777
		{"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
778
			gettext_noop("Generates debugging output for LISTEN and NOTIFY."),
779 780 781 782
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&Trace_notify,
783
		false, NULL, NULL
784
	},
785 786

#ifdef LOCK_DEBUG
787
	{
788
		{"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
789
			gettext_noop("No description available."),
790 791 792 793
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&Trace_locks,
794
		false, NULL, NULL
795 796
	},
	{
797
		{"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
798
			gettext_noop("No description available."),
799 800 801 802
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&Trace_userlocks,
803
		false, NULL, NULL
804 805
	},
	{
806
		{"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
807
			gettext_noop("No description available."),
808 809 810 811
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&Trace_lwlocks,
812
		false, NULL, NULL
813 814
	},
	{
815
		{"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
816
			gettext_noop("No description available."),
817 818 819 820
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&Debug_deadlocks,
821
		false, NULL, NULL
822
	},
823 824
#endif

825 826 827 828 829 830 831 832
	{
		{"log_lock_waits", PGC_SIGHUP, LOGGING_WHAT,
			gettext_noop("Logs long lock wait events."),
			NULL
		},
		&log_lock_waits,
		false, NULL, NULL
	},
833
	{
834
		{"log_hostname", PGC_SIGHUP, LOGGING_WHAT,
835
			gettext_noop("Logs the host name in the connection logs."),
836 837
			gettext_noop("By default, connection logs only show the IP address "
						 "of the connecting host. If you want them to show the host name you "
B
Bruce Momjian 已提交
838 839
			  "can turn this on, but depending on your host name resolution "
			   "setup it might impose a non-negligible performance penalty.")
840 841
		},
		&log_hostname,
842
		false, NULL, NULL
843 844
	},
	{
845
		{"sql_inheritance", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
846
			gettext_noop("Causes subtables to be included by default in various commands."),
847
			NULL
848 849
		},
		&SQL_inheritance,
850
		true, NULL, NULL
851 852
	},
	{
853
		{"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
854
			gettext_noop("Encrypt passwords."),
855
			gettext_noop("When a password is specified in CREATE USER or "
B
Bruce Momjian 已提交
856
			   "ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
857
						 "this parameter determines whether the password is to be encrypted.")
858 859
		},
		&Password_encryption,
860
		true, NULL, NULL
861 862
	},
	{
863
		{"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
864
			gettext_noop("Treats \"expr=NULL\" as \"expr IS NULL\"."),
865
			gettext_noop("When turned on, expressions of the form expr = NULL "
B
Bruce Momjian 已提交
866 867 868
			   "(or NULL = expr) are treated as expr IS NULL, that is, they "
				"return true if expr evaluates to the null value, and false "
			   "otherwise. The correct behavior of expr = NULL is to always "
869
						 "return null (unknown).")
870 871
		},
		&Transform_null_equals,
872
		false, NULL, NULL
873
	},
874
	{
875
		{"db_user_namespace", PGC_SIGHUP, CONN_AUTH_SECURITY,
876
			gettext_noop("Enables per-database user names."),
877 878 879
			NULL
		},
		&Db_user_namespace,
880 881
		false, NULL, NULL
	},
882
	{
883 884
		/* only here for backwards compatibility */
		{"autocommit", PGC_USERSET, CLIENT_CONN_STATEMENT,
885 886
			gettext_noop("This parameter doesn't do anything."),
			gettext_noop("It's just here so that we won't choke on SET AUTOCOMMIT TO ON from 7.3-vintage clients."),
887 888 889
			GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
		},
		&phony_autocommit,
890
		true, assign_phony_autocommit, NULL
891
	},
892
	{
893
		{"default_transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
894
			gettext_noop("Sets the default read-only status of new transactions."),
895 896 897
			NULL
		},
		&DefaultXactReadOnly,
898 899 900
		false, NULL, NULL
	},
	{
901
		{"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
902
			gettext_noop("Sets the current transaction's read-only status."),
903 904 905 906
			NULL,
			GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
		&XactReadOnly,
907
		false, assign_transaction_read_only, NULL
908
	},
909
	{
910
		{"add_missing_from", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
911
			gettext_noop("Automatically adds missing table references to FROM clauses."),
912 913 914
			NULL
		},
		&add_missing_from,
915
		false, NULL, NULL
916
	},
917 918
	{
		{"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
919
			gettext_noop("Check function bodies during CREATE FUNCTION."),
920 921 922 923 924
			NULL
		},
		&check_function_bodies,
		true, NULL, NULL
	},
925 926 927 928
	{
		{"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
			gettext_noop("Enable input of NULL elements in arrays."),
			gettext_noop("When turned on, unquoted NULL in an array input "
P
Peter Eisentraut 已提交
929
						 "value means a null value; "
930 931 932 933 934
						 "otherwise it is taken literally.")
		},
		&Array_nulls,
		true, NULL, NULL
	},
935 936
	{
		{"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
937
			gettext_noop("Create new tables with OIDs by default."),
B
Bruce Momjian 已提交
938
			NULL
939 940
		},
		&default_with_oids,
941
		false, NULL, NULL
942
	},
943
	{
944
		{"redirect_stderr", PGC_POSTMASTER, LOGGING_WHERE,
P
Peter Eisentraut 已提交
945
			gettext_noop("Start a subprocess to capture stderr output into log files."),
B
Bruce Momjian 已提交
946
			NULL
947
		},
948
		&Redirect_stderr,
949 950
		false, NULL, NULL
	},
951 952
	{
		{"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
P
Peter Eisentraut 已提交
953
			gettext_noop("Truncate existing log files of same name during log rotation."),
954 955 956 957 958
			NULL
		},
		&Log_truncate_on_rotation,
		false, NULL, NULL
	},
959

960 961 962 963 964 965 966 967 968 969 970 971
#ifdef TRACE_SORT
	{
		{"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
			gettext_noop("Emit information about resource usage in sorting."),
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&trace_sort,
		false, NULL, NULL
	},
#endif

972 973 974 975 976 977 978 979 980 981 982 983 984 985
#ifdef DEBUG_BOUNDED_SORT
	/* this is undocumented because not exposed in a standard build */
	{
		{
			"optimize_bounded_sort", PGC_USERSET, QUERY_TUNING_METHOD,
			gettext_noop("Enable bounded sorting using heap sort."),
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&optimize_bounded_sort,
		true, NULL, NULL
	},
#endif

986 987 988 989 990 991 992 993 994 995 996 997
#ifdef WAL_DEBUG
	{
		{"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
			gettext_noop("Emit WAL-related debugging output."),
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&XLOG_DEBUG,
		false, NULL, NULL
	},
#endif

998
	{
999
		{"integer_datetimes", PGC_INTERNAL, PRESET_OPTIONS,
1000
			gettext_noop("Datetimes are integer based."),
1001
			NULL,
1002
			GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1003 1004 1005 1006 1007 1008 1009 1010 1011
		},
		&integer_datetimes,
#ifdef HAVE_INT64_TIMESTAMP
		true, NULL, NULL
#else
		false, NULL, NULL
#endif
	},

B
 
Bruce Momjian 已提交
1012 1013
	{
		{"krb_caseins_users", PGC_POSTMASTER, CONN_AUTH_SECURITY,
1014
			gettext_noop("Sets whether Kerberos user names should be treated as case-insensitive."),
B
 
Bruce Momjian 已提交
1015 1016 1017 1018 1019 1020
			NULL
		},
		&pg_krb_caseins_users,
		false, NULL, NULL
	},

1021 1022
	{
		{"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1023
			gettext_noop("Warn about backslash escapes in ordinary string literals."),
1024 1025 1026
			NULL
		},
		&escape_string_warning,
1027
		true, NULL, NULL
1028 1029 1030
	},

	{
1031
		{"standard_conforming_strings", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
1032
			gettext_noop("Causes '...' strings to treat backslashes literally."),
1033
			NULL,
1034
			GUC_REPORT
1035
		},
1036
		&standard_conforming_strings,
1037 1038 1039
		false, NULL, NULL
	},

1040
	{
1041
		{"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS,
B
Bruce Momjian 已提交
1042 1043 1044
			gettext_noop("Allows modifications of the structure of system tables."),
			NULL,
			GUC_NOT_IN_SAMPLE
1045 1046 1047 1048 1049 1050 1051
		},
		&allowSystemTableMods,
		false, NULL, NULL
	},

	{
		{"ignore_system_indexes", PGC_BACKEND, DEVELOPER_OPTIONS,
B
Bruce Momjian 已提交
1052 1053 1054 1055
			gettext_noop("Disables reading from system indexes."),
			gettext_noop("It does not prevent updating the indexes, so it is safe "
						 "to use.  The worst consequence is slowness."),
			GUC_NOT_IN_SAMPLE
1056 1057 1058 1059 1060
		},
		&IgnoreSystemIndexes,
		false, NULL, NULL
	},

1061
	/* End-of-list marker */
1062
	{
1063 1064
		{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL
	}
1065 1066 1067
};


1068
static struct config_int ConfigureNamesInt[] =
1069
{
1070 1071
	{
		{"archive_timeout", PGC_SIGHUP, WAL_SETTINGS,
B
Bruce Momjian 已提交
1072 1073 1074 1075
			gettext_noop("Forces a switch to the next xlog file if a "
						 "new file has not been started within N seconds."),
			NULL,
			GUC_UNIT_S
1076 1077 1078 1079
		},
		&XLogArchiveTimeout,
		0, 0, INT_MAX, NULL, NULL
	},
1080 1081
	{
		{"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
B
Bruce Momjian 已提交
1082 1083 1084
			gettext_noop("Waits N seconds on connection startup after authentication."),
			gettext_noop("This allows attaching a debugger to the process."),
			GUC_NOT_IN_SAMPLE | GUC_UNIT_S
1085 1086 1087 1088
		},
		&PostAuthDelay,
		0, 0, INT_MAX, NULL, NULL
	},
1089
	{
1090
		{"default_statistics_target", PGC_USERSET, QUERY_TUNING_OTHER,
1091
			gettext_noop("Sets the default statistics target."),
1092
			gettext_noop("This applies to table columns that have not had a "
B
Bruce Momjian 已提交
1093
				"column-specific target set via ALTER TABLE SET STATISTICS.")
1094 1095
		},
		&default_statistics_target,
1096 1097
		10, 1, 1000, NULL, NULL
	},
1098
	{
1099
		{"from_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
1100 1101
			gettext_noop("Sets the FROM-list size beyond which subqueries "
						 "are not collapsed."),
1102
			gettext_noop("The planner will merge subqueries into upper "
B
Bruce Momjian 已提交
1103
				"queries if the resulting FROM list would have no more than "
1104
						 "this many items.")
1105 1106
		},
		&from_collapse_limit,
1107 1108 1109
		8, 1, INT_MAX, NULL, NULL
	},
	{
1110
		{"join_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
1111 1112
			gettext_noop("Sets the FROM-list size beyond which JOIN "
						 "constructs are not flattened."),
1113
			gettext_noop("The planner will flatten explicit JOIN "
1114 1115
						 "constructs into lists of FROM items whenever a "
						 "list of no more than this many items would result.")
1116 1117
		},
		&join_collapse_limit,
1118 1119 1120
		8, 1, INT_MAX, NULL, NULL
	},
	{
1121
		{"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
1122
			gettext_noop("Sets the threshold of FROM items beyond which GEQO is used."),
1123 1124 1125
			NULL
		},
		&geqo_threshold,
1126
		12, 2, INT_MAX, NULL, NULL
1127
	},
1128
	{
1129 1130
		{"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
			gettext_noop("GEQO: effort is used to set the default for other GEQO parameters."),
1131 1132
			NULL
		},
1133 1134 1135 1136 1137 1138 1139 1140
		&Geqo_effort,
		DEFAULT_GEQO_EFFORT, MIN_GEQO_EFFORT, MAX_GEQO_EFFORT, NULL, NULL
	},
	{
		{"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
			gettext_noop("GEQO: number of individuals in the population."),
			gettext_noop("Zero selects a suitable default value.")
		},
1141
		&Geqo_pool_size,
1142
		0, 0, INT_MAX, NULL, NULL
1143 1144
	},
	{
1145
		{"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
1146
			gettext_noop("GEQO: number of iterations of the algorithm."),
1147
			gettext_noop("Zero selects a suitable default value.")
1148 1149
		},
		&Geqo_generations,
1150
		0, 0, INT_MAX, NULL, NULL
1151 1152 1153
	},

	{
1154
		{"deadlock_timeout", PGC_SIGHUP, LOCK_MANAGEMENT,
1155
			gettext_noop("Sets the time to wait on a lock before checking for deadlock."),
1156 1157
			NULL,
			GUC_UNIT_MS
1158 1159
		},
		&DeadlockTimeout,
1160
		1000, 0, INT_MAX, NULL, NULL
1161
	},
1162 1163

	/*
B
Bruce Momjian 已提交
1164 1165
	 * Note: There is some postprocessing done in PostmasterMain() to make
	 * sure the buffers are at least twice the number of backends, so the
1166
	 * constraints here are partially unused. Similarly, the superuser
B
Bruce Momjian 已提交
1167 1168
	 * reserved number is checked to ensure it is less than the max backends
	 * number.
1169 1170
	 *
	 * MaxBackends is limited to INT_MAX/4 because some places compute
1171 1172 1173 1174 1175
	 * 4*MaxBackends without any overflow check.  This check is made on
	 * assign_maxconnections, since MaxBackends is computed as MaxConnections +
	 * autovacuum_max_workers.
	 *
	 * Likewise we have to limit NBuffers to INT_MAX/2.
1176
	 */
1177
	{
1178
		{"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1179
			gettext_noop("Sets the maximum number of concurrent connections."),
1180 1181
			NULL
		},
1182 1183
		&MaxConnections,
		100, 1, INT_MAX / 4, assign_maxconnections, NULL
1184
	},
1185

1186
	{
1187
		{"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1188
			gettext_noop("Sets the number of connection slots reserved for superusers."),
1189 1190 1191
			NULL
		},
		&ReservedBackends,
1192
		3, 0, INT_MAX / 4, NULL, NULL
1193 1194
	},

1195
	{
1196
		{"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
1197
			gettext_noop("Sets the number of shared memory buffers used by the server."),
1198 1199
			NULL,
			GUC_UNIT_BLOCKS
1200 1201
		},
		&NBuffers,
1202
		1024, 16, INT_MAX / 2, NULL, NULL
1203
	},
1204

1205 1206 1207
	{
		{"temp_buffers", PGC_USERSET, RESOURCES_MEM,
			gettext_noop("Sets the maximum number of temporary buffers used by each session."),
1208 1209
			NULL,
			GUC_UNIT_BLOCKS
1210 1211
		},
		&num_temp_buffers,
1212
		1024, 100, INT_MAX / 2, NULL, show_num_temp_buffers
1213 1214
	},

1215
	{
1216
		{"port", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1217
			gettext_noop("Sets the TCP port the server listens on."),
1218 1219 1220
			NULL
		},
		&PostPortNumber,
1221
		DEF_PGPORT, 1, 65535, NULL, NULL
1222
	},
1223

1224
	{
1225
		{"unix_socket_permissions", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
1226
			gettext_noop("Sets the access permissions of the Unix-domain socket."),
1227
			gettext_noop("Unix-domain sockets use the usual Unix file system "
1228
						 "permission set. The parameter value is expected to be an numeric mode "
1229
						 "specification in the form accepted by the chmod and umask system "
1230 1231 1232 1233
						 "calls. (To use the customary octal format the number must start with "
						 "a 0 (zero).)")
		},
		&Unix_socket_permissions,
1234
		0777, 0000, 0777, NULL, NULL
1235
	},
1236

1237
	{
1238 1239
		{"work_mem", PGC_USERSET, RESOURCES_MEM,
			gettext_noop("Sets the maximum memory to be used for query workspaces."),
1240
			gettext_noop("This much memory can be used by each internal "
B
Bruce Momjian 已提交
1241
						 "sort operation and hash table before switching to "
1242 1243
						 "temporary disk files."),
			GUC_UNIT_KB
1244
		},
1245
		&work_mem,
1246
		1024, 8 * BLCKSZ / 1024, MAX_KILOBYTES, NULL, NULL
1247
	},
1248

1249
	{
1250 1251
		{"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
			gettext_noop("Sets the maximum memory to be used for maintenance operations."),
1252 1253
			gettext_noop("This includes operations such as VACUUM and CREATE INDEX."),
			GUC_UNIT_KB
1254
		},
1255
		&maintenance_work_mem,
1256
		16384, 1024, MAX_KILOBYTES, NULL, NULL
1257
	},
1258

1259 1260 1261
	{
		{"max_stack_depth", PGC_SUSET, RESOURCES_MEM,
			gettext_noop("Sets the maximum stack depth, in kilobytes."),
1262 1263
			NULL,
			GUC_UNIT_KB
1264 1265
		},
		&max_stack_depth,
1266
		100, 100, MAX_KILOBYTES, assign_max_stack_depth, NULL
1267 1268
	},

J
Jan Wieck 已提交
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
	{
		{"vacuum_cost_page_hit", PGC_USERSET, RESOURCES,
			gettext_noop("Vacuum cost for a page found in the buffer cache."),
			NULL
		},
		&VacuumCostPageHit,
		1, 0, 10000, NULL, NULL
	},

	{
		{"vacuum_cost_page_miss", PGC_USERSET, RESOURCES,
			gettext_noop("Vacuum cost for a page not found in the buffer cache."),
			NULL
		},
		&VacuumCostPageMiss,
		10, 0, 10000, NULL, NULL
	},

	{
		{"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES,
			gettext_noop("Vacuum cost for a page dirtied by vacuum."),
			NULL
		},
		&VacuumCostPageDirty,
		20, 0, 10000, NULL, NULL
	},

	{
		{"vacuum_cost_limit", PGC_USERSET, RESOURCES,
			gettext_noop("Vacuum cost amount available before napping."),
			NULL
		},
		&VacuumCostLimit,
		200, 1, 10000, NULL, NULL
	},

	{
1306 1307
		{"vacuum_cost_delay", PGC_USERSET, RESOURCES,
			gettext_noop("Vacuum cost delay in milliseconds."),
1308 1309
			NULL,
			GUC_UNIT_MS
J
Jan Wieck 已提交
1310
		},
1311
		&VacuumCostDelay,
1312
		0, 0, 1000, NULL, NULL
J
Jan Wieck 已提交
1313 1314
	},

1315 1316 1317
	{
		{"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
			gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
1318 1319
			NULL,
			GUC_UNIT_MS
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
		},
		&autovacuum_vac_cost_delay,
		-1, -1, 1000, NULL, NULL
	},

	{
		{"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
			gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
			NULL
		},
		&autovacuum_vac_cost_limit,
		-1, -1, 10000, NULL, NULL
	},

1334
	{
1335
		{"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
1336
			gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
1337 1338 1339
			NULL
		},
		&max_files_per_process,
1340
		1000, 25, INT_MAX, NULL, NULL
1341
	},
1342

1343 1344 1345 1346 1347 1348
	{
		{"max_prepared_transactions", PGC_POSTMASTER, RESOURCES,
			gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
			NULL
		},
		&max_prepared_xacts,
1349
		5, 0, INT_MAX, NULL, NULL
1350 1351
	},

1352
#ifdef LOCK_DEBUG
1353
	{
1354
		{"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
1355
			gettext_noop("No description available."),
1356 1357 1358 1359
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&Trace_lock_oidmin,
1360
		FirstNormalObjectId, 0, INT_MAX, NULL, NULL
1361 1362
	},
	{
1363
		{"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
1364
			gettext_noop("No description available."),
1365 1366 1367 1368
			NULL,
			GUC_NOT_IN_SAMPLE
		},
		&Trace_lock_table,
1369
		0, 0, INT_MAX, NULL, NULL
1370
	},
1371 1372
#endif

1373
	{
1374
		{"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
1375
			gettext_noop("Sets the maximum allowed duration of any statement."),
1376 1377
			gettext_noop("A value of 0 turns off the timeout."),
			GUC_UNIT_MS
1378 1379
		},
		&StatementTimeout,
1380 1381 1382
		0, 0, INT_MAX, NULL, NULL
	},

1383 1384 1385 1386 1387 1388 1389 1390 1391
	{
		{"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
			gettext_noop("Minimum age at which VACUUM should freeze a table row."),
			NULL
		},
		&vacuum_freeze_min_age,
		100000000, 0, 1000000000, NULL, NULL
	},

1392
	{
1393
		{"max_fsm_relations", PGC_POSTMASTER, RESOURCES_FSM,
1394
			gettext_noop("Sets the maximum number of tables and indexes for which free space is tracked."),
1395 1396 1397
			NULL
		},
		&MaxFSMRelations,
1398
		1000, 100, INT_MAX, NULL, NULL
1399 1400
	},
	{
1401
		{"max_fsm_pages", PGC_POSTMASTER, RESOURCES_FSM,
1402
			gettext_noop("Sets the maximum number of disk pages for which free space is tracked."),
1403 1404 1405
			NULL
		},
		&MaxFSMPages,
1406
		20000, 1000, INT_MAX, NULL, NULL
1407
	},
1408

1409
	{
1410
		{"max_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
1411
			gettext_noop("Sets the maximum number of locks per transaction."),
1412
			gettext_noop("The shared lock table is sized on the assumption that "
B
Bruce Momjian 已提交
1413
			  "at most max_locks_per_transaction * max_connections distinct "
1414
						 "objects will need to be locked at any one time.")
1415 1416
		},
		&max_locks_per_xact,
1417
		64, 10, INT_MAX, NULL, NULL
1418
	},
1419

1420
	{
1421
		{"authentication_timeout", PGC_SIGHUP, CONN_AUTH_SECURITY,
1422
			gettext_noop("Sets the maximum allowed time to complete client authentication."),
1423 1424
			NULL,
			GUC_UNIT_S
1425 1426
		},
		&AuthenticationTimeout,
1427
		60, 1, 600, NULL, NULL
1428
	},
1429

1430
	{
1431 1432
		/* Not for general use */
		{"pre_auth_delay", PGC_SIGHUP, DEVELOPER_OPTIONS,
1433 1434
			gettext_noop("Waits N seconds on connection startup before authentication."),
			gettext_noop("This allows attaching a debugger to the process."),
1435
			GUC_NOT_IN_SAMPLE | GUC_UNIT_S
1436 1437
		},
		&PreAuthDelay,
1438
		0, 0, 60, NULL, NULL
1439
	},
1440

1441
	{
1442
		{"checkpoint_segments", PGC_SIGHUP, WAL_CHECKPOINTS,
1443
			gettext_noop("Sets the maximum distance in log segments between automatic WAL checkpoints."),
1444 1445 1446
			NULL
		},
		&CheckPointSegments,
1447
		3, 1, INT_MAX, NULL, NULL
1448
	},
T
Tom Lane 已提交
1449

1450
	{
1451
		{"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS,
1452
			gettext_noop("Sets the maximum time between automatic WAL checkpoints."),
1453 1454
			NULL,
			GUC_UNIT_S
1455 1456
		},
		&CheckPointTimeout,
1457
		300, 30, 3600, NULL, NULL
1458
	},
V
Vadim B. Mikheev 已提交
1459

1460
	{
1461
		{"checkpoint_warning", PGC_SIGHUP, WAL_CHECKPOINTS,
1462 1463
			gettext_noop("Enables warnings if checkpoint segments are filled more "
						 "frequently than this."),
1464
			gettext_noop("Write a message to the server log if checkpoints "
B
Bruce Momjian 已提交
1465
			"caused by the filling of checkpoint segment files happens more "
1466 1467
						 "frequently than this number of seconds. Zero turns off the warning."),
			GUC_UNIT_S
1468 1469
		},
		&CheckPointWarning,
1470 1471 1472
		30, 0, INT_MAX, NULL, NULL
	},

1473
	{
1474
		{"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
1475
			gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
1476 1477
			NULL,
			GUC_UNIT_XBLOCKS
1478 1479
		},
		&XLOGbuffers,
1480
		8, 4, INT_MAX, NULL, NULL
1481
	},
V
Vadim B. Mikheev 已提交
1482

1483
	{
1484
		{"commit_delay", PGC_USERSET, WAL_CHECKPOINTS,
1485 1486
			gettext_noop("Sets the delay in microseconds between transaction commit and "
						 "flushing WAL to disk."),
1487 1488 1489
			NULL
		},
		&CommitDelay,
1490
		0, 0, 100000, NULL, NULL
1491
	},
V
Vadim B. Mikheev 已提交
1492

1493
	{
1494
		{"commit_siblings", PGC_USERSET, WAL_CHECKPOINTS,
1495 1496
			gettext_noop("Sets the minimum concurrent open transactions before performing "
						 "commit_delay."),
1497 1498 1499
			NULL
		},
		&CommitSiblings,
1500
		5, 1, 1000, NULL, NULL
1501
	},
1502

1503
	{
1504
		{"extra_float_digits", PGC_USERSET, CLIENT_CONN_LOCALE,
1505
			gettext_noop("Sets the number of digits displayed for floating-point values."),
1506
			gettext_noop("This affects real, double precision, and geometric data types. "
B
Bruce Momjian 已提交
1507
			 "The parameter value is added to the standard number of digits "
1508
						 "(FLT_DIG or DBL_DIG as appropriate).")
1509 1510
		},
		&extra_float_digits,
1511 1512 1513
		0, -15, 2, NULL, NULL
	},

B
Bruce Momjian 已提交
1514
	{
1515
		{"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN,
1516
			gettext_noop("Sets the minimum execution time above which statements will "
1517
						 "be logged."),
1518 1519
			gettext_noop("Zero prints all queries. The default is -1 (turning this feature off)."),
			GUC_UNIT_MS
1520 1521
		},
		&log_min_duration_statement,
1522
		-1, -1, INT_MAX / 1000, NULL, NULL
B
Bruce Momjian 已提交
1523 1524
	},

1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
	{
		{"log_autovacuum", PGC_BACKEND, LOGGING_WHAT,
			gettext_noop("Sets the minimum execution time above which autovacuum actions "
						 "will be logged."),
			gettext_noop("Zero prints all actions.  The default is -1 (turning this feature off)."),
			GUC_UNIT_MS
		},
		&Log_autovacuum,
		-1, -1, INT_MAX / 1000, NULL, NULL
	},

J
Jan Wieck 已提交
1536 1537
	{
		{"bgwriter_delay", PGC_SIGHUP, RESOURCES,
1538
			gettext_noop("Background writer sleep time between rounds."),
1539 1540
			NULL,
			GUC_UNIT_MS
J
Jan Wieck 已提交
1541 1542
		},
		&BgWriterDelay,
1543
		200, 10, 10000, NULL, NULL
J
Jan Wieck 已提交
1544 1545 1546
	},

	{
1547
		{"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES,
1548
			gettext_noop("Background writer maximum number of LRU pages to flush per round."),
J
Jan Wieck 已提交
1549 1550
			NULL
		},
1551 1552
		&bgwriter_lru_maxpages,
		5, 0, 1000, NULL, NULL
J
Jan Wieck 已提交
1553 1554 1555
	},

	{
1556
		{"bgwriter_all_maxpages", PGC_SIGHUP, RESOURCES,
1557
			gettext_noop("Background writer maximum number of all pages to flush per round."),
J
Jan Wieck 已提交
1558 1559
			NULL
		},
1560 1561
		&bgwriter_all_maxpages,
		5, 0, 1000, NULL, NULL
J
Jan Wieck 已提交
1562 1563
	},

1564 1565
	{
		{"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
1566
			gettext_noop("Automatic log file rotation will occur after N minutes."),
1567 1568
			NULL,
			GUC_UNIT_MIN
1569 1570
		},
		&Log_RotationAge,
B
Bruce Momjian 已提交
1571
		HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / MINS_PER_HOUR, NULL, NULL
1572 1573 1574 1575
	},

	{
		{"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
1576
			gettext_noop("Automatic log file rotation will occur after N kilobytes."),
1577 1578
			NULL,
			GUC_UNIT_KB
1579 1580
		},
		&Log_RotationSize,
1581
		10 * 1024, 0, INT_MAX / 1024, NULL, NULL
1582 1583
	},

1584
	{
1585
		{"max_function_args", PGC_INTERNAL, PRESET_OPTIONS,
P
Peter Eisentraut 已提交
1586
			gettext_noop("Shows the maximum number of function arguments."),
1587 1588 1589 1590 1591 1592 1593 1594
			NULL,
			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
		&max_function_args,
		FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS, NULL, NULL
	},

	{
1595
		{"max_index_keys", PGC_INTERNAL, PRESET_OPTIONS,
P
Peter Eisentraut 已提交
1596
			gettext_noop("Shows the maximum number of index keys."),
1597 1598 1599 1600 1601 1602 1603 1604
			NULL,
			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
		&max_index_keys,
		INDEX_MAX_KEYS, INDEX_MAX_KEYS, INDEX_MAX_KEYS, NULL, NULL
	},

	{
1605
		{"max_identifier_length", PGC_INTERNAL, PRESET_OPTIONS,
1606
			gettext_noop("Shows the maximum identifier length."),
1607 1608 1609 1610 1611 1612 1613 1614
			NULL,
			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
		&max_identifier_length,
		NAMEDATALEN - 1, NAMEDATALEN - 1, NAMEDATALEN - 1, NULL, NULL
	},

	{
1615
		{"block_size", PGC_INTERNAL, PRESET_OPTIONS,
1616
			gettext_noop("Shows the size of a disk block."),
1617 1618 1619 1620 1621 1622 1623
			NULL,
			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
		&block_size,
		BLCKSZ, BLCKSZ, BLCKSZ, NULL, NULL
	},

1624 1625
	{
		{"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
1626
			gettext_noop("Time to sleep between autovacuum runs."),
1627 1628
			NULL,
			GUC_UNIT_S
1629 1630
		},
		&autovacuum_naptime,
1631
		60, 1, INT_MAX, NULL, NULL
1632 1633 1634 1635 1636 1637 1638
	},
	{
		{"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
			gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
			NULL
		},
		&autovacuum_vac_thresh,
1639
		500, 0, INT_MAX, NULL, NULL
1640 1641 1642 1643 1644 1645 1646
	},
	{
		{"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
			gettext_noop("Minimum number of tuple inserts, updates or deletes prior to analyze."),
			NULL
		},
		&autovacuum_anl_thresh,
1647
		250, 0, INT_MAX, NULL, NULL
1648
	},
1649 1650 1651
	{
		/* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
		{"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
P
Peter Eisentraut 已提交
1652
			gettext_noop("Age at which to autovacuum a table to prevent transaction ID wraparound."),
1653 1654 1655 1656 1657
			NULL
		},
		&autovacuum_freeze_max_age,
		200000000, 100000000, 2000000000, NULL, NULL
	},
1658 1659 1660 1661 1662 1663 1664 1665 1666
	{
		/* see max_connections */
		{"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
			gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
			NULL
		},
		&autovacuum_max_workers,
		3, 1, INT_MAX / 4, assign_autovacuum_max_workers, NULL
	},
1667

1668 1669
	{
		{"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER,
1670
			gettext_noop("Time between issuing TCP keepalives."),
B
Bruce Momjian 已提交
1671
			gettext_noop("A value of 0 uses the system default."),
1672
			GUC_UNIT_S
B
Bruce Momjian 已提交
1673
		},
1674 1675 1676 1677 1678 1679
		&tcp_keepalives_idle,
		0, 0, INT_MAX, assign_tcp_keepalives_idle, show_tcp_keepalives_idle
	},

	{
		{"tcp_keepalives_interval", PGC_USERSET, CLIENT_CONN_OTHER,
1680
			gettext_noop("Time between TCP keepalive retransmits."),
B
Bruce Momjian 已提交
1681
			gettext_noop("A value of 0 uses the system default."),
1682
			GUC_UNIT_S
B
Bruce Momjian 已提交
1683
		},
1684 1685 1686 1687 1688 1689
		&tcp_keepalives_interval,
		0, 0, INT_MAX, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
	},

	{
		{"tcp_keepalives_count", PGC_USERSET, CLIENT_CONN_OTHER,
B
Bruce Momjian 已提交
1690 1691 1692 1693 1694
			gettext_noop("Maximum number of TCP keepalive retransmits."),
			gettext_noop("This controls the number of consecutive keepalive retransmits that can be "
						 "lost before a connection is considered dead. A value of 0 uses the "
						 "system default."),
		},
1695 1696 1697 1698
		&tcp_keepalives_count,
		0, 0, INT_MAX, assign_tcp_keepalives_count, show_tcp_keepalives_count
	},

T
Teodor Sigaev 已提交
1699
	{
1700
		{"gin_fuzzy_search_limit", PGC_USERSET, CLIENT_CONN_OTHER,
P
Peter Eisentraut 已提交
1701
			gettext_noop("Sets the maximum allowed result for exact search by GIN."),
T
Teodor Sigaev 已提交
1702 1703 1704 1705 1706 1707 1708
			NULL,
			0
		},
		&GinFuzzySearchLimit,
		0, 0, INT_MAX, NULL, NULL
	},

1709 1710
	{
		{"effective_cache_size", PGC_USERSET, QUERY_TUNING_COST,
1711
			gettext_noop("Sets the planner's assumption about the size of the disk cache."),
1712 1713
			gettext_noop("That is, the portion of the kernel's disk cache that "
						 "will be used for PostgreSQL data files. This is measured in disk "
1714 1715
						 "pages, which are normally 8 kB each."),
			GUC_UNIT_BLOCKS,
1716 1717 1718 1719 1720
		},
		&effective_cache_size,
		DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX, NULL, NULL
	},

1721 1722 1723 1724 1725
	{
		/* Can't be set in postgresql.conf */
		{"server_version_num", PGC_INTERNAL, PRESET_OPTIONS,
			gettext_noop("Shows the server version as an integer."),
			NULL,
1726
			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1727 1728 1729 1730
		},
		&server_version_num,
		PG_VERSION_NUM, PG_VERSION_NUM, PG_VERSION_NUM, NULL, NULL
	},
1731

1732 1733
	{
		{"log_temp_files", PGC_USERSET, LOGGING_WHAT,
1734
			gettext_noop("Log the use of temporary files larger than this number of kilobytes."),
1735
			gettext_noop("Zero logs all files. The default is -1 (turning this feature off)."),
1736
			GUC_UNIT_KB
1737 1738 1739 1740
		},
		&log_temp_files,
		-1, -1, INT_MAX, NULL, NULL
	},
1741

1742
	/* End-of-list marker */
1743
	{
1744
		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
1745
	}
1746 1747 1748
};


1749
static struct config_real ConfigureNamesReal[] =
1750
{
1751
	{
1752 1753 1754 1755
		{"seq_page_cost", PGC_USERSET, QUERY_TUNING_COST,
			gettext_noop("Sets the planner's estimate of the cost of a "
						 "sequentially fetched disk page."),
			NULL
1756
		},
1757 1758
		&seq_page_cost,
		DEFAULT_SEQ_PAGE_COST, 0, DBL_MAX, NULL, NULL
1759
	},
1760
	{
1761
		{"random_page_cost", PGC_USERSET, QUERY_TUNING_COST,
1762 1763 1764
			gettext_noop("Sets the planner's estimate of the cost of a "
						 "nonsequentially fetched disk page."),
			NULL
1765 1766
		},
		&random_page_cost,
1767
		DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX, NULL, NULL
1768 1769
	},
	{
1770
		{"cpu_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
1771 1772 1773
			gettext_noop("Sets the planner's estimate of the cost of "
						 "processing each tuple (row)."),
			NULL
1774 1775
		},
		&cpu_tuple_cost,
1776
		DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX, NULL, NULL
1777 1778
	},
	{
1779
		{"cpu_index_tuple_cost", PGC_USERSET, QUERY_TUNING_COST,
1780 1781 1782
			gettext_noop("Sets the planner's estimate of the cost of "
						 "processing each index entry during an index scan."),
			NULL
1783 1784
		},
		&cpu_index_tuple_cost,
1785
		DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX, NULL, NULL
1786 1787
	},
	{
1788
		{"cpu_operator_cost", PGC_USERSET, QUERY_TUNING_COST,
1789 1790 1791
			gettext_noop("Sets the planner's estimate of the cost of "
						 "processing each operator or function call."),
			NULL
1792 1793
		},
		&cpu_operator_cost,
1794
		DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX, NULL, NULL
1795 1796 1797
	},

	{
1798
		{"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO,
1799
			gettext_noop("GEQO: selective pressure within the population."),
1800 1801 1802
			NULL
		},
		&Geqo_selection_bias,
1803 1804
		DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS,
		MAX_GEQO_SELECTION_BIAS, NULL, NULL
1805 1806
	},

1807 1808
	{
		{"bgwriter_lru_percent", PGC_SIGHUP, RESOURCES,
1809
			gettext_noop("Background writer percentage of LRU buffers to flush per round."),
1810 1811 1812 1813 1814 1815 1816 1817
			NULL
		},
		&bgwriter_lru_percent,
		1.0, 0.0, 100.0, NULL, NULL
	},

	{
		{"bgwriter_all_percent", PGC_SIGHUP, RESOURCES,
1818
			gettext_noop("Background writer percentage of all buffers to flush per round."),
1819 1820 1821 1822 1823 1824
			NULL
		},
		&bgwriter_all_percent,
		0.333, 0.0, 100.0, NULL, NULL
	},

1825
	{
1826
		{"seed", PGC_USERSET, UNGROUPED,
1827
			gettext_noop("Sets the seed for random-number generation."),
1828 1829 1830
			NULL,
			GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
1831 1832 1833 1834
		&phony_random_seed,
		0.5, 0.0, 1.0, assign_random_seed, show_random_seed
	},

1835 1836 1837 1838 1839 1840
	{
		{"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
			gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
			NULL
		},
		&autovacuum_vac_scale,
1841
		0.2, 0.0, 100.0, NULL, NULL
1842 1843 1844 1845 1846 1847 1848
	},
	{
		{"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
			gettext_noop("Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples."),
			NULL
		},
		&autovacuum_anl_scale,
1849
		0.1, 0.0, 100.0, NULL, NULL
1850 1851
	},

1852
	/* End-of-list marker */
1853
	{
1854
		{NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL
1855
	}
1856 1857 1858
};


1859
static struct config_string ConfigureNamesString[] =
1860
{
B
Bruce Momjian 已提交
1861 1862
	{
		{"archive_command", PGC_SIGHUP, WAL_SETTINGS,
1863 1864
			gettext_noop("Sets the shell command that will be called to archive a WAL file."),
			NULL
B
Bruce Momjian 已提交
1865 1866 1867 1868
		},
		&XLogArchiveCommand,
		"", NULL, NULL
	},
1869

1870 1871 1872 1873 1874 1875 1876 1877 1878
	{
		{"backslash_quote", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
			gettext_noop("Sets whether \"\\'\" is allowed in string literals."),
			gettext_noop("Valid values are ON, OFF, and SAFE_ENCODING.")
		},
		&backslash_quote_string,
		"safe_encoding", assign_backslash_quote, NULL
	},

1879
	{
1880
		{"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
1881
			gettext_noop("Sets the client's character set encoding."),
1882
			NULL,
1883
			GUC_IS_NAME | GUC_REPORT
1884
		},
1885
		&client_encoding_string,
1886
		"SQL_ASCII", assign_client_encoding, NULL
1887 1888
	},

1889
	{
1890
		{"client_min_messages", PGC_USERSET, LOGGING_WHEN,
1891
			gettext_noop("Sets the message levels that are sent to the client."),
1892 1893 1894 1895 1896 1897
			gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, "
						 "DEBUG1, LOG, NOTICE, WARNING, and ERROR. Each level includes all the "
						 "levels that follow it. The later the level, the fewer messages are "
						 "sent.")
		},
		&client_min_messages_str,
1898
		"notice", assign_client_min_messages, NULL
1899
	},
1900

1901
	{
1902
		{"log_min_messages", PGC_SUSET, LOGGING_WHEN,
1903
			gettext_noop("Sets the message levels that are logged."),
1904
			gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, "
B
Bruce Momjian 已提交
1905
			"INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. Each level "
1906
						 "includes all the levels that follow it.")
1907 1908
		},
		&log_min_messages_str,
1909 1910 1911 1912
		"notice", assign_log_min_messages, NULL
	},

	{
1913
		{"log_error_verbosity", PGC_SUSET, LOGGING_WHEN,
1914
			gettext_noop("Sets the verbosity of logged messages."),
1915
			gettext_noop("Valid values are \"terse\", \"default\", and \"verbose\".")
1916 1917
		},
		&log_error_verbosity_str,
1918 1919
		"default", assign_log_error_verbosity, NULL
	},
1920
	{
1921
		{"log_statement", PGC_SUSET, LOGGING_WHAT,
1922
			gettext_noop("Sets the type of statements logged."),
1923
			gettext_noop("Valid values are \"none\", \"ddl\", \"mod\", and \"all\".")
1924 1925 1926 1927
		},
		&log_statement_str,
		"none", assign_log_statement, NULL
	},
1928

1929
	{
1930
		{"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
1931
			gettext_noop("Causes all statements generating error at or above this level to be logged."),
1932
			gettext_noop("All SQL statements that cause an error of the "
1933
						 "specified level or a higher level are logged.")
1934 1935
		},
		&log_min_error_statement_str,
1936
		"error", assign_min_error_statement, NULL
1937 1938
	},

B
Add:  
Bruce Momjian 已提交
1939 1940
	{
		{"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
1941 1942
			gettext_noop("Controls information prefixed to each log line."),
			gettext_noop("If blank, no prefix is used.")
B
Add:  
Bruce Momjian 已提交
1943 1944 1945 1946 1947 1948
		},
		&Log_line_prefix,
		"", NULL, NULL
	},


1949
	{
1950
		{"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
1951
			gettext_noop("Sets the display format for date and time values."),
1952
			gettext_noop("Also controls interpretation of ambiguous "
1953
						 "date inputs."),
1954 1955
			GUC_LIST_INPUT | GUC_REPORT
		},
1956
		&datestyle_string,
1957
		"ISO, MDY", assign_datestyle, NULL
1958
	},
1959

1960 1961 1962
	{
		{"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT,
			gettext_noop("Sets the default tablespace to create tables and indexes in."),
1963
			gettext_noop("An empty string selects the database's default tablespace."),
B
Bruce Momjian 已提交
1964
			GUC_IS_NAME
1965 1966 1967 1968 1969
		},
		&default_tablespace,
		"", assign_default_tablespace, NULL
	},

1970
	{
1971
		{"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
1972
			gettext_noop("Sets the transaction isolation level of each new transaction."),
1973
			gettext_noop("Each SQL transaction has an isolation level, which "
B
Bruce Momjian 已提交
1974
						 "can be either \"read uncommitted\", \"read committed\", \"repeatable read\", or \"serializable\".")
1975 1976
		},
		&default_iso_level_string,
1977
		"read committed", assign_defaultxactisolevel, NULL
1978 1979
	},

1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
	{
		{"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
			gettext_noop("Sets the sessions behaviour for triggers and rewrite rules."),
			gettext_noop("Each session can be either"
						 " \"origin\", \"replica\" or \"local\".")
		},
		&session_replication_role_string,
		"origin", assign_session_replication_role, NULL
	},

1990
	{
1991
		{"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
1992
			gettext_noop("Sets the path for dynamically loadable modules."),
1993
			gettext_noop("If a dynamically loadable module needs to be opened and "
1994
						 "the specified name does not have a directory component (i.e., the "
1995
						 "name does not contain a slash), the system will search this path for "
1996 1997
						 "the specified file."),
			GUC_SUPERUSER_ONLY
1998 1999
		},
		&Dynamic_library_path,
2000
		"$libdir", NULL, NULL
2001 2002 2003
	},

	{
2004
		{"krb_server_keyfile", PGC_POSTMASTER, CONN_AUTH_SECURITY,
2005
			gettext_noop("Sets the location of the Kerberos server key file."),
2006 2007
			NULL,
			GUC_SUPERUSER_ONLY
2008 2009
		},
		&pg_krb_server_keyfile,
2010
		PG_KRB_SRVTAB, NULL, NULL
2011
	},
2012

B
 
Bruce Momjian 已提交
2013 2014 2015 2016 2017 2018 2019 2020 2021
	{
		{"krb_srvname", PGC_POSTMASTER, CONN_AUTH_SECURITY,
			gettext_noop("Sets the name of the Kerberos service."),
			NULL
		},
		&pg_krb_srvnam,
		PG_KRB_SRVNAM, NULL, NULL
	},

2022 2023 2024 2025 2026 2027 2028 2029 2030
	{
		{"krb_server_hostname", PGC_POSTMASTER, CONN_AUTH_SECURITY,
			gettext_noop("Sets the hostname of the Kerberos server."),
			NULL
		},
		&pg_krb_server_hostname,
		NULL, NULL, NULL
	},

2031
	{
2032 2033
		{"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
			gettext_noop("Sets the Bonjour broadcast service name."),
2034 2035
			NULL
		},
2036
		&bonjour_name,
2037 2038 2039
		"", NULL, NULL
	},

2040 2041
	/* See main.c about why defaults for LC_foo are not all alike */

2042
	{
2043
		{"lc_collate", PGC_INTERNAL, CLIENT_CONN_LOCALE,
2044
			gettext_noop("Shows the collation order locale."),
2045 2046 2047 2048
			NULL,
			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
		&locale_collate,
2049 2050 2051 2052
		"C", NULL, NULL
	},

	{
2053
		{"lc_ctype", PGC_INTERNAL, CLIENT_CONN_LOCALE,
2054
			gettext_noop("Shows the character classification and case conversion locale."),
2055 2056 2057 2058
			NULL,
			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
		&locale_ctype,
2059 2060 2061
		"C", NULL, NULL
	},

2062
	{
2063
		{"lc_messages", PGC_SUSET, CLIENT_CONN_LOCALE,
2064
			gettext_noop("Sets the language in which messages are displayed."),
2065 2066 2067
			NULL
		},
		&locale_messages,
2068 2069 2070 2071
		"", locale_messages_assign, NULL
	},

	{
2072
		{"lc_monetary", PGC_USERSET, CLIENT_CONN_LOCALE,
2073
			gettext_noop("Sets the locale for formatting monetary amounts."),
2074 2075 2076
			NULL
		},
		&locale_monetary,
2077
		"C", locale_monetary_assign, NULL
2078 2079 2080
	},

	{
2081
		{"lc_numeric", PGC_USERSET, CLIENT_CONN_LOCALE,
2082
			gettext_noop("Sets the locale for formatting numbers."),
2083 2084 2085
			NULL
		},
		&locale_numeric,
2086
		"C", locale_numeric_assign, NULL
2087 2088 2089
	},

	{
2090
		{"lc_time", PGC_USERSET, CLIENT_CONN_LOCALE,
2091
			gettext_noop("Sets the locale for formatting date and time values."),
2092 2093 2094
			NULL
		},
		&locale_time,
2095
		"C", locale_time_assign, NULL
2096 2097
	},

2098
	{
2099
		{"shared_preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
2100
			gettext_noop("Lists shared libraries to preload into server."),
2101
			NULL,
2102
			GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
2103
		},
2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114
		&shared_preload_libraries_string,
		"", NULL, NULL
	},

	{
		{"local_preload_libraries", PGC_BACKEND, CLIENT_CONN_OTHER,
			gettext_noop("Lists shared libraries to preload into each backend."),
			NULL,
			GUC_LIST_INPUT | GUC_LIST_QUOTE
		},
		&local_preload_libraries_string,
2115
		"", NULL, NULL
2116 2117
	},

2118
	{
2119
		{"regex_flavor", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
2120
			gettext_noop("Sets the regular expression \"flavor\"."),
2121
			gettext_noop("This can be set to advanced, extended, or basic.")
2122 2123
		},
		&regex_flavor_string,
2124 2125 2126
		"advanced", assign_regex_flavor, NULL
	},

2127
	{
2128
		{"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT,
2129
			gettext_noop("Sets the schema search order for names that are not schema-qualified."),
2130 2131 2132
			NULL,
			GUC_LIST_INPUT | GUC_LIST_QUOTE
		},
2133
		&namespace_search_path,
2134
		"\"$user\",public", assign_search_path, NULL
2135 2136 2137
	},

	{
2138 2139
		/* Can't be set in postgresql.conf */
		{"server_encoding", PGC_INTERNAL, CLIENT_CONN_LOCALE,
2140
			gettext_noop("Sets the server (database) character set encoding."),
2141
			NULL,
2142
			GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2143
		},
2144 2145 2146 2147 2148
		&server_encoding_string,
		"SQL_ASCII", NULL, NULL
	},

	{
2149
		/* Can't be set in postgresql.conf */
2150
		{"server_version", PGC_INTERNAL, PRESET_OPTIONS,
2151
			gettext_noop("Shows the server version."),
2152 2153 2154
			NULL,
			GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
2155 2156
		&server_version_string,
		PG_VERSION, NULL, NULL
2157 2158
	},

2159 2160 2161 2162 2163
	{
		/* Not for general use --- used by SET ROLE */
		{"role", PGC_USERSET, UNGROUPED,
			gettext_noop("Sets the current role."),
			NULL,
2164
			GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2165 2166 2167 2168 2169
		},
		&role_string,
		"none", assign_role, show_role
	},

2170
	{
2171 2172
		/* Not for general use --- used by SET SESSION AUTHORIZATION */
		{"session_authorization", PGC_USERSET, UNGROUPED,
2173
			gettext_noop("Sets the session user name."),
2174
			NULL,
2175
			GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2176
		},
2177 2178
		&session_authorization_string,
		NULL, assign_session_authorization, show_session_authorization
2179 2180
	},

2181
	{
2182
		{"log_destination", PGC_SIGHUP, LOGGING_WHERE,
B
Bruce Momjian 已提交
2183
			gettext_noop("Sets the destination for server log output."),
P
Peter Eisentraut 已提交
2184 2185
			gettext_noop("Valid values are combinations of \"stderr\", \"syslog\", "
						 "and \"eventlog\", depending on the platform."),
B
Bruce Momjian 已提交
2186
			GUC_LIST_INPUT
2187 2188 2189 2190
		},
		&log_destination_string,
		"stderr", assign_log_destination, NULL
	},
2191 2192
	{
		{"log_directory", PGC_SIGHUP, LOGGING_WHERE,
2193
			gettext_noop("Sets the destination directory for log files."),
2194
			gettext_noop("Can be specified as relative to the data directory "
2195 2196
						 "or as absolute path."),
			GUC_SUPERUSER_ONLY
2197 2198
		},
		&Log_directory,
2199
		"pg_log", assign_canonical_path, NULL
2200 2201
	},
	{
2202 2203
		{"log_filename", PGC_SIGHUP, LOGGING_WHERE,
			gettext_noop("Sets the file name pattern for log files."),
2204 2205
			NULL,
			GUC_SUPERUSER_ONLY
2206
		},
2207 2208
		&Log_filename,
		"postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL
2209
	},
2210

T
Tatsuo Ishii 已提交
2211
#ifdef HAVE_SYSLOG
2212
	{
2213
		{"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
2214
			gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
2215 2216
			gettext_noop("Valid values are LOCAL0, LOCAL1, LOCAL2, LOCAL3, "
						 "LOCAL4, LOCAL5, LOCAL6, LOCAL7.")
2217
		},
2218 2219
		&syslog_facility_str,
		"LOCAL0", assign_syslog_facility, NULL
2220 2221
	},
	{
2222 2223 2224
		{"syslog_ident", PGC_SIGHUP, LOGGING_WHERE,
			gettext_noop("Sets the program name used to identify PostgreSQL "
						 "messages in syslog."),
2225 2226
			NULL
		},
2227 2228
		&syslog_ident_str,
		"postgres", assign_syslog_ident, NULL
2229
	},
2230
#endif
2231

2232
	{
2233
		{"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
2234
			gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
2235 2236
			NULL,
			GUC_REPORT
2237 2238
		},
		&timezone_string,
2239 2240
		"UNKNOWN", assign_timezone, show_timezone
	},
2241 2242
	{
		{"timezone_abbreviations", PGC_USERSET, CLIENT_CONN_LOCALE,
2243
			gettext_noop("Selects a file of time zone abbreviations."),
2244 2245
			NULL,
		},
2246 2247
		&timezone_abbreviations_string,
		"UNKNOWN", assign_timezone_abbreviations, NULL
2248
	},
2249 2250

	{
2251
		{"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
2252
			gettext_noop("Sets the current transaction's isolation level."),
2253 2254 2255
			NULL,
			GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
		},
2256 2257 2258 2259 2260
		&XactIsoLevel_string,
		NULL, assign_XactIsoLevel, show_XactIsoLevel
	},

	{
2261
		{"unix_socket_group", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2262
			gettext_noop("Sets the owning group of the Unix-domain socket."),
2263 2264
			gettext_noop("The owning user of the socket is always the user "
						 "that starts the server.")
2265 2266
		},
		&Unix_socket_group,
2267
		"", NULL, NULL
2268
	},
2269

2270
	{
2271
		{"unix_socket_directory", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2272
			gettext_noop("Sets the directory where the Unix-domain socket will be created."),
2273 2274
			NULL,
			GUC_SUPERUSER_ONLY
2275 2276
		},
		&UnixSocketDir,
2277
		"", assign_canonical_path, NULL
2278
	},
2279

2280
	{
2281
		{"listen_addresses", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2282 2283 2284
			gettext_noop("Sets the host name or IP address(es) to listen to."),
			NULL,
			GUC_LIST_INPUT
2285
		},
2286 2287
		&ListenAddresses,
		"localhost", NULL, NULL
2288
	},
2289

2290
	{
2291
		{"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
2292
			gettext_noop("Selects the method used for forcing WAL updates to disk."),
2293 2294 2295
			NULL
		},
		&XLOG_sync_method,
2296
		XLOG_sync_method_default, assign_xlog_sync_method, NULL
2297
	},
2298

2299
	{
2300
		{"custom_variable_classes", PGC_SIGHUP, CUSTOM_OPTIONS,
2301
			gettext_noop("Sets the list of known custom variable classes."),
2302 2303 2304 2305 2306 2307 2308
			NULL,
			GUC_LIST_INPUT | GUC_LIST_QUOTE
		},
		&custom_variable_classes,
		NULL, assign_custom_variable_classes, NULL
	},

2309
	{
2310
		{"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
B
Bruce Momjian 已提交
2311 2312 2313
			gettext_noop("Sets the server's data directory."),
			NULL,
			GUC_SUPERUSER_ONLY
2314
		},
2315 2316
		&data_directory,
		NULL, NULL, NULL
2317 2318 2319
	},

	{
2320
		{"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
B
Bruce Momjian 已提交
2321 2322 2323
			gettext_noop("Sets the server's main configuration file."),
			NULL,
			GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
2324 2325 2326 2327 2328 2329 2330
		},
		&ConfigFileName,
		NULL, NULL, NULL
	},

	{
		{"hba_file", PGC_POSTMASTER, FILE_LOCATIONS,
2331
			gettext_noop("Sets the server's \"hba\" configuration file."),
B
Bruce Momjian 已提交
2332 2333
			NULL,
			GUC_SUPERUSER_ONLY
2334
		},
2335 2336
		&HbaFileName,
		NULL, NULL, NULL
2337 2338 2339
	},

	{
2340
		{"ident_file", PGC_POSTMASTER, FILE_LOCATIONS,
2341
			gettext_noop("Sets the server's \"ident\" configuration file."),
B
Bruce Momjian 已提交
2342 2343
			NULL,
			GUC_SUPERUSER_ONLY
2344
		},
2345 2346
		&IdentFileName,
		NULL, NULL, NULL
2347 2348 2349
	},

	{
2350
		{"external_pid_file", PGC_POSTMASTER, FILE_LOCATIONS,
B
Bruce Momjian 已提交
2351 2352 2353
			gettext_noop("Writes the postmaster PID to the specified file."),
			NULL,
			GUC_SUPERUSER_ONLY
2354
		},
2355
		&external_pid_file,
2356
		NULL, assign_canonical_path, NULL
2357 2358
	},

2359 2360 2361 2362 2363 2364 2365 2366 2367
	{
		{"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
			gettext_noop("Sets how binary values are to be encoded in XML."),
			gettext_noop("Valid values are BASE64 and HEX.")
		},
		&xmlbinary_string,
		"base64", assign_xmlbinary, NULL
	},

2368 2369 2370 2371 2372 2373 2374 2375 2376 2377
	{
		{"xmloption", PGC_USERSET, CLIENT_CONN_STATEMENT,
			gettext_noop("Sets whether XML data in implicit parsing and serialization "
						 "operations is to be considered as documents or content fragments."),
			gettext_noop("Valid values are DOCUMENT and CONTENT.")
		},
		&xmloption_string,
		"content", assign_xmloption, NULL
	},

T
Tom Lane 已提交
2378
#ifdef USE_SSL
B
Bruce Momjian 已提交
2379 2380 2381 2382 2383 2384 2385 2386 2387
	{
		{"ssl_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY,
			gettext_noop("Sets the list of allowed SSL ciphers."),
			NULL,
			GUC_SUPERUSER_ONLY
		},
		&SSLCipherSuites,
		"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH", NULL, NULL
	},
T
Tom Lane 已提交
2388 2389
#endif /* USE_SSL */

2390
	/* End-of-list marker */
2391
	{
2392
		{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
2393
	}
2394 2395 2396
};


2397
/******** end of options list ********/
2398

B
Bruce Momjian 已提交
2399

2400 2401 2402 2403 2404 2405
/*
 * To allow continued support of obsolete names for GUC variables, we apply
 * the following mappings to any unrecognized name.  Note that an old name
 * should be mapped to a new one only if the new variable has very similar
 * semantics to the old.
 */
B
Bruce Momjian 已提交
2406
static const char *const map_old_guc_names[] = {
2407 2408 2409 2410 2411 2412
	"sort_mem", "work_mem",
	"vacuum_mem", "maintenance_work_mem",
	NULL
};


2413
/*
2414
 * Actual lookup of variables is done through this single, sorted array.
2415
 */
2416 2417
static struct config_generic **guc_variables;

2418
/* Current number of variables contained in the vector */
B
Bruce Momjian 已提交
2419
static int	num_guc_variables;
2420

2421
/* Vector capacity */
B
Bruce Momjian 已提交
2422
static int	size_guc_variables;
2423

2424

2425
static bool guc_dirty;			/* TRUE if need to do commit/abort work */
2426

2427 2428
static bool reporting_enabled;	/* TRUE to enable GUC_REPORT */

2429

B
Bruce Momjian 已提交
2430
static int	guc_var_compare(const void *a, const void *b);
2431
static int	guc_name_compare(const char *namea, const char *nameb);
B
Bruce Momjian 已提交
2432
static void push_old_value(struct config_generic * gconf);
2433
static void ReportGUCOption(struct config_generic * record);
2434 2435
static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
static void ShowAllGUCConfig(DestReceiver *dest);
2436
static char *_ShowOption(struct config_generic * record, bool use_units);
B
Bruce Momjian 已提交
2437
static bool is_newvalue_equal(struct config_generic * record, const char *newvalue);
2438

2439

2440 2441 2442 2443 2444 2445
/*
 * Some infrastructure for checking malloc/strdup/realloc calls
 */
static void *
guc_malloc(int elevel, size_t size)
{
B
Bruce Momjian 已提交
2446
	void	   *data;
2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458

	data = malloc(size);
	if (data == NULL)
		ereport(elevel,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 errmsg("out of memory")));
	return data;
}

static void *
guc_realloc(int elevel, void *old, size_t size)
{
B
Bruce Momjian 已提交
2459
	void	   *data;
2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471

	data = realloc(old, size);
	if (data == NULL)
		ereport(elevel,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 errmsg("out of memory")));
	return data;
}

static char *
guc_strdup(int elevel, const char *src)
{
B
Bruce Momjian 已提交
2472
	char	   *data;
2473 2474 2475 2476 2477 2478 2479 2480 2481 2482

	data = strdup(src);
	if (data == NULL)
		ereport(elevel,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 errmsg("out of memory")));
	return data;
}


2483 2484 2485 2486 2487 2488
/*
 * Support for assigning to a field of a string GUC item.  Free the prior
 * value if it's not referenced anywhere else in the item (including stacked
 * states).
 */
static void
2489
set_string_field(struct config_string * conf, char **field, char *newval)
2490
{
B
Bruce Momjian 已提交
2491 2492
	char	   *oldval = *field;
	GucStack   *stack;
2493 2494 2495 2496 2497 2498 2499 2500

	/* Do the assignment */
	*field = newval;

	/* Exit if any duplicate references, or if old value was NULL anyway */
	if (oldval == NULL ||
		oldval == *(conf->variable) ||
		oldval == conf->reset_val ||
2501 2502
		oldval == conf->tentative_val ||
		oldval == conf->boot_val)
2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518
		return;
	for (stack = conf->gen.stack; stack; stack = stack->prev)
	{
		if (oldval == stack->tentative_val.stringval ||
			oldval == stack->value.stringval)
			return;
	}

	/* Not used anymore, so free it */
	free(oldval);
}

/*
 * Detect whether strval is referenced anywhere in a GUC string item
 */
static bool
B
Bruce Momjian 已提交
2519
string_field_used(struct config_string * conf, char *strval)
2520
{
B
Bruce Momjian 已提交
2521
	GucStack   *stack;
2522 2523 2524

	if (strval == *(conf->variable) ||
		strval == conf->reset_val ||
2525 2526
		strval == conf->tentative_val ||
		strval == conf->boot_val)
2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539
		return true;
	for (stack = conf->gen.stack; stack; stack = stack->prev)
	{
		if (strval == stack->tentative_val.stringval ||
			strval == stack->value.stringval)
			return true;
	}
	return false;
}


struct config_generic **
get_guc_variables(void)
2540 2541 2542
{
	return guc_variables;
}
2543

2544

2545
/*
B
Bruce Momjian 已提交
2546
 * Build the sorted array.	This is split out so that it could be
2547 2548
 * re-executed after startup (eg, we could allow loadable modules to
 * add vars, and then we'd need to re-sort).
2549
 */
2550
void
2551
build_guc_variables(void)
2552
{
B
Bruce Momjian 已提交
2553
	int			size_vars;
2554 2555
	int			num_vars = 0;
	struct config_generic **guc_vars;
B
Bruce Momjian 已提交
2556
	int			i;
2557

2558
	for (i = 0; ConfigureNamesBool[i].gen.name; i++)
2559 2560 2561
	{
		struct config_bool *conf = &ConfigureNamesBool[i];

2562 2563 2564
		/* Rather than requiring vartype to be filled in by hand, do this: */
		conf->gen.vartype = PGC_BOOL;
		num_vars++;
2565
	}
2566

2567
	for (i = 0; ConfigureNamesInt[i].gen.name; i++)
2568 2569 2570
	{
		struct config_int *conf = &ConfigureNamesInt[i];

2571 2572
		conf->gen.vartype = PGC_INT;
		num_vars++;
2573
	}
2574

2575
	for (i = 0; ConfigureNamesReal[i].gen.name; i++)
2576 2577 2578
	{
		struct config_real *conf = &ConfigureNamesReal[i];

2579 2580
		conf->gen.vartype = PGC_REAL;
		num_vars++;
2581
	}
2582

2583
	for (i = 0; ConfigureNamesString[i].gen.name; i++)
2584
	{
2585
		struct config_string *conf = &ConfigureNamesString[i];
2586

2587 2588
		conf->gen.vartype = PGC_STRING;
		num_vars++;
2589 2590
	}

B
Bruce Momjian 已提交
2591 2592
	/*
	 * Create table with 20% slack
2593 2594 2595
	 */
	size_vars = num_vars + num_vars / 4;

2596
	guc_vars = (struct config_generic **)
2597
		guc_malloc(FATAL, size_vars * sizeof(struct config_generic *));
2598

2599
	num_vars = 0;
2600

2601
	for (i = 0; ConfigureNamesBool[i].gen.name; i++)
B
Bruce Momjian 已提交
2602
		guc_vars[num_vars++] = &ConfigureNamesBool[i].gen;
2603

2604
	for (i = 0; ConfigureNamesInt[i].gen.name; i++)
B
Bruce Momjian 已提交
2605
		guc_vars[num_vars++] = &ConfigureNamesInt[i].gen;
2606

2607
	for (i = 0; ConfigureNamesReal[i].gen.name; i++)
B
Bruce Momjian 已提交
2608
		guc_vars[num_vars++] = &ConfigureNamesReal[i].gen;
2609

2610
	for (i = 0; ConfigureNamesString[i].gen.name; i++)
B
Bruce Momjian 已提交
2611
		guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
2612

2613 2614 2615 2616
	if (guc_variables)
		free(guc_variables);
	guc_variables = guc_vars;
	num_guc_variables = num_vars;
2617
	size_guc_variables = size_vars;
B
Bruce Momjian 已提交
2618 2619
	qsort((void *) guc_variables, num_guc_variables,
		  sizeof(struct config_generic *), guc_var_compare);
2620 2621
}

2622 2623 2624
static bool
is_custom_class(const char *name, int dotPos)
{
B
Bruce Momjian 已提交
2625
	/*
B
Bruce Momjian 已提交
2626 2627
	 * assign_custom_variable_classes() has made sure no empty identifiers or
	 * whitespace exists in the variable
2628
	 */
B
Bruce Momjian 已提交
2629
	bool		result = false;
2630
	const char *ccs = GetConfigOption("custom_variable_classes");
B
Bruce Momjian 已提交
2631 2632

	if (ccs != NULL)
2633 2634
	{
		const char *start = ccs;
B
Bruce Momjian 已提交
2635 2636

		for (;; ++ccs)
2637
		{
B
Bruce Momjian 已提交
2638 2639 2640
			int			c = *ccs;

			if (c == 0 || c == ',')
2641
			{
B
Bruce Momjian 已提交
2642
				if (dotPos == ccs - start && strncmp(start, name, dotPos) == 0)
2643 2644 2645 2646
				{
					result = true;
					break;
				}
B
Bruce Momjian 已提交
2647
				if (c == 0)
2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659
					break;
				start = ccs + 1;
			}
		}
	}
	return result;
}

/*
 * Add a new GUC variable to the list of known variables. The
 * list is expanded if needed.
 */
2660
static bool
B
Bruce Momjian 已提交
2661
add_guc_variable(struct config_generic * var, int elevel)
2662
{
B
Bruce Momjian 已提交
2663
	if (num_guc_variables + 1 >= size_guc_variables)
2664
	{
B
Bruce Momjian 已提交
2665 2666
		/*
		 * Increase the vector by 25%
2667
		 */
B
Bruce Momjian 已提交
2668 2669
		int			size_vars = size_guc_variables + size_guc_variables / 4;
		struct config_generic **guc_vars;
2670

B
Bruce Momjian 已提交
2671
		if (size_vars == 0)
2672
		{
2673
			size_vars = 100;
B
Bruce Momjian 已提交
2674 2675
			guc_vars = (struct config_generic **)
				guc_malloc(elevel, size_vars * sizeof(struct config_generic *));
2676 2677
		}
		else
2678
		{
B
Bruce Momjian 已提交
2679 2680
			guc_vars = (struct config_generic **)
				guc_realloc(elevel, guc_variables, size_vars * sizeof(struct config_generic *));
2681 2682
		}

B
Bruce Momjian 已提交
2683
		if (guc_vars == NULL)
2684 2685
			return false;		/* out of memory */

2686 2687 2688 2689
		guc_variables = guc_vars;
		size_guc_variables = size_vars;
	}
	guc_variables[num_guc_variables++] = var;
B
Bruce Momjian 已提交
2690 2691
	qsort((void *) guc_variables, num_guc_variables,
		  sizeof(struct config_generic *), guc_var_compare);
2692
	return true;
2693 2694 2695
}

/*
2696
 * Create and add a placeholder variable. It's presumed to belong
2697 2698
 * to a valid custom variable class at this point.
 */
B
Bruce Momjian 已提交
2699
static struct config_string *
2700
add_placeholder_variable(const char *name, int elevel)
2701
{
B
Bruce Momjian 已提交
2702 2703 2704
	size_t		sz = sizeof(struct config_string) + sizeof(char *);
	struct config_string *var;
	struct config_generic *gen;
2705

B
Bruce Momjian 已提交
2706 2707
	var = (struct config_string *) guc_malloc(elevel, sz);
	if (var == NULL)
2708 2709 2710
		return NULL;

	gen = &var->gen;
2711 2712
	memset(var, 0, sz);

2713 2714
	gen->name = guc_strdup(elevel, name);
	if (gen->name == NULL)
2715 2716 2717 2718 2719
	{
		free(var);
		return NULL;
	}

B
Bruce Momjian 已提交
2720 2721
	gen->context = PGC_USERSET;
	gen->group = CUSTOM_OPTIONS;
2722
	gen->short_desc = "GUC placeholder variable";
B
Bruce Momjian 已提交
2723 2724
	gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER;
	gen->vartype = PGC_STRING;
2725

B
Bruce Momjian 已提交
2726 2727 2728 2729 2730
	/*
	 * The char* is allocated at the end of the struct since we have no
	 * 'static' place to point to.
	 */
	var->variable = (char **) (var + 1);
2731

B
Bruce Momjian 已提交
2732
	if (!add_guc_variable((struct config_generic *) var, elevel))
2733 2734 2735 2736 2737 2738
	{
		free((void *) gen->name);
		free(var);
		return NULL;
	}

2739 2740
	return var;
}
2741 2742

/*
2743 2744
 * Look up option NAME. If it exists, return a pointer to its record,
 * else return NULL.
2745
 */
2746
static struct config_generic *
2747
find_option(const char *name, int elevel)
2748
{
2749
	const char *dot;
2750 2751
	const char **key = &name;
	struct config_generic **res;
2752
	int			i;
2753

2754
	Assert(name);
2755

2756
	/*
B
Bruce Momjian 已提交
2757 2758
	 * By equating const char ** with struct config_generic *, we are assuming
	 * the name field is first in config_generic.
2759
	 */
B
Bruce Momjian 已提交
2760 2761 2762
	res = (struct config_generic **) bsearch((void *) &key,
											 (void *) guc_variables,
											 num_guc_variables,
B
Bruce Momjian 已提交
2763
											 sizeof(struct config_generic *),
B
Bruce Momjian 已提交
2764
											 guc_var_compare);
2765 2766
	if (res)
		return *res;
2767 2768

	/*
B
Bruce Momjian 已提交
2769 2770 2771
	 * See if the name is an obsolete name for a variable.	We assume that the
	 * set of supported old names is short enough that a brute-force search is
	 * the best way.
2772 2773 2774 2775
	 */
	for (i = 0; map_old_guc_names[i] != NULL; i += 2)
	{
		if (guc_name_compare(name, map_old_guc_names[i]) == 0)
B
Bruce Momjian 已提交
2776
			return find_option(map_old_guc_names[i + 1], elevel);
2777 2778
	}

2779
	/*
B
Bruce Momjian 已提交
2780 2781
	 * Check if the name is qualified, and if so, check if the qualifier maps
	 * to a custom variable class.
2782 2783
	 */
	dot = strchr(name, GUC_QUALIFIER_SEPARATOR);
B
Bruce Momjian 已提交
2784
	if (dot != NULL && is_custom_class(name, dot - name))
2785
		/* Add a placeholder variable for this name */
B
Bruce Momjian 已提交
2786
		return (struct config_generic *) add_placeholder_variable(name, elevel);
2787

2788
	/* Unknown name */
2789 2790
	return NULL;
}
2791 2792 2793


/*
2794
 * comparator for qsorting and bsearching guc_variables array
2795
 */
2796 2797
static int
guc_var_compare(const void *a, const void *b)
2798
{
2799 2800
	struct config_generic *confa = *(struct config_generic **) a;
	struct config_generic *confb = *(struct config_generic **) b;
2801

2802 2803 2804 2805 2806 2807 2808
	return guc_name_compare(confa->name, confb->name);
}


static int
guc_name_compare(const char *namea, const char *nameb)
{
2809
	/*
B
Bruce Momjian 已提交
2810 2811 2812
	 * The temptation to use strcasecmp() here must be resisted, because the
	 * array ordering has to remain stable across setlocale() calls. So, build
	 * our own with a simple ASCII-only downcasing.
2813
	 */
2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824
	while (*namea && *nameb)
	{
		char		cha = *namea++;
		char		chb = *nameb++;

		if (cha >= 'A' && cha <= 'Z')
			cha += 'a' - 'A';
		if (chb >= 'A' && chb <= 'Z')
			chb += 'a' - 'A';
		if (cha != chb)
			return cha - chb;
2825
	}
2826 2827 2828 2829 2830
	if (*namea)
		return 1;				/* a is longer */
	if (*nameb)
		return -1;				/* b is longer */
	return 0;
2831
}
2832 2833


2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857
static int
guc_get_index(const char *name)
{
	const char **key = &name;
	struct config_generic **res;

	Assert(name);

	/*
	 * By equating const char ** with struct config_generic *, we are assuming
	 * the name field is first in config_generic.
	 */
	res = (struct config_generic **) bsearch((void *) &key,
											 (void *) guc_variables,
											 num_guc_variables,
											 sizeof(struct config_generic *),
											 guc_var_compare);
	if (!res)
		return -1;

	return res - guc_variables;
}


2858
/*
2859
 * Initialize GUC options during program startup.
2860 2861 2862
 *
 * Note that we cannot read the config file yet, since we have not yet
 * processed command-line switches.
2863
 */
2864 2865
void
InitializeGUCOptions(void)
2866
{
2867 2868
	int			i;
	char	   *env;
2869
	long		stack_rlimit;
2870

2871 2872 2873 2874
	/*
	 * Build sorted array of all GUC variables.
	 */
	build_guc_variables();
2875

2876
	/*
2877 2878
	 * Load all variables with their compiled-in defaults, and initialize
	 * status fields as needed.
2879
	 */
2880
	for (i = 0; i < num_guc_variables; i++)
2881
	{
2882
		struct config_generic *gconf = guc_variables[i];
2883

2884 2885 2886 2887
		gconf->status = 0;
		gconf->reset_source = PGC_S_DEFAULT;
		gconf->tentative_source = PGC_S_DEFAULT;
		gconf->source = PGC_S_DEFAULT;
2888
		gconf->stack = NULL;
2889 2890 2891 2892

		switch (gconf->vartype)
		{
			case PGC_BOOL:
B
Bruce Momjian 已提交
2893 2894
				{
					struct config_bool *conf = (struct config_bool *) gconf;
2895

2896
					if (conf->assign_hook)
2897
						if (!(*conf->assign_hook) (conf->boot_val, true,
2898 2899
												   PGC_S_DEFAULT))
							elog(FATAL, "failed to initialize %s to %d",
2900 2901
								 conf->gen.name, (int) conf->boot_val);
					*conf->variable = conf->reset_val = conf->boot_val;
B
Bruce Momjian 已提交
2902 2903
					break;
				}
2904
			case PGC_INT:
B
Bruce Momjian 已提交
2905 2906
				{
					struct config_int *conf = (struct config_int *) gconf;
2907

2908 2909
					Assert(conf->boot_val >= conf->min);
					Assert(conf->boot_val <= conf->max);
2910
					if (conf->assign_hook)
2911
						if (!(*conf->assign_hook) (conf->boot_val, true,
2912 2913
												   PGC_S_DEFAULT))
							elog(FATAL, "failed to initialize %s to %d",
2914
								 conf->gen.name, conf->boot_val);
2915
					*conf->variable = conf->reset_val = conf->boot_val;
B
Bruce Momjian 已提交
2916 2917
					break;
				}
2918 2919
			case PGC_REAL:
				{
B
Bruce Momjian 已提交
2920 2921
					struct config_real *conf = (struct config_real *) gconf;

2922 2923
					Assert(conf->boot_val >= conf->min);
					Assert(conf->boot_val <= conf->max);
2924
					if (conf->assign_hook)
2925
						if (!(*conf->assign_hook) (conf->boot_val, true,
2926 2927
												   PGC_S_DEFAULT))
							elog(FATAL, "failed to initialize %s to %g",
2928
								 conf->gen.name, conf->boot_val);
2929
					*conf->variable = conf->reset_val = conf->boot_val;
2930 2931
					break;
				}
B
Bruce Momjian 已提交
2932
			case PGC_STRING:
2933
				{
B
Bruce Momjian 已提交
2934 2935 2936 2937 2938 2939
					struct config_string *conf = (struct config_string *) gconf;
					char	   *str;

					*conf->variable = NULL;
					conf->reset_val = NULL;
					conf->tentative_val = NULL;
2940

B
Bruce Momjian 已提交
2941
					if (conf->boot_val == NULL)
2942
					{
B
Bruce Momjian 已提交
2943 2944
						/* Cannot set value yet */
						break;
2945
					}
B
Bruce Momjian 已提交
2946

2947
					str = guc_strdup(FATAL, conf->boot_val);
B
Bruce Momjian 已提交
2948 2949 2950
					conf->reset_val = str;

					if (conf->assign_hook)
2951
					{
B
Bruce Momjian 已提交
2952 2953
						const char *newstr;

2954 2955
						newstr = (*conf->assign_hook) (str, true,
													   PGC_S_DEFAULT);
B
Bruce Momjian 已提交
2956
						if (newstr == NULL)
2957
						{
2958 2959
							elog(FATAL, "failed to initialize %s to \"%s\"",
								 conf->gen.name, str);
2960
						}
B
Bruce Momjian 已提交
2961 2962 2963 2964 2965
						else if (newstr != str)
						{
							free(str);

							/*
B
Bruce Momjian 已提交
2966
							 * See notes in set_config_option about casting
B
Bruce Momjian 已提交
2967 2968 2969 2970
							 */
							str = (char *) newstr;
							conf->reset_val = str;
						}
2971
					}
B
Bruce Momjian 已提交
2972 2973
					*conf->variable = str;
					break;
2974 2975 2976 2977 2978 2979
				}
		}
	}

	guc_dirty = false;

2980 2981
	reporting_enabled = false;

2982
	/*
2983
	 * Prevent any attempt to override the transaction modes from
2984 2985
	 * non-interactive sources.
	 */
2986 2987 2988
	SetConfigOption("transaction_isolation", "default",
					PGC_POSTMASTER, PGC_S_OVERRIDE);
	SetConfigOption("transaction_read_only", "no",
2989 2990 2991
					PGC_POSTMASTER, PGC_S_OVERRIDE);

	/*
B
Bruce Momjian 已提交
2992 2993
	 * For historical reasons, some GUC parameters can receive defaults from
	 * environment variables.  Process those settings.
2994 2995 2996 2997 2998 2999
	 */

	env = getenv("PGPORT");
	if (env != NULL)
		SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);

3000 3001
	env = getenv("PGDATESTYLE");
	if (env != NULL)
3002 3003
		SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);

3004 3005
	env = getenv("PGCLIENTENCODING");
	if (env != NULL)
3006
		SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027

	/*
	 * rlimit isn't exactly an "environment variable", but it behaves about
	 * the same.  If we can identify the platform stack depth rlimit, increase
	 * default stack depth setting up to whatever is safe (but at most 2MB).
	 */
	stack_rlimit = get_stack_depth_rlimit();
	if (stack_rlimit > 0)
	{
		int		new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;

		if (new_limit > 100)
		{
			char	limbuf[16];

			new_limit = Min(new_limit, 2048);
			sprintf(limbuf, "%d", new_limit);
			SetConfigOption("max_stack_depth", limbuf,
							PGC_POSTMASTER, PGC_S_ENV_VAR);
		}
	}
3028 3029 3030
}


3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044
/*
 * Select the configuration files and data directory to be used, and
 * do the initial read of postgresql.conf.
 *
 * This is called after processing command-line switches.
 *		userDoption is the -D switch value if any (NULL if unspecified).
 *		progname is just for use in error messages.
 *
 * Returns true on success; on failure, prints a suitable error message
 * to stderr and returns false.
 */
bool
SelectConfigFiles(const char *userDoption, const char *progname)
{
3045 3046
	char	   *configdir;
	char	   *fname;
3047 3048
	struct stat stat_buf;

3049 3050 3051 3052 3053
	/* configdir is -D option, or $PGDATA if no -D */
	if (userDoption)
		configdir = make_absolute_path(userDoption);
	else
		configdir = make_absolute_path(getenv("PGDATA"));
3054 3055

	/*
3056
	 * Find the configuration file: if config_file was specified on the
B
Bruce Momjian 已提交
3057 3058 3059
	 * command line, use it, else use configdir/postgresql.conf.  In any case
	 * ensure the result is an absolute path, so that it will be interpreted
	 * the same way by future backends.
3060
	 */
3061 3062
	if (ConfigFileName)
		fname = make_absolute_path(ConfigFileName);
3063 3064 3065 3066 3067 3068 3069
	else if (configdir)
	{
		fname = guc_malloc(FATAL,
						   strlen(configdir) + strlen(CONFIG_FILENAME) + 2);
		sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);
	}
	else
3070
	{
3071
		write_stderr("%s does not know where to find the server configuration file.\n"
P
Peter Eisentraut 已提交
3072
					 "You must specify the --config-file or -D invocation "
3073 3074 3075
					 "option or set the PGDATA environment variable.\n",
					 progname);
		return false;
3076 3077
	}

3078
	/*
B
Bruce Momjian 已提交
3079 3080
	 * Set the ConfigFileName GUC variable to its final value, ensuring that
	 * it can't be overridden later.
3081 3082 3083 3084 3085 3086 3087
	 */
	SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
	free(fname);

	/*
	 * Now read the config file for the first time.
	 */
3088 3089
	if (stat(ConfigFileName, &stat_buf) != 0)
	{
3090
		write_stderr("%s cannot access the server configuration file \"%s\": %s\n",
3091 3092 3093 3094 3095 3096 3097
					 progname, ConfigFileName, strerror(errno));
		return false;
	}

	ProcessConfigFile(PGC_POSTMASTER);

	/*
3098 3099
	 * If the data_directory GUC variable has been set, use that as DataDir;
	 * otherwise use configdir if set; else punt.
3100
	 *
3101 3102
	 * Note: SetDataDir will copy and absolute-ize its argument, so we don't
	 * have to.
3103
	 */
3104 3105 3106 3107
	if (data_directory)
		SetDataDir(data_directory);
	else if (configdir)
		SetDataDir(configdir);
3108 3109 3110
	else
	{
		write_stderr("%s does not know where to find the database system data.\n"
3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121
					 "This can be specified as \"data_directory\" in \"%s\", "
					 "or by the -D invocation option, or by the "
					 "PGDATA environment variable.\n",
					 progname, ConfigFileName);
		return false;
	}

	/*
	 * Reflect the final DataDir value back into the data_directory GUC var.
	 * (If you are wondering why we don't just make them a single variable,
	 * it's because the EXEC_BACKEND case needs DataDir to be transmitted to
B
Bruce Momjian 已提交
3122 3123 3124
	 * child backends specially.  XXX is that still true?  Given that we now
	 * chdir to DataDir, EXEC_BACKEND can read the config file without knowing
	 * DataDir in advance.)
3125 3126 3127 3128 3129 3130 3131 3132
	 */
	SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);

	/*
	 * Figure out where pg_hba.conf is, and make sure the path is absolute.
	 */
	if (HbaFileName)
		fname = make_absolute_path(HbaFileName);
3133 3134 3135 3136 3137 3138 3139
	else if (configdir)
	{
		fname = guc_malloc(FATAL,
						   strlen(configdir) + strlen(HBA_FILENAME) + 2);
		sprintf(fname, "%s/%s", configdir, HBA_FILENAME);
	}
	else
3140 3141 3142 3143 3144
	{
		write_stderr("%s does not know where to find the \"hba\" configuration file.\n"
					 "This can be specified as \"hba_file\" in \"%s\", "
					 "or by the -D invocation option, or by the "
					 "PGDATA environment variable.\n",
3145 3146 3147
					 progname, ConfigFileName);
		return false;
	}
3148 3149
	SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
	free(fname);
3150 3151

	/*
3152
	 * Likewise for pg_ident.conf.
3153
	 */
3154 3155
	if (IdentFileName)
		fname = make_absolute_path(IdentFileName);
3156 3157 3158 3159 3160 3161 3162
	else if (configdir)
	{
		fname = guc_malloc(FATAL,
						   strlen(configdir) + strlen(IDENT_FILENAME) + 2);
		sprintf(fname, "%s/%s", configdir, IDENT_FILENAME);
	}
	else
3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174
	{
		write_stderr("%s does not know where to find the \"ident\" configuration file.\n"
					 "This can be specified as \"ident_file\" in \"%s\", "
					 "or by the -D invocation option, or by the "
					 "PGDATA environment variable.\n",
					 progname, ConfigFileName);
		return false;
	}
	SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
	free(fname);

	free(configdir);
3175 3176 3177 3178 3179

	return true;
}


3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192
/*
 * Reset all options to their saved default values (implements RESET ALL)
 */
void
ResetAllOptions(void)
{
	int			i;

	for (i = 0; i < num_guc_variables; i++)
	{
		struct config_generic *gconf = guc_variables[i];

		/* Don't reset non-SET-able values */
3193 3194
		if (gconf->context != PGC_SUSET &&
			gconf->context != PGC_USERSET)
3195 3196 3197 3198 3199 3200 3201 3202
			continue;
		/* Don't reset if special exclusion from RESET ALL */
		if (gconf->flags & GUC_NO_RESET_ALL)
			continue;
		/* No need to reset if wasn't SET */
		if (gconf->source <= PGC_S_OVERRIDE)
			continue;

3203 3204 3205
		/* Save old value to support transaction abort */
		push_old_value(gconf);

3206 3207 3208
		switch (gconf->vartype)
		{
			case PGC_BOOL:
B
Bruce Momjian 已提交
3209 3210
				{
					struct config_bool *conf = (struct config_bool *) gconf;
3211

B
Bruce Momjian 已提交
3212
					if (conf->assign_hook)
3213 3214
						if (!(*conf->assign_hook) (conf->reset_val, true,
												   PGC_S_SESSION))
3215
							elog(ERROR, "failed to reset %s", conf->gen.name);
B
Bruce Momjian 已提交
3216 3217 3218 3219 3220 3221 3222 3223
					*conf->variable = conf->reset_val;
					conf->tentative_val = conf->reset_val;
					conf->gen.source = conf->gen.reset_source;
					conf->gen.tentative_source = conf->gen.reset_source;
					conf->gen.status |= GUC_HAVE_TENTATIVE;
					guc_dirty = true;
					break;
				}
3224
			case PGC_INT:
B
Bruce Momjian 已提交
3225 3226
				{
					struct config_int *conf = (struct config_int *) gconf;
3227

B
Bruce Momjian 已提交
3228
					if (conf->assign_hook)
3229 3230
						if (!(*conf->assign_hook) (conf->reset_val, true,
												   PGC_S_SESSION))
3231
							elog(ERROR, "failed to reset %s", conf->gen.name);
B
Bruce Momjian 已提交
3232 3233 3234 3235 3236 3237 3238 3239
					*conf->variable = conf->reset_val;
					conf->tentative_val = conf->reset_val;
					conf->gen.source = conf->gen.reset_source;
					conf->gen.tentative_source = conf->gen.reset_source;
					conf->gen.status |= GUC_HAVE_TENTATIVE;
					guc_dirty = true;
					break;
				}
3240 3241
			case PGC_REAL:
				{
B
Bruce Momjian 已提交
3242 3243 3244
					struct config_real *conf = (struct config_real *) gconf;

					if (conf->assign_hook)
3245 3246
						if (!(*conf->assign_hook) (conf->reset_val, true,
												   PGC_S_SESSION))
3247
							elog(ERROR, "failed to reset %s", conf->gen.name);
B
Bruce Momjian 已提交
3248 3249 3250 3251 3252 3253
					*conf->variable = conf->reset_val;
					conf->tentative_val = conf->reset_val;
					conf->gen.source = conf->gen.reset_source;
					conf->gen.tentative_source = conf->gen.reset_source;
					conf->gen.status |= GUC_HAVE_TENTATIVE;
					guc_dirty = true;
3254 3255
					break;
				}
B
Bruce Momjian 已提交
3256 3257 3258 3259
			case PGC_STRING:
				{
					struct config_string *conf = (struct config_string *) gconf;
					char	   *str;
3260

B
Bruce Momjian 已提交
3261 3262 3263 3264 3265
					if (conf->reset_val == NULL)
					{
						/* Nothing to reset to, as yet; so do nothing */
						break;
					}
3266

B
Bruce Momjian 已提交
3267 3268
					/* We need not strdup here */
					str = conf->reset_val;
3269

B
Bruce Momjian 已提交
3270
					if (conf->assign_hook)
3271
					{
B
Bruce Momjian 已提交
3272 3273
						const char *newstr;

3274 3275
						newstr = (*conf->assign_hook) (str, true,
													   PGC_S_SESSION);
B
Bruce Momjian 已提交
3276
						if (newstr == NULL)
3277
							elog(ERROR, "failed to reset %s", conf->gen.name);
B
Bruce Momjian 已提交
3278 3279 3280
						else if (newstr != str)
						{
							/*
B
Bruce Momjian 已提交
3281
							 * See notes in set_config_option about casting
B
Bruce Momjian 已提交
3282 3283 3284
							 */
							str = (char *) newstr;
						}
3285 3286
					}

3287 3288
					set_string_field(conf, conf->variable, str);
					set_string_field(conf, &conf->tentative_val, str);
B
Bruce Momjian 已提交
3289 3290 3291 3292 3293 3294
					conf->gen.source = conf->gen.reset_source;
					conf->gen.tentative_source = conf->gen.reset_source;
					conf->gen.status |= GUC_HAVE_TENTATIVE;
					guc_dirty = true;
					break;
				}
3295
		}
3296 3297 3298

		if (gconf->flags & GUC_REPORT)
			ReportGUCOption(gconf);
3299 3300 3301 3302 3303
	}
}


/*
3304 3305 3306 3307 3308 3309 3310 3311 3312 3313
 * push_old_value
 *		Push previous state during first assignment to a GUC variable
 *		within a particular transaction.
 *
 * We have to be willing to "back-fill" the state stack if the first
 * assignment occurs within a subtransaction nested several levels deep.
 * This ensures that if an intermediate transaction aborts, it will have
 * the proper value available to restore the setting to.
 */
static void
B
Bruce Momjian 已提交
3314
push_old_value(struct config_generic * gconf)
3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330
{
	int			my_level = GetCurrentTransactionNestLevel();
	GucStack   *stack;

	/* If we're not inside a transaction, do nothing */
	if (my_level == 0)
		return;

	for (;;)
	{
		/* Done if we already pushed it at this nesting depth */
		if (gconf->stack && gconf->stack->nest_level >= my_level)
			return;

		/*
		 * We keep all the stack entries in TopTransactionContext so as to
B
Bruce Momjian 已提交
3331 3332
		 * avoid allocation problems when a subtransaction back-fills stack
		 * entries for upper transaction levels.
3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383
		 */
		stack = (GucStack *) MemoryContextAlloc(TopTransactionContext,
												sizeof(GucStack));

		stack->prev = gconf->stack;
		stack->nest_level = stack->prev ? stack->prev->nest_level + 1 : 1;
		stack->status = gconf->status;
		stack->tentative_source = gconf->tentative_source;
		stack->source = gconf->source;

		switch (gconf->vartype)
		{
			case PGC_BOOL:
				stack->tentative_val.boolval =
					((struct config_bool *) gconf)->tentative_val;
				stack->value.boolval =
					*((struct config_bool *) gconf)->variable;
				break;

			case PGC_INT:
				stack->tentative_val.intval =
					((struct config_int *) gconf)->tentative_val;
				stack->value.intval =
					*((struct config_int *) gconf)->variable;
				break;

			case PGC_REAL:
				stack->tentative_val.realval =
					((struct config_real *) gconf)->tentative_val;
				stack->value.realval =
					*((struct config_real *) gconf)->variable;
				break;

			case PGC_STRING:
				stack->tentative_val.stringval =
					((struct config_string *) gconf)->tentative_val;
				stack->value.stringval =
					*((struct config_string *) gconf)->variable;
				break;
		}

		gconf->stack = stack;

		/* Set state to indicate nothing happened yet within this level */
		gconf->status = GUC_HAVE_STACK;

		/* Ensure we remember to pop at end of xact */
		guc_dirty = true;
	}
}

3384
/*
3385
 * Do GUC processing at transaction or subtransaction commit or abort.
3386 3387
 */
void
3388
AtEOXact_GUC(bool isCommit, bool isSubXact)
3389
{
3390
	int			my_level;
3391 3392 3393 3394 3395 3396
	int			i;

	/* Quick exit if nothing's changed in this transaction */
	if (!guc_dirty)
		return;

3397 3398 3399
	my_level = GetCurrentTransactionNestLevel();
	Assert(isSubXact ? (my_level > 1) : (my_level == 1));

3400 3401 3402
	for (i = 0; i < num_guc_variables; i++)
	{
		struct config_generic *gconf = guc_variables[i];
3403
		int			my_status = gconf->status;
3404 3405
		GucStack   *stack = gconf->stack;
		bool		useTentative;
3406
		bool		changed;
3407

3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419
		/*
		 * Skip if nothing's happened to this var in this transaction
		 */
		if (my_status == 0)
		{
			Assert(stack == NULL);
			continue;
		}
		/* Assert that we stacked old value before changing it */
		Assert(stack != NULL && (my_status & GUC_HAVE_STACK));
		/* However, the last change may have been at an outer xact level */
		if (stack->nest_level < my_level)
3420
			continue;
3421 3422 3423
		Assert(stack->nest_level == my_level);

		/*
B
Bruce Momjian 已提交
3424 3425 3426
		 * We will pop the stack entry.  Start by restoring outer xact status
		 * (since we may want to modify it below).	Be careful to use
		 * my_status to reference the inner xact status below this point...
3427 3428 3429 3430 3431 3432
		 */
		gconf->status = stack->status;

		/*
		 * We have two cases:
		 *
3433 3434
		 * If commit and HAVE_TENTATIVE, set actual value to tentative (this
		 * is to override a SET LOCAL if one occurred later than SET). We keep
B
Bruce Momjian 已提交
3435 3436 3437 3438
		 * the tentative value and propagate HAVE_TENTATIVE to the parent
		 * status, allowing the SET's effect to percolate up. (But if we're
		 * exiting the outermost transaction, we'll drop the HAVE_TENTATIVE
		 * bit below.)
3439
		 *
B
Bruce Momjian 已提交
3440
		 * Otherwise, we have a transaction that aborted or executed only SET
B
Bruce Momjian 已提交
3441 3442 3443
		 * LOCAL (or no SET at all).  In either case it should have no further
		 * effect, so restore both tentative and actual values from the stack
		 * entry.
3444
		 */
3445

3446
		useTentative = isCommit && (my_status & GUC_HAVE_TENTATIVE) != 0;
3447 3448
		changed = false;

3449 3450 3451 3452
		switch (gconf->vartype)
		{
			case PGC_BOOL:
				{
B
Bruce Momjian 已提交
3453
					struct config_bool *conf = (struct config_bool *) gconf;
3454 3455
					bool		newval;
					GucSource	newsource;
3456

3457 3458 3459 3460 3461 3462 3463
					if (useTentative)
					{
						newval = conf->tentative_val;
						newsource = conf->gen.tentative_source;
						conf->gen.status |= GUC_HAVE_TENTATIVE;
					}
					else
B
Bruce Momjian 已提交
3464
					{
3465 3466 3467 3468
						newval = stack->value.boolval;
						newsource = stack->source;
						conf->tentative_val = stack->tentative_val.boolval;
						conf->gen.tentative_source = stack->tentative_source;
B
Bruce Momjian 已提交
3469 3470
					}

3471
					if (*conf->variable != newval)
B
Bruce Momjian 已提交
3472 3473
					{
						if (conf->assign_hook)
3474
							if (!(*conf->assign_hook) (newval,
B
Bruce Momjian 已提交
3475
													   true, PGC_S_OVERRIDE))
3476 3477
								elog(LOG, "failed to commit %s",
									 conf->gen.name);
3478
						*conf->variable = newval;
3479
						changed = true;
B
Bruce Momjian 已提交
3480
					}
3481
					conf->gen.source = newsource;
B
Bruce Momjian 已提交
3482
					break;
3483 3484 3485
				}
			case PGC_INT:
				{
B
Bruce Momjian 已提交
3486
					struct config_int *conf = (struct config_int *) gconf;
3487 3488
					int			newval;
					GucSource	newsource;
3489

3490 3491 3492 3493 3494 3495 3496
					if (useTentative)
					{
						newval = conf->tentative_val;
						newsource = conf->gen.tentative_source;
						conf->gen.status |= GUC_HAVE_TENTATIVE;
					}
					else
B
Bruce Momjian 已提交
3497
					{
3498 3499 3500 3501
						newval = stack->value.intval;
						newsource = stack->source;
						conf->tentative_val = stack->tentative_val.intval;
						conf->gen.tentative_source = stack->tentative_source;
B
Bruce Momjian 已提交
3502 3503
					}

3504
					if (*conf->variable != newval)
B
Bruce Momjian 已提交
3505 3506
					{
						if (conf->assign_hook)
3507
							if (!(*conf->assign_hook) (newval,
B
Bruce Momjian 已提交
3508
													   true, PGC_S_OVERRIDE))
3509 3510
								elog(LOG, "failed to commit %s",
									 conf->gen.name);
3511
						*conf->variable = newval;
3512
						changed = true;
B
Bruce Momjian 已提交
3513
					}
3514
					conf->gen.source = newsource;
B
Bruce Momjian 已提交
3515
					break;
3516 3517 3518
				}
			case PGC_REAL:
				{
B
Bruce Momjian 已提交
3519
					struct config_real *conf = (struct config_real *) gconf;
3520 3521
					double		newval;
					GucSource	newsource;
3522

3523
					if (useTentative)
B
Bruce Momjian 已提交
3524
					{
3525 3526 3527 3528 3529 3530 3531 3532 3533 3534
						newval = conf->tentative_val;
						newsource = conf->gen.tentative_source;
						conf->gen.status |= GUC_HAVE_TENTATIVE;
					}
					else
					{
						newval = stack->value.realval;
						newsource = stack->source;
						conf->tentative_val = stack->tentative_val.realval;
						conf->gen.tentative_source = stack->tentative_source;
B
Bruce Momjian 已提交
3535
					}
3536

3537
					if (*conf->variable != newval)
B
Bruce Momjian 已提交
3538 3539
					{
						if (conf->assign_hook)
3540
							if (!(*conf->assign_hook) (newval,
B
Bruce Momjian 已提交
3541
													   true, PGC_S_OVERRIDE))
3542 3543
								elog(LOG, "failed to commit %s",
									 conf->gen.name);
3544
						*conf->variable = newval;
3545
						changed = true;
B
Bruce Momjian 已提交
3546
					}
3547
					conf->gen.source = newsource;
B
Bruce Momjian 已提交
3548
					break;
3549
				}
B
Bruce Momjian 已提交
3550
			case PGC_STRING:
3551
				{
B
Bruce Momjian 已提交
3552
					struct config_string *conf = (struct config_string *) gconf;
3553 3554
					char	   *newval;
					GucSource	newsource;
3555

3556
					if (useTentative)
B
Bruce Momjian 已提交
3557
					{
3558 3559 3560
						newval = conf->tentative_val;
						newsource = conf->gen.tentative_source;
						conf->gen.status |= GUC_HAVE_TENTATIVE;
B
Bruce Momjian 已提交
3561 3562
					}
					else
3563
					{
3564 3565 3566 3567 3568 3569
						newval = stack->value.stringval;
						newsource = stack->source;
						set_string_field(conf, &conf->tentative_val,
										 stack->tentative_val.stringval);
						conf->gen.tentative_source = stack->tentative_source;
					}
3570

3571 3572
					if (*conf->variable != newval)
					{
B
Bruce Momjian 已提交
3573
						if (conf->assign_hook)
3574
						{
B
Bruce Momjian 已提交
3575 3576
							const char *newstr;

3577
							newstr = (*conf->assign_hook) (newval, true,
B
Bruce Momjian 已提交
3578
														   PGC_S_OVERRIDE);
B
Bruce Momjian 已提交
3579
							if (newstr == NULL)
3580 3581
								elog(LOG, "failed to commit %s",
									 conf->gen.name);
3582
							else if (newstr != newval)
B
Bruce Momjian 已提交
3583 3584
							{
								/*
3585 3586 3587
								 * If newval should now be freed, it'll be
								 * taken care of below.
								 *
3588 3589
								 * See notes in set_config_option about
								 * casting
B
Bruce Momjian 已提交
3590
								 */
3591
								newval = (char *) newstr;
B
Bruce Momjian 已提交
3592
							}
3593 3594
						}

3595
						set_string_field(conf, conf->variable, newval);
3596
						changed = true;
B
Bruce Momjian 已提交
3597
					}
3598 3599 3600 3601 3602 3603 3604 3605 3606
					conf->gen.source = newsource;
					/* Release stacked values if not used anymore */
					set_string_field(conf, &stack->value.stringval,
									 NULL);
					set_string_field(conf, &stack->tentative_val.stringval,
									 NULL);
					/* Don't store tentative value separately after commit */
					if (!isSubXact)
						set_string_field(conf, &conf->tentative_val, NULL);
B
Bruce Momjian 已提交
3607
					break;
3608 3609
				}
		}
3610

3611 3612 3613 3614 3615
		/* Finish popping the state stack */
		gconf->stack = stack->prev;
		pfree(stack);

		/*
B
Bruce Momjian 已提交
3616 3617
		 * If we're now out of all xact levels, forget TENTATIVE status bit;
		 * there's nothing tentative about the value anymore.
3618 3619 3620 3621 3622 3623 3624 3625
		 */
		if (!isSubXact)
		{
			Assert(gconf->stack == NULL);
			gconf->status = 0;
		}

		/* Report new value if we changed it */
3626 3627
		if (changed && (gconf->flags & GUC_REPORT))
			ReportGUCOption(gconf);
3628 3629
	}

3630
	/*
B
Bruce Momjian 已提交
3631 3632 3633 3634
	 * If we're now out of all xact levels, we can clear guc_dirty. (Note: we
	 * cannot reset guc_dirty when exiting a subtransaction, because we know
	 * that all outer transaction levels will have stacked values to deal
	 * with.)
3635 3636 3637
	 */
	if (!isSubXact)
		guc_dirty = false;
3638 3639 3640
}


3641 3642 3643 3644 3645 3646 3647 3648 3649 3650
/*
 * Start up automatic reporting of changes to variables marked GUC_REPORT.
 * This is executed at completion of backend startup.
 */
void
BeginReportingGUCOptions(void)
{
	int			i;

	/*
B
Bruce Momjian 已提交
3651 3652
	 * Don't do anything unless talking to an interactive frontend of protocol
	 * 3.0 or later.
3653
	 */
3654
	if (whereToSendOutput != DestRemote ||
3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673
		PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
		return;

	reporting_enabled = true;

	/* Transmit initial values of interesting variables */
	for (i = 0; i < num_guc_variables; i++)
	{
		struct config_generic *conf = guc_variables[i];

		if (conf->flags & GUC_REPORT)
			ReportGUCOption(conf);
	}
}

/*
 * ReportGUCOption: if appropriate, transmit option value to frontend
 */
static void
3674
ReportGUCOption(struct config_generic * record)
3675 3676 3677
{
	if (reporting_enabled && (record->flags & GUC_REPORT))
	{
3678
		char	   *val = _ShowOption(record, false);
3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690
		StringInfoData msgbuf;

		pq_beginmessage(&msgbuf, 'S');
		pq_sendstring(&msgbuf, record->name);
		pq_sendstring(&msgbuf, val);
		pq_endmessage(&msgbuf);

		pfree(val);
	}
}


3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701
/*
 * Try to interpret value as boolean value.  Valid values are: true,
 * false, yes, no, on, off, 1, 0.  If the string parses okay, return
 * true, else false.  If result is not NULL, return the parsing result
 * there.
 */
static bool
parse_bool(const char *value, bool *result)
{
	size_t		len = strlen(value);

3702
	if (pg_strncasecmp(value, "true", len) == 0)
3703 3704 3705 3706
	{
		if (result)
			*result = true;
	}
3707
	else if (pg_strncasecmp(value, "false", len) == 0)
3708 3709 3710 3711 3712
	{
		if (result)
			*result = false;
	}

3713
	else if (pg_strncasecmp(value, "yes", len) == 0)
3714 3715 3716 3717
	{
		if (result)
			*result = true;
	}
3718
	else if (pg_strncasecmp(value, "no", len) == 0)
3719 3720 3721 3722 3723
	{
		if (result)
			*result = false;
	}

3724 3725
	/* 'o' is not unique enough */
	else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
3726 3727 3728 3729
	{
		if (result)
			*result = true;
	}
3730
	else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
3731 3732 3733 3734 3735
	{
		if (result)
			*result = false;
	}

3736
	else if (pg_strcasecmp(value, "1") == 0)
3737 3738 3739 3740
	{
		if (result)
			*result = true;
	}
3741
	else if (pg_strcasecmp(value, "0") == 0)
3742 3743 3744 3745 3746 3747
	{
		if (result)
			*result = false;
	}

	else
3748 3749 3750
	{
		if (result)
			*result = false;	/* suppress compiler warning */
3751
		return false;
3752
	}
3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764
	return true;
}



/*
 * Try to parse value as an integer.  The accepted formats are the
 * usual decimal, octal, or hexadecimal formats.  If the string parses
 * okay, return true, else false.  If result is not NULL, return the
 * value there.
 */
static bool
3765
parse_int(const char *value, int *result, int flags)
3766 3767 3768 3769 3770 3771
{
	long		val;
	char	   *endptr;

	errno = 0;
	val = strtol(value, &endptr, 0);
3772 3773 3774

	if ((flags & GUC_UNIT_MEMORY) && endptr != value)
	{
B
Bruce Momjian 已提交
3775
		bool		used = false;
3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792

		while (*endptr == ' ')
			endptr++;

		if (strcmp(endptr, "kB") == 0)
		{
			used = true;
			endptr += 2;
		}
		else if (strcmp(endptr, "MB") == 0)
		{
			val *= KB_PER_MB;
			used = true;
			endptr += 2;
		}
		else if (strcmp(endptr, "GB") == 0)
		{
3793
			val *= KB_PER_GB;
3794 3795 3796 3797
			used = true;
			endptr += 2;
		}

3798 3799 3800 3801
#if BLCKSZ < 1024
#error BLCKSZ must be >= 1024
#endif

3802 3803 3804 3805 3806
		if (used)
		{
			switch (flags & GUC_UNIT_MEMORY)
			{
				case GUC_UNIT_BLOCKS:
B
Bruce Momjian 已提交
3807
					val /= (BLCKSZ / 1024);
3808 3809
					break;
				case GUC_UNIT_XBLOCKS:
B
Bruce Momjian 已提交
3810
					val /= (XLOG_BLCKSZ / 1024);
3811 3812 3813
					break;
			}
		}
3814 3815 3816 3817
	}

	if ((flags & GUC_UNIT_TIME) && endptr != value)
	{
B
Bruce Momjian 已提交
3818
		bool		used = false;
3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852

		while (*endptr == ' ')
			endptr++;

		if (strcmp(endptr, "ms") == 0)
		{
			used = true;
			endptr += 2;
		}
		else if (strcmp(endptr, "s") == 0)
		{
			val *= MS_PER_S;
			used = true;
			endptr += 1;
		}
		else if (strcmp(endptr, "min") == 0)
		{
			val *= MS_PER_MIN;
			used = true;
			endptr += 3;
		}
		else if (strcmp(endptr, "h") == 0)
		{
			val *= MS_PER_H;
			used = true;
			endptr += 1;
		}
		else if (strcmp(endptr, "d") == 0)
		{
			val *= MS_PER_D;
			used = true;
			endptr += 1;
		}

3853 3854 3855 3856
		if (used)
		{
			switch (flags & GUC_UNIT_TIME)
			{
B
Bruce Momjian 已提交
3857 3858 3859 3860 3861 3862
				case GUC_UNIT_S:
					val /= MS_PER_S;
					break;
				case GUC_UNIT_MIN:
					val /= MS_PER_MIN;
					break;
3863 3864
			}
		}
3865 3866
	}

3867 3868 3869 3870 3871 3872
	if (endptr == value || *endptr != '\0' || errno == ERANGE
#ifdef HAVE_LONG_INT_64
	/* if long > 32 bits, check for overflow of int4 */
		|| val != (long) ((int32) val)
#endif
		)
3873 3874 3875
	{
		if (result)
			*result = 0;		/* suppress compiler warning */
3876
		return false;
3877
	}
3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898
	if (result)
		*result = (int) val;
	return true;
}



/*
 * Try to parse value as a floating point constant in the usual
 * format.	If the value parsed okay return true, else false.  If
 * result is not NULL, return the semantic value there.
 */
static bool
parse_real(const char *value, double *result)
{
	double		val;
	char	   *endptr;

	errno = 0;
	val = strtod(value, &endptr);
	if (endptr == value || *endptr != '\0' || errno == ERANGE)
3899 3900 3901
	{
		if (result)
			*result = 0;		/* suppress compiler warning */
3902
		return false;
3903
	}
3904 3905 3906 3907 3908 3909
	if (result)
		*result = val;
	return true;
}


3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936
/*
 * Call a GucStringAssignHook function, being careful to free the
 * "newval" string if the hook ereports.
 *
 * This is split out of set_config_option just to avoid the "volatile"
 * qualifiers that would otherwise have to be plastered all over.
 */
static const char *
call_string_assign_hook(GucStringAssignHook assign_hook,
						char *newval, bool doit, GucSource source)
{
	const char *result;

	PG_TRY();
	{
		result = (*assign_hook) (newval, doit, source);
	}
	PG_CATCH();
	{
		free(newval);
		PG_RE_THROW();
	}
	PG_END_TRY();

	return result;
}

3937

3938
/*
3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958
 * Sets option `name' to given value. The value should be a string
 * which is going to be parsed and converted to the appropriate data
 * type.  The context and source parameters indicate in which context this
 * function is being called so it can apply the access restrictions
 * properly.
 *
 * If value is NULL, set the option to its default value. If the
 * parameter changeVal is false then don't really set the option but do all
 * the checks to see if it would work.
 *
 * If there is an error (non-existing option, invalid value) then an
 * ereport(ERROR) is thrown *unless* this is called in a context where we
 * don't want to ereport (currently, startup or SIGHUP config file reread).
 * In that case we write a suitable error message via ereport(DEBUG) and
 * return false. This is working around the deficiencies in the ereport
 * mechanism, so don't blame me.  In all other cases, the function
 * returns true, including cases where the input is valid but we chose
 * not to apply it because of context or source-priority considerations.
 *
 * See also SetConfigOption for an external interface.
3959
 */
3960 3961 3962 3963
bool
set_config_option(const char *name, const char *value,
				  GucContext context, GucSource source,
				  bool isLocal, bool changeVal)
3964
{
3965 3966 3967
	struct config_generic *record;
	int			elevel;
	bool		makeDefault;
3968

3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980
	if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
	{
		/*
		 * To avoid cluttering the log, only the postmaster bleats loudly
		 * about problems with the config file.
		 */
		elevel = IsUnderPostmaster ? DEBUG2 : LOG;
	}
	else if (source == PGC_S_DATABASE || source == PGC_S_USER)
		elevel = INFO;
	else
		elevel = ERROR;
3981

3982 3983 3984 3985 3986 3987 3988
	record = find_option(name, elevel);
	if (record == NULL)
	{
		ereport(elevel,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
			   errmsg("unrecognized configuration parameter \"%s\"", name)));
		return false;
3989 3990
	}

3991 3992 3993 3994 3995 3996 3997
	/*
	 * Do not replace a value that has been set on the command line by a SIGHUP
	 * reload
	 */
	if (context == PGC_SIGHUP && record->source == PGC_S_ARGV)
		return true;

3998 3999 4000 4001 4002
	/*
	 * Check if the option can be set at this time. See guc.h for the precise
	 * rules. Note that we don't want to throw errors if we're in the SIGHUP
	 * context. In that case we just ignore the attempt and return true.
	 */
4003 4004
	switch (record->context)
	{
4005
		case PGC_INTERNAL:
4006 4007
			if (context == PGC_SIGHUP)
				return true;
4008 4009
			if (context != PGC_INTERNAL)
			{
4010 4011
				ereport(elevel,
						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4012
						 errmsg("parameter \"%s\" cannot be changed",
4013
								name)));
4014 4015 4016
				return false;
			}
			break;
4017 4018
		case PGC_POSTMASTER:
			if (context == PGC_SIGHUP)
4019 4020 4021 4022 4023 4024
			{
				if (changeVal && !is_newvalue_equal(record, value))
					ereport(elevel,
							(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
							 errmsg("parameter \"%s\" cannot be changed after server start; configuration file change ignored",
									name)));
4025

4026 4027
				return true;
			}
4028 4029
			if (context != PGC_POSTMASTER)
			{
4030 4031
				ereport(elevel,
						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
B
Bruce Momjian 已提交
4032
						 errmsg("parameter \"%s\" cannot be changed after server start",
4033
								name)));
4034 4035 4036 4037 4038 4039
				return false;
			}
			break;
		case PGC_SIGHUP:
			if (context != PGC_SIGHUP && context != PGC_POSTMASTER)
			{
4040 4041
				ereport(elevel,
						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
4042
						 errmsg("parameter \"%s\" cannot be changed now",
4043
								name)));
4044 4045 4046 4047
				return false;
			}

			/*
B
Bruce Momjian 已提交
4048 4049 4050 4051
			 * Hmm, the idea of the SIGHUP context is "ought to be global, but
			 * can be changed after postmaster start". But there's nothing
			 * that prevents a crafty administrator from sending SIGHUP
			 * signals to individual backends only.
4052 4053 4054 4055 4056 4057
			 */
			break;
		case PGC_BACKEND:
			if (context == PGC_SIGHUP)
			{
				/*
B
Bruce Momjian 已提交
4058 4059 4060 4061 4062 4063
				 * If a PGC_BACKEND parameter is changed in the config file,
				 * we want to accept the new value in the postmaster (whence
				 * it will propagate to subsequently-started backends), but
				 * ignore it in existing backends.	This is a tad klugy, but
				 * necessary because we don't re-read the config file during
				 * backend start.
4064 4065
				 */
				if (IsUnderPostmaster)
4066
					return true;
4067 4068 4069
			}
			else if (context != PGC_BACKEND && context != PGC_POSTMASTER)
			{
4070 4071
				ereport(elevel,
						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
B
Bruce Momjian 已提交
4072
						 errmsg("parameter \"%s\" cannot be set after connection start",
4073
								name)));
4074 4075 4076 4077 4078 4079
				return false;
			}
			break;
		case PGC_SUSET:
			if (context == PGC_USERSET || context == PGC_BACKEND)
			{
4080 4081
				ereport(elevel,
						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
B
Bruce Momjian 已提交
4082
						 errmsg("permission denied to set parameter \"%s\"",
4083
								name)));
4084
				return false;
4085 4086 4087 4088 4089
			}
			break;
		case PGC_USERSET:
			/* always okay */
			break;
4090
	}
4091

4092
	/*
4093 4094 4095 4096
	 * Should we set reset/stacked values?  (If so, the behavior is not
	 * transactional.)  This is done either when we get a default
	 * value from the database's/user's/client's default settings or
	 * when we reset a value to its default.
4097
	 */
4098 4099
	makeDefault = changeVal && (source <= PGC_S_OVERRIDE)
					&& ((value != NULL) || source == PGC_S_DEFAULT);
4100 4101

	/*
4102 4103 4104 4105 4106 4107 4108 4109
	 * Ignore attempted set if overridden by previously processed
	 * setting.  However, if changeVal is false then plow ahead anyway
	 * since we are trying to find out if the value is potentially
	 * good, not actually use it.  Also keep going if makeDefault is
	 * true, since we may want to set the reset/stacked values even if
	 * we can't set the variable itself.  There's one exception to
	 * this rule: if we want to apply the default value to variables
	 * that were removed from the configuration file.  This is
4110
	 * indicated by source == PGC_S_DEFAULT and context == PGC_SIGHUP.
4111
	 */
4112 4113
	if (record->source > source
		&& !(source == PGC_S_DEFAULT && context == PGC_SIGHUP))
4114
	{
4115
		if (changeVal && !makeDefault)
4116
		{
4117
			elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
4118 4119 4120
				 name);
			return true;
		}
4121
		changeVal = false;
4122 4123
	}

4124
	/*
4125
	 * Evaluate value and set variable.
4126
	 */
4127
	switch (record->vartype)
4128 4129 4130
	{
		case PGC_BOOL:
			{
B
Bruce Momjian 已提交
4131
				struct config_bool *conf = (struct config_bool *) record;
4132
				bool		newval;
4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144

				if (value)
				{
					if (!parse_bool(value, &newval))
					{
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						  errmsg("parameter \"%s\" requires a Boolean value",
								 name)));
						return false;
					}
				}
4145 4146 4147 4148 4149 4150 4151 4152
				/*
				 * If value == NULL and source == PGC_S_DEFAULT then
				 * we reset some value to its default (removed from
				 * configuration file).
				 */
				else if (source == PGC_S_DEFAULT)
					newval = conf->boot_val;
				/* else we handle a "RESET varname" command */
4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167
				else
				{
					newval = conf->reset_val;
					source = conf->gen.reset_source;
				}

				if (conf->assign_hook)
					if (!(*conf->assign_hook) (newval, changeVal, source))
					{
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
							 errmsg("invalid value for parameter \"%s\": %d",
									name, (int) newval)));
						return false;
					}
4168

4169
				if (changeVal || makeDefault)
4170
				{
4171 4172 4173
					/* Save old value to support transaction abort */
					if (!makeDefault)
						push_old_value(&conf->gen);
4174
					if (changeVal)
4175
					{
4176 4177 4178 4179 4180
						*conf->variable = newval;
						conf->gen.source = source;
					}
					if (makeDefault)
					{
B
Bruce Momjian 已提交
4181
						GucStack   *stack;
4182

4183 4184 4185 4186 4187
						if (conf->gen.reset_source <= source)
						{
							conf->reset_val = newval;
							conf->gen.reset_source = source;
						}
4188
						for (stack = conf->gen.stack; stack; stack = stack->prev)
4189
						{
4190 4191 4192 4193 4194
							if (stack->source <= source)
							{
								stack->value.boolval = newval;
								stack->source = source;
							}
4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207
						}
					}
					else if (isLocal)
					{
						conf->gen.status |= GUC_HAVE_LOCAL;
						guc_dirty = true;
					}
					else
					{
						conf->tentative_val = newval;
						conf->gen.tentative_source = source;
						conf->gen.status |= GUC_HAVE_TENTATIVE;
						guc_dirty = true;
4208
					}
4209
				}
B
Bruce Momjian 已提交
4210
				break;
4211
			}
4212 4213

		case PGC_INT:
4214
			{
B
Bruce Momjian 已提交
4215
				struct config_int *conf = (struct config_int *) record;
4216
				int			newval;
4217

4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236
				if (value)
				{
					if (!parse_int(value, &newval, conf->gen.flags))
					{
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						 errmsg("parameter \"%s\" requires an integer value",
								name)));
						return false;
					}
					if (newval < conf->min || newval > conf->max)
					{
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
								 errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
										newval, name, conf->min, conf->max)));
						return false;
					}
				}
4237 4238 4239 4240 4241 4242 4243 4244
				/*
				 * If value == NULL and source == PGC_S_DEFAULT then
				 * we reset some value to its default (removed from
				 * configuration file).
				 */
				else if (source == PGC_S_DEFAULT)
					newval = conf->boot_val;
				/* else we handle a "RESET varname" command */
4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259
				else
				{
					newval = conf->reset_val;
					source = conf->gen.reset_source;
				}

				if (conf->assign_hook)
					if (!(*conf->assign_hook) (newval, changeVal, source))
					{
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
							 errmsg("invalid value for parameter \"%s\": %d",
									name, newval)));
						return false;
					}
4260

4261
				if (changeVal || makeDefault)
4262
				{
4263 4264 4265
					/* Save old value to support transaction abort */
					if (!makeDefault)
						push_old_value(&conf->gen);
4266
					if (changeVal)
4267
					{
4268 4269 4270 4271 4272
						*conf->variable = newval;
						conf->gen.source = source;
					}
					if (makeDefault)
					{
B
Bruce Momjian 已提交
4273
						GucStack   *stack;
4274

4275 4276 4277 4278 4279
						if (conf->gen.reset_source <= source)
						{
							conf->reset_val = newval;
							conf->gen.reset_source = source;
						}
4280
						for (stack = conf->gen.stack; stack; stack = stack->prev)
4281
						{
4282 4283 4284 4285 4286
							if (stack->source <= source)
							{
								stack->value.intval = newval;
								stack->source = source;
							}
4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299
						}
					}
					else if (isLocal)
					{
						conf->gen.status |= GUC_HAVE_LOCAL;
						guc_dirty = true;
					}
					else
					{
						conf->tentative_val = newval;
						conf->gen.tentative_source = source;
						conf->gen.status |= GUC_HAVE_TENTATIVE;
						guc_dirty = true;
4300
					}
4301
				}
B
Bruce Momjian 已提交
4302
				break;
4303
			}
4304 4305

		case PGC_REAL:
4306
			{
B
Bruce Momjian 已提交
4307
				struct config_real *conf = (struct config_real *) record;
4308
				double		newval;
4309

4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328
				if (value)
				{
					if (!parse_real(value, &newval))
					{
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						  errmsg("parameter \"%s\" requires a numeric value",
								 name)));
						return false;
					}
					if (newval < conf->min || newval > conf->max)
					{
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
								 errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
										newval, name, conf->min, conf->max)));
						return false;
					}
				}
4329 4330 4331 4332 4333 4334 4335 4336
				/*
				 * If value == NULL and source == PGC_S_DEFAULT then
				 * we reset some value to its default (removed from
				 * configuration file).
				 */
				else if (source == PGC_S_DEFAULT)
					newval = conf->boot_val;
				/* else we handle a "RESET varname" command */
4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351
				else
				{
					newval = conf->reset_val;
					source = conf->gen.reset_source;
				}

				if (conf->assign_hook)
					if (!(*conf->assign_hook) (newval, changeVal, source))
					{
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
							 errmsg("invalid value for parameter \"%s\": %g",
									name, newval)));
						return false;
					}
4352

4353
				if (changeVal || makeDefault)
4354
				{
4355 4356 4357
					/* Save old value to support transaction abort */
					if (!makeDefault)
						push_old_value(&conf->gen);
4358
					if (changeVal)
4359
					{
4360 4361 4362 4363 4364
						*conf->variable = newval;
						conf->gen.source = source;
					}
					if (makeDefault)
					{
B
Bruce Momjian 已提交
4365
						GucStack   *stack;
4366

4367 4368 4369 4370 4371
						if (conf->gen.reset_source <= source)
						{
							conf->reset_val = newval;
							conf->gen.reset_source = source;
						}
4372
						for (stack = conf->gen.stack; stack; stack = stack->prev)
4373
						{
4374 4375 4376 4377 4378
							if (stack->source <= source)
							{
								stack->value.realval = newval;
								stack->source = source;
							}
4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391
						}
					}
					else if (isLocal)
					{
						conf->gen.status |= GUC_HAVE_LOCAL;
						guc_dirty = true;
					}
					else
					{
						conf->tentative_val = newval;
						conf->gen.tentative_source = source;
						conf->gen.status |= GUC_HAVE_TENTATIVE;
						guc_dirty = true;
4392
					}
4393
				}
B
Bruce Momjian 已提交
4394
				break;
4395
			}
4396 4397 4398

		case PGC_STRING:
			{
B
Bruce Momjian 已提交
4399
				struct config_string *conf = (struct config_string *) record;
4400
				char	   *newval;
B
Bruce Momjian 已提交
4401

4402 4403 4404 4405 4406
				if (value)
				{
					newval = guc_strdup(elevel, value);
					if (newval == NULL)
						return false;
B
Bruce Momjian 已提交
4407

4408
					/*
B
Bruce Momjian 已提交
4409 4410
					 * The only sort of "parsing" check we need to do is apply
					 * truncation if GUC_IS_NAME.
4411 4412 4413 4414
					 */
					if (conf->gen.flags & GUC_IS_NAME)
						truncate_identifier(newval, strlen(newval), true);
				}
4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431
				/*
				 * If value == NULL and source == PGC_S_DEFAULT then
				 * we reset some value to its default (removed from
				 * configuration file).
				 */
				else if (source == PGC_S_DEFAULT)
				{
					if (conf->boot_val == NULL)
						newval = NULL;
					else
					{
						newval = guc_strdup(elevel, conf->boot_val);
						if (newval == NULL)
							return false;
					}
				}
				/* else we handle a "RESET varname" command */
4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484
				else if (conf->reset_val)
				{
					/*
					 * We could possibly avoid strdup here, but easier to make
					 * this case work the same as the normal assignment case.
					 */
					newval = guc_strdup(elevel, conf->reset_val);
					if (newval == NULL)
						return false;
					source = conf->gen.reset_source;
				}
				else
				{
					/* Nothing to reset to, as yet; so do nothing */
					break;
				}

				if (conf->assign_hook)
				{
					const char *hookresult;

					/*
					 * If the hook ereports, we have to make sure we free
					 * newval, else it will be a permanent memory leak.
					 */
					hookresult = call_string_assign_hook(conf->assign_hook,
														 newval,
														 changeVal,
														 source);
					if (hookresult == NULL)
					{
						free(newval);
						ereport(elevel,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						 errmsg("invalid value for parameter \"%s\": \"%s\"",
								name, value ? value : "")));
						return false;
					}
					else if (hookresult != newval)
					{
						free(newval);

						/*
						 * Having to cast away const here is annoying, but the
						 * alternative is to declare assign_hooks as returning
						 * char*, which would mean they'd have to cast away
						 * const, or as both taking and returning char*, which
						 * doesn't seem attractive either --- we don't want
						 * them to scribble on the passed str.
						 */
						newval = (char *) hookresult;
					}
				}
4485

4486
				if (changeVal || makeDefault)
4487
				{
4488 4489 4490
					/* Save old value to support transaction abort */
					if (!makeDefault)
						push_old_value(&conf->gen);
4491
					if (changeVal)
4492
					{
4493
						set_string_field(conf, conf->variable, newval);
4494 4495 4496 4497
						conf->gen.source = source;
					}
					if (makeDefault)
					{
B
Bruce Momjian 已提交
4498
						GucStack   *stack;
4499

4500
						if (conf->gen.reset_source <= source)
B
Bruce Momjian 已提交
4501
						{
4502
							set_string_field(conf, &conf->reset_val, newval);
4503
							conf->gen.reset_source = source;
B
Bruce Momjian 已提交
4504
						}
4505
						for (stack = conf->gen.stack; stack; stack = stack->prev)
4506
						{
4507 4508 4509 4510 4511 4512
							if (stack->source <= source)
							{
								set_string_field(conf, &stack->value.stringval,
												 newval);
								stack->source = source;
							}
4513
						}
4514
						/* Perhaps we didn't install newval anywhere */
4515
						if (!string_field_used(conf, newval))
4516
							free(newval);
B
Bruce Momjian 已提交
4517
					}
4518
					else if (isLocal)
4519
					{
4520 4521
						conf->gen.status |= GUC_HAVE_LOCAL;
						guc_dirty = true;
4522
					}
4523
					else
4524
					{
4525
						set_string_field(conf, &conf->tentative_val, newval);
4526 4527 4528
						conf->gen.tentative_source = source;
						conf->gen.status |= GUC_HAVE_TENTATIVE;
						guc_dirty = true;
4529
					}
4530 4531
				}
				else
4532
					free(newval);
B
Bruce Momjian 已提交
4533
				break;
4534
			}
4535
	}
4536

4537
	if (changeVal && (record->flags & GUC_REPORT))
4538
		ReportGUCOption(record);
4539

4540 4541 4542 4543 4544 4545
	return true;
}


/*
 * Set a config option to the given value. See also set_config_option,
B
Bruce Momjian 已提交
4546
 * this is just the wrapper to be called from outside GUC.	NB: this
4547
 * is used only for non-transactional operations.
4548 4549
 */
void
4550
SetConfigOption(const char *name, const char *value,
4551
				GucContext context, GucSource source)
4552
{
4553
	(void) set_config_option(name, value, context, source, false, true);
4554 4555 4556 4557 4558
}



/*
4559
 * Fetch the current value of the option `name'. If the option doesn't exist,
4560
 * throw an ereport and don't return.
4561 4562 4563 4564 4565
 *
 * The string is *not* allocated for modification and is really only
 * valid until the next call to configuration related functions.
 */
const char *
B
Bruce Momjian 已提交
4566
GetConfigOption(const char *name)
4567
{
B
Bruce Momjian 已提交
4568
	struct config_generic *record;
4569 4570
	static char buffer[256];

4571
	record = find_option(name, ERROR);
4572
	if (record == NULL)
4573 4574
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
B
Bruce Momjian 已提交
4575
			   errmsg("unrecognized configuration parameter \"%s\"", name)));
4576 4577 4578 4579
	if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("must be superuser to examine \"%s\"", name)));
4580

4581
	switch (record->vartype)
4582 4583
	{
		case PGC_BOOL:
B
Bruce Momjian 已提交
4584
			return *((struct config_bool *) record)->variable ? "on" : "off";
4585

4586
		case PGC_INT:
4587 4588
			snprintf(buffer, sizeof(buffer), "%d",
					 *((struct config_int *) record)->variable);
4589 4590
			return buffer;

4591
		case PGC_REAL:
4592 4593
			snprintf(buffer, sizeof(buffer), "%g",
					 *((struct config_real *) record)->variable);
4594 4595 4596
			return buffer;

		case PGC_STRING:
B
Bruce Momjian 已提交
4597
			return *((struct config_string *) record)->variable;
4598 4599 4600
	}
	return NULL;
}
4601

4602 4603 4604 4605 4606
/*
 * Get the RESET value associated with the given option.
 */
const char *
GetConfigOptionResetString(const char *name)
4607
{
4608 4609
	struct config_generic *record;
	static char buffer[256];
4610

4611
	record = find_option(name, ERROR);
4612
	if (record == NULL)
4613 4614
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
B
Bruce Momjian 已提交
4615
			   errmsg("unrecognized configuration parameter \"%s\"", name)));
4616 4617 4618 4619
	if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("must be superuser to examine \"%s\"", name)));
4620 4621

	switch (record->vartype)
4622 4623
	{
		case PGC_BOOL:
4624
			return ((struct config_bool *) record)->reset_val ? "on" : "off";
4625

4626
		case PGC_INT:
4627
			snprintf(buffer, sizeof(buffer), "%d",
4628 4629
					 ((struct config_int *) record)->reset_val);
			return buffer;
4630 4631

		case PGC_REAL:
4632
			snprintf(buffer, sizeof(buffer), "%g",
4633 4634
					 ((struct config_real *) record)->reset_val);
			return buffer;
4635 4636

		case PGC_STRING:
4637 4638 4639 4640
			return ((struct config_string *) record)->reset_val;
	}
	return NULL;
}
4641

4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656
/*
 * Detect whether the given configuration option can only be set by
 * a superuser.
 */
bool
IsSuperuserConfigOption(const char *name)
{
	struct config_generic *record;

	record = find_option(name, ERROR);
	/* On an unrecognized name, don't error, just return false. */
	if (record == NULL)
		return false;
	return (record->context == PGC_SUSET);
}
4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675


/*
 * flatten_set_variable_args
 *		Given a parsenode List as emitted by the grammar for SET,
 *		convert to the flat string representation used by GUC.
 *
 * We need to be told the name of the variable the args are for, because
 * the flattening rules vary (ugh).
 *
 * The result is NULL if input is NIL (ie, SET ... TO DEFAULT), otherwise
 * a palloc'd string.
 */
char *
flatten_set_variable_args(const char *name, List *args)
{
	struct config_generic *record;
	int			flags;
	StringInfoData buf;
4676
	ListCell   *l;
4677

4678
	/*
B
Bruce Momjian 已提交
4679 4680
	 * Fast path if just DEFAULT.  We do not check the variable name in this
	 * case --- necessary for RESET ALL to work correctly.
4681
	 */
4682 4683 4684
	if (args == NIL)
		return NULL;

4685
	/* Else get flags for the variable */
4686
	record = find_option(name, ERROR);
4687
	if (record == NULL)
4688 4689
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
B
Bruce Momjian 已提交
4690
			   errmsg("unrecognized configuration parameter \"%s\"", name)));
4691 4692

	flags = record->flags;
4693 4694 4695

	/* Complain if list input and non-list variable */
	if ((flags & GUC_LIST_INPUT) == 0 &&
4696
		list_length(args) != 1)
4697 4698 4699
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("SET %s takes only one argument", name)));
4700 4701 4702 4703 4704 4705 4706 4707

	initStringInfo(&buf);

	foreach(l, args)
	{
		A_Const    *arg = (A_Const *) lfirst(l);
		char	   *val;

4708
		if (l != list_head(args))
4709 4710 4711
			appendStringInfo(&buf, ", ");

		if (!IsA(arg, A_Const))
4712
			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
4713 4714 4715 4716 4717 4718 4719 4720

		switch (nodeTag(&arg->val))
		{
			case T_Integer:
				appendStringInfo(&buf, "%ld", intVal(&arg->val));
				break;
			case T_Float:
				/* represented as a string, so just copy it */
N
Neil Conway 已提交
4721
				appendStringInfoString(&buf, strVal(&arg->val));
4722 4723 4724 4725 4726 4727
				break;
			case T_String:
				val = strVal(&arg->val);
				if (arg->typename != NULL)
				{
					/*
B
Bruce Momjian 已提交
4728 4729 4730
					 * Must be a ConstInterval argument for TIME ZONE. Coerce
					 * to interval and back to normalize the value and account
					 * for any typmod.
4731
					 */
4732
					int32		typmod;
B
Bruce Momjian 已提交
4733
					Datum		interval;
B
Bruce Momjian 已提交
4734
					char	   *intervalout;
4735

4736 4737
					typmod = typenameTypeMod(NULL, arg->typename, INTERVALOID);

4738
					interval =
B
Bruce Momjian 已提交
4739 4740 4741
						DirectFunctionCall3(interval_in,
											CStringGetDatum(val),
											ObjectIdGetDatum(InvalidOid),
4742
											Int32GetDatum(typmod));
4743 4744

					intervalout =
4745 4746
						DatumGetCString(DirectFunctionCall1(interval_out,
															interval));
4747 4748 4749 4750 4751
					appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
				}
				else
				{
					/*
B
Bruce Momjian 已提交
4752 4753
					 * Plain string literal or identifier.	For quote mode,
					 * quote it if it's not a vanilla identifier.
4754 4755
					 */
					if (flags & GUC_LIST_QUOTE)
N
Neil Conway 已提交
4756
						appendStringInfoString(&buf, quote_identifier(val));
4757
					else
N
Neil Conway 已提交
4758
						appendStringInfoString(&buf, val);
4759 4760 4761
				}
				break;
			default:
4762 4763
				elog(ERROR, "unrecognized node type: %d",
					 (int) nodeTag(&arg->val));
4764 4765
				break;
		}
4766
	}
4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788

	return buf.data;
}


/*
 * SET command
 */
void
SetPGVariable(const char *name, List *args, bool is_local)
{
	char	   *argstring = flatten_set_variable_args(name, args);

	/* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
	set_config_option(name,
					  argstring,
					  (superuser() ? PGC_SUSET : PGC_USERSET),
					  PGC_S_SESSION,
					  is_local,
					  true);
}

4789 4790 4791 4792 4793 4794
/*
 * SET command wrapped as a SQL callable function.
 */
Datum
set_config_by_name(PG_FUNCTION_ARGS)
{
B
Bruce Momjian 已提交
4795 4796 4797 4798 4799
	char	   *name;
	char	   *value;
	char	   *new_value;
	bool		is_local;
	text	   *result_text;
4800 4801

	if (PG_ARGISNULL(0))
4802 4803
		ereport(ERROR,
				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4804
				 errmsg("SET requires parameter name")));
4805 4806

	/* Get the GUC variable name */
4807
	name = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(0)));
4808 4809 4810 4811 4812

	/* Get the desired value or set to NULL for a reset request */
	if (PG_ARGISNULL(1))
		value = NULL;
	else
4813
		value = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(1)));
4814 4815

	/*
B
Bruce Momjian 已提交
4816 4817
	 * Get the desired state of is_local. Default to false if provided value
	 * is NULL
4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832
	 */
	if (PG_ARGISNULL(2))
		is_local = false;
	else
		is_local = PG_GETARG_BOOL(2);

	/* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
	set_config_option(name,
					  value,
					  (superuser() ? PGC_SUSET : PGC_USERSET),
					  PGC_S_SESSION,
					  is_local,
					  true);

	/* get the new current value */
4833
	new_value = GetConfigOptionByName(name, NULL);
4834 4835 4836 4837 4838 4839 4840 4841

	/* Convert return string to text */
	result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(new_value)));

	/* return it */
	PG_RETURN_TEXT_P(result_text);
}

4842
static void
B
Bruce Momjian 已提交
4843
define_custom_variable(struct config_generic * variable)
4844
{
B
Bruce Momjian 已提交
4845 4846 4847 4848 4849
	const char *name = variable->name;
	const char **nameAddr = &name;
	const char *value;
	struct config_string *pHolder;
	struct config_generic **res = (struct config_generic **) bsearch(
B
Bruce Momjian 已提交
4850 4851 4852 4853 4854
														  (void *) &nameAddr,
													  (void *) guc_variables,
														   num_guc_variables,
											 sizeof(struct config_generic *),
															guc_var_compare);
B
Bruce Momjian 已提交
4855 4856

	if (res == NULL)
4857
	{
4858
		add_guc_variable(variable, ERROR);
4859 4860 4861
		return;
	}

B
Bruce Momjian 已提交
4862 4863
	/*
	 * This better be a placeholder
4864
	 */
B
Bruce Momjian 已提交
4865
	if (((*res)->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
4866 4867 4868
		ereport(ERROR,
				(errcode(ERRCODE_INTERNAL_ERROR),
				 errmsg("attempt to redefine parameter \"%s\"", name)));
4869 4870

	Assert((*res)->vartype == PGC_STRING);
B
Bruce Momjian 已提交
4871 4872
	pHolder = (struct config_string *) * res;

4873
	/* We have the same name, no sorting is necessary */
4874 4875 4876 4877
	*res = variable;

	value = *pHolder->variable;

4878
	/*
B
Bruce Momjian 已提交
4879
	 * Assign the string value stored in the placeholder to the real variable.
4880 4881 4882 4883
	 *
	 * XXX this is not really good enough --- it should be a nontransactional
	 * assignment, since we don't want it to roll back if the current xact
	 * fails later.
4884 4885
	 */
	set_config_option(name, value,
B
Bruce Momjian 已提交
4886 4887
					  pHolder->gen.context, pHolder->gen.source,
					  false, true);
4888

4889 4890 4891
	/*
	 * Free up as much as we conveniently can of the placeholder structure
	 * (this neglects any stack items...)
4892
	 */
4893 4894 4895
	set_string_field(pHolder, pHolder->variable, NULL);
	set_string_field(pHolder, &pHolder->reset_val, NULL);
	set_string_field(pHolder, &pHolder->tentative_val, NULL);
4896 4897 4898 4899

	free(pHolder);
}

B
Bruce Momjian 已提交
4900
static void
4901
init_custom_variable(struct config_generic * gen,
B
Bruce Momjian 已提交
4902 4903 4904 4905 4906
					 const char *name,
					 const char *short_desc,
					 const char *long_desc,
					 GucContext context,
					 enum config_type type)
4907
{
B
Bruce Momjian 已提交
4908 4909 4910
	gen->name = guc_strdup(ERROR, name);
	gen->context = context;
	gen->group = CUSTOM_OPTIONS;
4911
	gen->short_desc = short_desc;
B
Bruce Momjian 已提交
4912 4913
	gen->long_desc = long_desc;
	gen->vartype = type;
4914 4915
}

B
Bruce Momjian 已提交
4916
void
4917
DefineCustomBoolVariable(const char *name,
B
Bruce Momjian 已提交
4918 4919 4920 4921 4922 4923
						 const char *short_desc,
						 const char *long_desc,
						 bool *valueAddr,
						 GucContext context,
						 GucBoolAssignHook assign_hook,
						 GucShowHook show_hook)
4924
{
B
Bruce Momjian 已提交
4925 4926
	size_t		sz = sizeof(struct config_bool);
	struct config_bool *var = (struct config_bool *) guc_malloc(ERROR, sz);
4927 4928 4929 4930

	memset(var, 0, sz);
	init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_BOOL);

B
Bruce Momjian 已提交
4931 4932
	var->variable = valueAddr;
	var->reset_val = *valueAddr;
4933
	var->assign_hook = assign_hook;
B
Bruce Momjian 已提交
4934
	var->show_hook = show_hook;
4935 4936 4937
	define_custom_variable(&var->gen);
}

B
Bruce Momjian 已提交
4938
void
4939
DefineCustomIntVariable(const char *name,
B
Bruce Momjian 已提交
4940 4941 4942
						const char *short_desc,
						const char *long_desc,
						int *valueAddr,
4943 4944
						int minValue,
						int maxValue,
B
Bruce Momjian 已提交
4945 4946 4947
						GucContext context,
						GucIntAssignHook assign_hook,
						GucShowHook show_hook)
4948
{
B
Bruce Momjian 已提交
4949 4950
	size_t		sz = sizeof(struct config_int);
	struct config_int *var = (struct config_int *) guc_malloc(ERROR, sz);
4951 4952 4953 4954

	memset(var, 0, sz);
	init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_INT);

B
Bruce Momjian 已提交
4955 4956
	var->variable = valueAddr;
	var->reset_val = *valueAddr;
4957 4958
	var->min = minValue;
	var->max = maxValue;
4959
	var->assign_hook = assign_hook;
B
Bruce Momjian 已提交
4960
	var->show_hook = show_hook;
4961 4962 4963
	define_custom_variable(&var->gen);
}

B
Bruce Momjian 已提交
4964
void
4965
DefineCustomRealVariable(const char *name,
B
Bruce Momjian 已提交
4966 4967 4968
						 const char *short_desc,
						 const char *long_desc,
						 double *valueAddr,
4969 4970
						 double minValue,
						 double maxValue,
B
Bruce Momjian 已提交
4971 4972 4973
						 GucContext context,
						 GucRealAssignHook assign_hook,
						 GucShowHook show_hook)
4974
{
B
Bruce Momjian 已提交
4975 4976
	size_t		sz = sizeof(struct config_real);
	struct config_real *var = (struct config_real *) guc_malloc(ERROR, sz);
4977 4978 4979 4980

	memset(var, 0, sz);
	init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_REAL);

B
Bruce Momjian 已提交
4981 4982
	var->variable = valueAddr;
	var->reset_val = *valueAddr;
4983 4984
	var->min = minValue;
	var->max = maxValue;
4985
	var->assign_hook = assign_hook;
B
Bruce Momjian 已提交
4986
	var->show_hook = show_hook;
4987 4988 4989
	define_custom_variable(&var->gen);
}

B
Bruce Momjian 已提交
4990
void
4991
DefineCustomStringVariable(const char *name,
B
Bruce Momjian 已提交
4992 4993 4994 4995 4996 4997
						   const char *short_desc,
						   const char *long_desc,
						   char **valueAddr,
						   GucContext context,
						   GucStringAssignHook assign_hook,
						   GucShowHook show_hook)
4998
{
B
Bruce Momjian 已提交
4999 5000
	size_t		sz = sizeof(struct config_string);
	struct config_string *var = (struct config_string *) guc_malloc(ERROR, sz);
5001 5002 5003 5004

	memset(var, 0, sz);
	init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_STRING);

B
Bruce Momjian 已提交
5005 5006
	var->variable = valueAddr;
	var->reset_val = *valueAddr;
5007
	var->assign_hook = assign_hook;
B
Bruce Momjian 已提交
5008
	var->show_hook = show_hook;
5009 5010 5011
	define_custom_variable(&var->gen);
}

N
Neil Conway 已提交
5012
void
B
Bruce Momjian 已提交
5013
EmitWarningsOnPlaceholders(const char *className)
5014
{
B
Bruce Momjian 已提交
5015 5016 5017 5018
	struct config_generic **vars = guc_variables;
	struct config_generic **last = vars + num_guc_variables;

	int			nameLen = strlen(className);
5019

B
Bruce Momjian 已提交
5020
	while (vars < last)
5021
	{
B
Bruce Momjian 已提交
5022 5023 5024 5025 5026
		struct config_generic *var = *vars++;

		if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
			strncmp(className, var->name, nameLen) == 0 &&
			var->name[nameLen] == GUC_QUALIFIER_SEPARATOR)
5027 5028
		{
			ereport(INFO,
B
Bruce Momjian 已提交
5029 5030
					(errcode(ERRCODE_UNDEFINED_OBJECT),
					 errmsg("unrecognized configuration parameter \"%s\"", var->name)));
5031 5032 5033 5034 5035
		}
	}
}


5036 5037 5038 5039
/*
 * SHOW command
 */
void
5040
GetPGVariable(const char *name, DestReceiver *dest)
5041
{
5042
	if (pg_strcasecmp(name, "all") == 0)
5043
		ShowAllGUCConfig(dest);
5044
	else
5045 5046 5047 5048 5049 5050 5051 5052
		ShowGUCConfigOption(name, dest);
}

TupleDesc
GetPGVariableResultDesc(const char *name)
{
	TupleDesc	tupdesc;

5053
	if (pg_strcasecmp(name, "all") == 0)
5054
	{
5055 5056
		/* need a tuple descriptor representing three TEXT columns */
		tupdesc = CreateTemplateTupleDesc(3, false);
5057
		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
5058
						   TEXTOID, -1, 0);
5059
		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
5060
						   TEXTOID, -1, 0);
5061 5062 5063
		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
						   TEXTOID, -1, 0);

5064 5065 5066 5067 5068 5069 5070 5071 5072 5073
	}
	else
	{
		const char *varname;

		/* Get the canonical spelling of name */
		(void) GetConfigOptionByName(name, &varname);

		/* need a tuple descriptor representing a single TEXT column */
		tupdesc = CreateTemplateTupleDesc(1, false);
5074 5075
		TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
						   TEXTOID, -1, 0);
5076 5077
	}
	return tupdesc;
5078 5079 5080 5081 5082 5083
}

/*
 * RESET command
 */
void
5084
ResetPGVariable(const char *name, bool isTopLevel)
5085
{
5086
	if (pg_strcasecmp(name, "all") == 0)
5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100
		ResetAllOptions();
	else
		set_config_option(name,
						  NULL,
						  (superuser() ? PGC_SUSET : PGC_USERSET),
						  PGC_S_SESSION,
						  false,
						  true);
}


/*
 * SHOW command
 */
5101
static void
5102
ShowGUCConfigOption(const char *name, DestReceiver *dest)
5103
{
5104
	TupOutputState *tstate;
B
Bruce Momjian 已提交
5105 5106 5107
	TupleDesc	tupdesc;
	const char *varname;
	char	   *value;
5108

5109 5110 5111
	/* Get the value and canonical spelling of name */
	value = GetConfigOptionByName(name, &varname);

5112
	/* need a tuple descriptor representing a single TEXT column */
5113
	tupdesc = CreateTemplateTupleDesc(1, false);
5114
	TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
5115
					   TEXTOID, -1, 0);
5116

5117 5118 5119 5120
	/* prepare for projection of tuples */
	tstate = begin_tup_output_tupdesc(dest, tupdesc);

	/* Send it */
5121
	do_text_output_oneline(tstate, value);
5122 5123

	end_tup_output(tstate);
5124 5125
}

5126 5127 5128
/*
 * SHOW ALL command
 */
5129
static void
5130
ShowAllGUCConfig(DestReceiver *dest)
5131
{
5132
	bool		am_superuser = superuser();
5133
	int			i;
5134
	TupOutputState *tstate;
B
Bruce Momjian 已提交
5135
	TupleDesc	tupdesc;
5136
	char	   *values[3];
5137

5138 5139
	/* need a tuple descriptor representing three TEXT columns */
	tupdesc = CreateTemplateTupleDesc(3, false);
5140
	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
5141
					   TEXTOID, -1, 0);
5142
	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
5143
					   TEXTOID, -1, 0);
5144 5145
	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
					   TEXTOID, -1, 0);
B
Bruce Momjian 已提交
5146

5147 5148 5149

	/* prepare for projection of tuples */
	tstate = begin_tup_output_tupdesc(dest, tupdesc);
5150

5151 5152
	for (i = 0; i < num_guc_variables; i++)
	{
5153 5154
		struct config_generic *conf = guc_variables[i];

5155 5156
		if ((conf->flags & GUC_NO_SHOW_ALL) ||
			((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser))
5157
			continue;
5158 5159

		/* assign to the values array */
5160
		values[0] = (char *) conf->name;
5161
		values[1] = _ShowOption(conf, true);
5162
		values[2] = (char *) conf->short_desc;
5163 5164 5165

		/* send it to dest */
		do_tup_output(tstate, values);
5166

5167
		/* clean up */
5168 5169
		if (values[1] != NULL)
			pfree(values[1]);
5170
	}
5171 5172

	end_tup_output(tstate);
5173
}
5174

5175
/*
5176 5177
 * Return GUC variable value by name; optionally return canonical
 * form of name.  Return value is palloc'd.
5178 5179
 */
char *
5180
GetConfigOptionByName(const char *name, const char **varname)
5181 5182 5183
{
	struct config_generic *record;

5184
	record = find_option(name, ERROR);
5185
	if (record == NULL)
5186 5187
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
B
Bruce Momjian 已提交
5188
			   errmsg("unrecognized configuration parameter \"%s\"", name)));
5189 5190 5191 5192
	if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("must be superuser to examine \"%s\"", name)));
5193

5194 5195 5196
	if (varname)
		*varname = record->name;

5197
	return _ShowOption(record, true);
5198 5199 5200
}

/*
5201 5202
 * Return GUC variable value by variable number; optionally return canonical
 * form of name.  Return value is palloc'd.
5203
 */
5204 5205
void
GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
5206
{
B
Bruce Momjian 已提交
5207 5208
	char		buffer[256];
	struct config_generic *conf;
5209 5210 5211 5212 5213

	/* check requested variable number valid */
	Assert((varnum >= 0) && (varnum < num_guc_variables));

	conf = guc_variables[varnum];
5214

5215
	if (noshow)
5216 5217 5218 5219 5220 5221 5222
	{
		if ((conf->flags & GUC_NO_SHOW_ALL) ||
			((conf->flags & GUC_SUPERUSER_ONLY) && !superuser()))
			*noshow = true;
		else
			*noshow = false;
	}
5223

5224 5225 5226 5227 5228 5229
	/* first get the generic attributes */

	/* name */
	values[0] = conf->name;

	/* setting : use _ShowOption in order to avoid duplicating the logic */
5230 5231 5232 5233 5234
	values[1] = _ShowOption(conf, false);

	/* unit */
	if (conf->vartype == PGC_INT)
	{
5235
		static char buf[8];
5236

5237 5238 5239 5240 5241 5242
		switch (conf->flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME))
		{
			case GUC_UNIT_KB:
				values[2] = "kB";
				break;
			case GUC_UNIT_BLOCKS:
B
Bruce Momjian 已提交
5243
				snprintf(buf, sizeof(buf), "%dkB", BLCKSZ / 1024);
5244 5245 5246
				values[2] = buf;
				break;
			case GUC_UNIT_XBLOCKS:
B
Bruce Momjian 已提交
5247
				snprintf(buf, sizeof(buf), "%dkB", XLOG_BLCKSZ / 1024);
5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261
				values[2] = buf;
				break;
			case GUC_UNIT_MS:
				values[2] = "ms";
				break;
			case GUC_UNIT_S:
				values[2] = "s";
				break;
			case GUC_UNIT_MIN:
				values[2] = "min";
				break;
			default:
				values[2] = "";
				break;
5262 5263 5264 5265
		}
	}
	else
		values[2] = NULL;
5266

5267
	/* group */
5268
	values[3] = config_group_names[conf->group];
5269 5270

	/* short_desc */
5271
	values[4] = conf->short_desc;
5272 5273

	/* extra_desc */
5274
	values[5] = conf->long_desc;
5275

5276
	/* context */
5277
	values[6] = GucContext_Names[conf->context];
5278 5279

	/* vartype */
5280
	values[7] = config_type_names[conf->vartype];
5281 5282

	/* source */
5283
	values[8] = GucSource_Names[conf->source];
5284 5285 5286 5287 5288 5289 5290

	/* now get the type specifc attributes */
	switch (conf->vartype)
	{
		case PGC_BOOL:
			{
				/* min_val */
5291
				values[9] = NULL;
5292 5293

				/* max_val */
5294
				values[10] = NULL;
5295 5296 5297 5298 5299 5300 5301 5302 5303
			}
			break;

		case PGC_INT:
			{
				struct config_int *lconf = (struct config_int *) conf;

				/* min_val */
				snprintf(buffer, sizeof(buffer), "%d", lconf->min);
5304
				values[9] = pstrdup(buffer);
5305 5306 5307

				/* max_val */
				snprintf(buffer, sizeof(buffer), "%d", lconf->max);
5308
				values[10] = pstrdup(buffer);
5309 5310 5311 5312 5313 5314 5315 5316 5317
			}
			break;

		case PGC_REAL:
			{
				struct config_real *lconf = (struct config_real *) conf;

				/* min_val */
				snprintf(buffer, sizeof(buffer), "%g", lconf->min);
5318
				values[9] = pstrdup(buffer);
5319 5320 5321

				/* max_val */
				snprintf(buffer, sizeof(buffer), "%g", lconf->max);
5322
				values[10] = pstrdup(buffer);
5323 5324 5325 5326 5327 5328
			}
			break;

		case PGC_STRING:
			{
				/* min_val */
5329
				values[9] = NULL;
5330 5331

				/* max_val */
5332
				values[10] = NULL;
5333 5334 5335 5336 5337 5338
			}
			break;

		default:
			{
				/*
B
Bruce Momjian 已提交
5339
				 * should never get here, but in case we do, set 'em to NULL
5340 5341 5342
				 */

				/* min_val */
5343
				values[9] = NULL;
5344 5345

				/* max_val */
5346
				values[10] = NULL;
5347 5348 5349
			}
			break;
	}
5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367
}

/*
 * Return the total number of GUC variables
 */
int
GetNumConfigOptions(void)
{
	return num_guc_variables;
}

/*
 * show_config_by_name - equiv to SHOW X command but implemented as
 * a function.
 */
Datum
show_config_by_name(PG_FUNCTION_ARGS)
{
B
Bruce Momjian 已提交
5368 5369 5370
	char	   *varname;
	char	   *varval;
	text	   *result_text;
5371 5372

	/* Get the GUC variable name */
5373
	varname = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(0)));
5374 5375

	/* Get the value */
5376
	varval = GetConfigOptionByName(varname, NULL);
5377 5378 5379 5380 5381 5382 5383 5384

	/* Convert to text */
	result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(varval)));

	/* return it */
	PG_RETURN_TEXT_P(result_text);
}

5385 5386 5387 5388
/*
 * show_all_settings - equiv to SHOW ALL command but implemented as
 * a Table Function.
 */
5389
#define NUM_PG_SETTINGS_ATTS	11
5390

5391 5392 5393
Datum
show_all_settings(PG_FUNCTION_ARGS)
{
B
Bruce Momjian 已提交
5394 5395 5396 5397 5398 5399
	FuncCallContext *funcctx;
	TupleDesc	tupdesc;
	int			call_cntr;
	int			max_calls;
	AttInMetadata *attinmeta;
	MemoryContext oldcontext;
5400 5401

	/* stuff done only on the first call of the function */
B
Bruce Momjian 已提交
5402 5403
	if (SRF_IS_FIRSTCALL())
	{
5404
		/* create a function context for cross-call persistence */
B
Bruce Momjian 已提交
5405
		funcctx = SRF_FIRSTCALL_INIT();
5406

B
Bruce Momjian 已提交
5407
		/*
B
Bruce Momjian 已提交
5408
		 * switch to memory context appropriate for multiple function calls
B
Bruce Momjian 已提交
5409
		 */
5410 5411
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

5412
		/*
B
Bruce Momjian 已提交
5413 5414
		 * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
		 * of the appropriate types
5415 5416
		 */
		tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS, false);
5417
		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
5418
						   TEXTOID, -1, 0);
5419
		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
5420
						   TEXTOID, -1, 0);
5421 5422 5423
		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit",
						   TEXTOID, -1, 0);
		TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category",
5424
						   TEXTOID, -1, 0);
5425
		TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc",
5426
						   TEXTOID, -1, 0);
5427
		TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc",
5428
						   TEXTOID, -1, 0);
5429
		TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context",
5430
						   TEXTOID, -1, 0);
5431
		TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype",
5432
						   TEXTOID, -1, 0);
5433
		TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source",
5434
						   TEXTOID, -1, 0);
5435
		TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val",
5436
						   TEXTOID, -1, 0);
5437
		TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
5438
						   TEXTOID, -1, 0);
5439 5440

		/*
B
Bruce Momjian 已提交
5441 5442
		 * Generate attribute metadata needed later to produce tuples from raw
		 * C strings
5443 5444 5445 5446 5447 5448
		 */
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		funcctx->attinmeta = attinmeta;

		/* total number of tuples to be returned */
		funcctx->max_calls = GetNumConfigOptions();
5449 5450

		MemoryContextSwitchTo(oldcontext);
B
Bruce Momjian 已提交
5451
	}
5452 5453

	/* stuff done on every call of the function */
B
Bruce Momjian 已提交
5454
	funcctx = SRF_PERCALL_SETUP();
5455 5456 5457 5458 5459

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;
	attinmeta = funcctx->attinmeta;

B
Bruce Momjian 已提交
5460 5461
	if (call_cntr < max_calls)	/* do when there is more left to send */
	{
5462
		char	   *values[NUM_PG_SETTINGS_ATTS];
5463 5464 5465 5466 5467 5468 5469 5470 5471
		bool		noshow;
		HeapTuple	tuple;
		Datum		result;

		/*
		 * Get the next visible GUC variable name and value
		 */
		do
		{
5472
			GetConfigOptionByNum(call_cntr, (const char **) values, &noshow);
5473 5474 5475 5476 5477 5478 5479
			if (noshow)
			{
				/* bump the counter and get the next config setting */
				call_cntr = ++funcctx->call_cntr;

				/* make sure we haven't gone too far now */
				if (call_cntr >= max_calls)
B
Bruce Momjian 已提交
5480
					SRF_RETURN_DONE(funcctx);
5481 5482 5483 5484 5485 5486 5487
			}
		} while (noshow);

		/* build a tuple */
		tuple = BuildTupleFromCStrings(attinmeta, values);

		/* make the tuple into a datum */
5488
		result = HeapTupleGetDatum(tuple);
5489

B
Bruce Momjian 已提交
5490 5491 5492
		SRF_RETURN_NEXT(funcctx, result);
	}
	else
5493 5494
	{
		/* do when there is no more left */
B
Bruce Momjian 已提交
5495
		SRF_RETURN_DONE(funcctx);
5496
	}
5497 5498
}

5499
static char *
5500
_ShowOption(struct config_generic * record, bool use_units)
5501 5502 5503
{
	char		buffer[256];
	const char *val;
5504

5505 5506 5507 5508 5509
	switch (record->vartype)
	{
		case PGC_BOOL:
			{
				struct config_bool *conf = (struct config_bool *) record;
5510

5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525
				if (conf->show_hook)
					val = (*conf->show_hook) ();
				else
					val = *conf->variable ? "on" : "off";
			}
			break;

		case PGC_INT:
			{
				struct config_int *conf = (struct config_int *) record;

				if (conf->show_hook)
					val = (*conf->show_hook) ();
				else
				{
B
Bruce Momjian 已提交
5526 5527
					char		unit[4];
					int			result = *conf->variable;
5528 5529 5530

					if (use_units && result > 0 && (record->flags & GUC_UNIT_MEMORY))
					{
5531 5532 5533
						switch (record->flags & GUC_UNIT_MEMORY)
						{
							case GUC_UNIT_BLOCKS:
B
Bruce Momjian 已提交
5534
								result *= BLCKSZ / 1024;
5535 5536
								break;
							case GUC_UNIT_XBLOCKS:
B
Bruce Momjian 已提交
5537
								result *= XLOG_BLCKSZ / 1024;
5538 5539
								break;
						}
5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557

						if (result % KB_PER_GB == 0)
						{
							result /= KB_PER_GB;
							strcpy(unit, "GB");
						}
						else if (result % KB_PER_MB == 0)
						{
							result /= KB_PER_MB;
							strcpy(unit, "MB");
						}
						else
						{
							strcpy(unit, "kB");
						}
					}
					else if (use_units && result > 0 && (record->flags & GUC_UNIT_TIME))
					{
5558 5559 5560 5561 5562 5563 5564 5565 5566
						switch (record->flags & GUC_UNIT_TIME)
						{
							case GUC_UNIT_S:
								result *= MS_PER_S;
								break;
							case GUC_UNIT_MIN:
								result *= MS_PER_MIN;
								break;
						}
5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596

						if (result % MS_PER_D == 0)
						{
							result /= MS_PER_D;
							strcpy(unit, "d");
						}
						else if (result % MS_PER_H == 0)
						{
							result /= MS_PER_H;
							strcpy(unit, "h");
						}
						else if (result % MS_PER_MIN == 0)
						{
							result /= MS_PER_MIN;
							strcpy(unit, "min");
						}
						else if (result % MS_PER_S == 0)
						{
							result /= MS_PER_S;
							strcpy(unit, "s");
						}
						else
						{
							strcpy(unit, "ms");
						}
					}
					else
						strcpy(unit, "");

					snprintf(buffer, sizeof(buffer), "%d%s",
B
Bruce Momjian 已提交
5597
							 (int) result, unit);
5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620
					val = buffer;
				}
			}
			break;

		case PGC_REAL:
			{
				struct config_real *conf = (struct config_real *) record;

				if (conf->show_hook)
					val = (*conf->show_hook) ();
				else
				{
					snprintf(buffer, sizeof(buffer), "%g",
							 *conf->variable);
					val = buffer;
				}
			}
			break;

		case PGC_STRING:
			{
				struct config_string *conf = (struct config_string *) record;
5621

5622 5623 5624 5625 5626
				if (conf->show_hook)
					val = (*conf->show_hook) ();
				else if (*conf->variable && **conf->variable)
					val = *conf->variable;
				else
5627
					val = "";
5628 5629
			}
			break;
5630

5631 5632 5633 5634 5635
		default:
			/* just to keep compiler quiet */
			val = "???";
			break;
	}
5636

5637
	return pstrdup(val);
5638
}
5639 5640


5641
static bool
B
Bruce Momjian 已提交
5642
is_newvalue_equal(struct config_generic * record, const char *newvalue)
5643 5644 5645 5646
{
	switch (record->vartype)
	{
		case PGC_BOOL:
B
Bruce Momjian 已提交
5647 5648 5649
			{
				struct config_bool *conf = (struct config_bool *) record;
				bool		newval;
5650

B
Bruce Momjian 已提交
5651 5652
				return parse_bool(newvalue, &newval) && *conf->variable == newval;
			}
5653
		case PGC_INT:
B
Bruce Momjian 已提交
5654 5655 5656
			{
				struct config_int *conf = (struct config_int *) record;
				int			newval;
5657

B
Bruce Momjian 已提交
5658 5659
				return parse_int(newvalue, &newval, record->flags) && *conf->variable == newval;
			}
5660
		case PGC_REAL:
B
Bruce Momjian 已提交
5661 5662 5663
			{
				struct config_real *conf = (struct config_real *) record;
				double		newval;
5664

B
Bruce Momjian 已提交
5665 5666
				return parse_real(newvalue, &newval) && *conf->variable == newval;
			}
5667
		case PGC_STRING:
B
Bruce Momjian 已提交
5668 5669
			{
				struct config_string *conf = (struct config_string *) record;
5670

B
Bruce Momjian 已提交
5671 5672
				return strcmp(*conf->variable, newvalue) == 0;
			}
5673 5674 5675 5676 5677 5678
	}

	return false;
}


B
Bruce Momjian 已提交
5679
#ifdef EXEC_BACKEND
5680

B
Bruce Momjian 已提交
5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691
/*
 *	This routine dumps out all non-default GUC options into a binary
 *	file that is read by all exec'ed backends.  The format is:
 *
 *		variable name, string, null terminated
 *		variable value, string, null terminated
 *		variable source, integer
 */
void
write_nondefault_variables(GucContext context)
{
5692 5693 5694
	int			i;
	int			elevel;
	FILE	   *fp;
B
Bruce Momjian 已提交
5695 5696

	Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
5697 5698

	elevel = (context == PGC_SIGHUP) ? LOG : ERROR;
B
Bruce Momjian 已提交
5699 5700 5701 5702

	/*
	 * Open file
	 */
5703
	fp = AllocateFile(CONFIG_EXEC_PARAMS_NEW, "w");
5704 5705
	if (!fp)
	{
5706 5707
		ereport(elevel,
				(errcode_for_file_access(),
5708 5709
				 errmsg("could not write to file \"%s\": %m",
						CONFIG_EXEC_PARAMS_NEW)));
B
Bruce Momjian 已提交
5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766
		return;
	}

	for (i = 0; i < num_guc_variables; i++)
	{
		struct config_generic *gconf = guc_variables[i];

		if (gconf->source != PGC_S_DEFAULT)
		{
			fprintf(fp, "%s", gconf->name);
			fputc(0, fp);

			switch (gconf->vartype)
			{
				case PGC_BOOL:
					{
						struct config_bool *conf = (struct config_bool *) gconf;

						if (*conf->variable == 0)
							fprintf(fp, "false");
						else
							fprintf(fp, "true");
					}
					break;

				case PGC_INT:
					{
						struct config_int *conf = (struct config_int *) gconf;

						fprintf(fp, "%d", *conf->variable);
					}
					break;

				case PGC_REAL:
					{
						struct config_real *conf = (struct config_real *) gconf;

						/* Could lose precision here? */
						fprintf(fp, "%f", *conf->variable);
					}
					break;

				case PGC_STRING:
					{
						struct config_string *conf = (struct config_string *) gconf;

						fprintf(fp, "%s", *conf->variable);
					}
					break;
			}

			fputc(0, fp);

			fwrite(&gconf->source, sizeof(gconf->source), 1, fp);
		}
	}

5767 5768 5769 5770
	if (FreeFile(fp))
	{
		ereport(elevel,
				(errcode_for_file_access(),
5771 5772
				 errmsg("could not write to file \"%s\": %m",
						CONFIG_EXEC_PARAMS_NEW)));
5773 5774 5775
		return;
	}

5776
	/*
B
Bruce Momjian 已提交
5777 5778
	 * Put new file in place.  This could delay on Win32, but we don't hold
	 * any exclusive locks.
5779
	 */
5780
	rename(CONFIG_EXEC_PARAMS_NEW, CONFIG_EXEC_PARAMS);
B
Bruce Momjian 已提交
5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791
}


/*
 *	Read string, including null byte from file
 *
 *	Return NULL on EOF and nothing read
 */
static char *
read_string_with_null(FILE *fp)
{
5792 5793 5794 5795
	int			i = 0,
				ch,
				maxlen = 256;
	char	   *str = NULL;
B
Bruce Momjian 已提交
5796 5797 5798 5799 5800 5801 5802 5803

	do
	{
		if ((ch = fgetc(fp)) == EOF)
		{
			if (i == 0)
				return NULL;
			else
5804
				elog(FATAL, "invalid format of exec config params file");
B
Bruce Momjian 已提交
5805 5806
		}
		if (i == 0)
5807
			str = guc_malloc(FATAL, maxlen);
B
Bruce Momjian 已提交
5808
		else if (i == maxlen)
5809
			str = guc_realloc(FATAL, str, maxlen *= 2);
B
Bruce Momjian 已提交
5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823
		str[i++] = ch;
	} while (ch != 0);

	return str;
}


/*
 *	This routine loads a previous postmaster dump of its non-default
 *	settings.
 */
void
read_nondefault_variables(void)
{
5824 5825 5826 5827
	FILE	   *fp;
	char	   *varname,
			   *varvalue;
	int			varsource;
B
Bruce Momjian 已提交
5828 5829 5830 5831

	/*
	 * Open file
	 */
5832
	fp = AllocateFile(CONFIG_EXEC_PARAMS, "r");
5833 5834 5835 5836
	if (!fp)
	{
		/* File not found is fine */
		if (errno != ENOENT)
5837 5838
			ereport(FATAL,
					(errcode_for_file_access(),
5839 5840
					 errmsg("could not read from file \"%s\": %m",
							CONFIG_EXEC_PARAMS)));
B
Bruce Momjian 已提交
5841
		return;
5842
	}
B
Bruce Momjian 已提交
5843

5844
	for (;;)
B
Bruce Momjian 已提交
5845
	{
5846 5847
		struct config_generic *record;

B
Bruce Momjian 已提交
5848 5849 5850
		if ((varname = read_string_with_null(fp)) == NULL)
			break;

5851
		if ((record = find_option(varname, FATAL)) == NULL)
B
Bruce Momjian 已提交
5852
			elog(FATAL, "failed to locate variable %s in exec config params file", varname);
B
Bruce Momjian 已提交
5853
		if ((varvalue = read_string_with_null(fp)) == NULL)
5854
			elog(FATAL, "invalid format of exec config params file");
5855
		if (fread(&varsource, sizeof(varsource), 1, fp) == 0)
5856
			elog(FATAL, "invalid format of exec config params file");
B
Bruce Momjian 已提交
5857

5858
		(void) set_config_option(varname, varvalue, record->context,
5859
								 varsource, false, true);
B
Bruce Momjian 已提交
5860 5861 5862 5863 5864 5865
		free(varname);
		free(varvalue);
	}

	FreeFile(fp);
}
B
Bruce Momjian 已提交
5866
#endif   /* EXEC_BACKEND */
B
Bruce Momjian 已提交
5867 5868


5869 5870 5871 5872 5873 5874 5875 5876
/*
 * A little "long argument" simulation, although not quite GNU
 * compliant. Takes a string of the form "some-option=some value" and
 * returns name = "some_option" and value = "some value" in malloc'ed
 * storage. Note that '-' is converted to '_' in the option name. If
 * there is no '=' in the input string then value will be NULL.
 */
void
B
Bruce Momjian 已提交
5877
ParseLongOption(const char *string, char **name, char **value)
5878
{
B
Bruce Momjian 已提交
5879 5880
	size_t		equal_pos;
	char	   *cp;
5881 5882 5883 5884 5885 5886 5887 5888 5889

	AssertArg(string);
	AssertArg(name);
	AssertArg(value);

	equal_pos = strcspn(string, "=");

	if (string[equal_pos] == '=')
	{
5890
		*name = guc_malloc(FATAL, equal_pos + 1);
5891
		strlcpy(*name, string, equal_pos + 1);
5892

5893
		*value = guc_strdup(FATAL, &string[equal_pos + 1]);
5894
	}
B
Bruce Momjian 已提交
5895
	else
5896
	{
5897
		/* no equal sign in string */
5898
		*name = guc_strdup(FATAL, string);
5899 5900 5901
		*value = NULL;
	}

B
Bruce Momjian 已提交
5902
	for (cp = *name; *cp; cp++)
5903 5904 5905
		if (*cp == '-')
			*cp = '_';
}
5906 5907


5908
/*
5909
 * Handle options fetched from pg_database.datconfig or pg_authid.rolconfig.
5910
 * The array parameter must be an array of TEXT (it must not be NULL).
5911
 */
5912 5913 5914
void
ProcessGUCArray(ArrayType *array, GucSource source)
{
B
Bruce Momjian 已提交
5915
	int			i;
5916

5917
	Assert(array != NULL);
5918 5919 5920
	Assert(ARR_ELEMTYPE(array) == TEXTOID);
	Assert(ARR_NDIM(array) == 1);
	Assert(ARR_LBOUND(array)[0] == 1);
5921
	Assert(source == PGC_S_DATABASE || source == PGC_S_USER);
5922 5923 5924 5925 5926 5927 5928 5929 5930 5931

	for (i = 1; i <= ARR_DIMS(array)[0]; i++)
	{
		Datum		d;
		bool		isnull;
		char	   *s;
		char	   *name;
		char	   *value;

		d = array_ref(array, 1, &i,
B
Bruce Momjian 已提交
5932 5933 5934 5935
					  -1 /* varlenarray */ ,
					  -1 /* TEXT's typlen */ ,
					  false /* TEXT's typbyval */ ,
					  'i' /* TEXT's typalign */ ,
5936 5937 5938 5939 5940 5941
					  &isnull);

		if (isnull)
			continue;

		s = DatumGetCString(DirectFunctionCall1(textout, d));
5942

5943 5944 5945
		ParseLongOption(s, &name, &value);
		if (!value)
		{
5946 5947
			ereport(WARNING,
					(errcode(ERRCODE_SYNTAX_ERROR),
B
Bruce Momjian 已提交
5948
			  errmsg("could not parse setting for parameter \"%s\"", name)));
5949
			free(name);
B
Bruce Momjian 已提交
5950
			continue;
5951 5952
		}

5953
		/*
B
Bruce Momjian 已提交
5954 5955 5956
		 * We process all these options at SUSET level.  We assume that the
		 * right to insert an option into pg_database or pg_authid was checked
		 * when it was inserted.
5957
		 */
5958
		SetConfigOption(name, value, PGC_SUSET, source);
5959 5960 5961 5962

		free(name);
		if (value)
			free(value);
5963 5964 5965 5966
	}
}


5967 5968 5969 5970
/*
 * Add an entry to an option array.  The array parameter may be NULL
 * to indicate the current table entry is NULL.
 */
5971 5972 5973
ArrayType *
GUCArrayAdd(ArrayType *array, const char *name, const char *value)
{
5974
	const char *varname;
5975 5976 5977 5978 5979 5980 5981 5982 5983 5984
	Datum		datum;
	char	   *newval;
	ArrayType  *a;

	Assert(name);
	Assert(value);

	/* test if the option is valid */
	set_config_option(name, value,
					  superuser() ? PGC_SUSET : PGC_USERSET,
5985
					  PGC_S_TEST, false, false);
5986

5987 5988 5989 5990
	/* convert name to canonical spelling, so we can use plain strcmp */
	(void) GetConfigOptionByName(name, &varname);
	name = varname;

5991 5992 5993
	newval = palloc(strlen(name) + 1 + strlen(value) + 1);
	sprintf(newval, "%s=%s", name, value);
	datum = DirectFunctionCall1(textin, CStringGetDatum(newval));
B
Bruce Momjian 已提交
5994

5995 5996
	if (array)
	{
B
Bruce Momjian 已提交
5997 5998 5999
		int			index;
		bool		isnull;
		int			i;
6000

6001 6002 6003 6004
		Assert(ARR_ELEMTYPE(array) == TEXTOID);
		Assert(ARR_NDIM(array) == 1);
		Assert(ARR_LBOUND(array)[0] == 1);

B
Bruce Momjian 已提交
6005
		index = ARR_DIMS(array)[0] + 1; /* add after end */
6006 6007 6008 6009 6010 6011 6012

		for (i = 1; i <= ARR_DIMS(array)[0]; i++)
		{
			Datum		d;
			char	   *current;

			d = array_ref(array, 1, &i,
B
Bruce Momjian 已提交
6013 6014 6015 6016
						  -1 /* varlenarray */ ,
						  -1 /* TEXT's typlen */ ,
						  false /* TEXT's typbyval */ ,
						  'i' /* TEXT's typalign */ ,
6017
						  &isnull);
6018 6019
			if (isnull)
				continue;
6020
			current = DatumGetCString(DirectFunctionCall1(textout, d));
B
Bruce Momjian 已提交
6021
			if (strncmp(current, newval, strlen(name) + 1) == 0)
6022 6023 6024 6025 6026 6027
			{
				index = i;
				break;
			}
		}

6028 6029
		a = array_set(array, 1, &index,
					  datum,
6030 6031
					  false,
					  -1 /* varlena array */ ,
B
Bruce Momjian 已提交
6032 6033
					  -1 /* TEXT's typlen */ ,
					  false /* TEXT's typbyval */ ,
6034
					  'i' /* TEXT's typalign */ );
6035 6036
	}
	else
6037 6038 6039
		a = construct_array(&datum, 1,
							TEXTOID,
							-1, false, 'i');
6040 6041 6042 6043 6044

	return a;
}


6045 6046 6047 6048 6049
/*
 * Delete an entry from an option array.  The array parameter may be NULL
 * to indicate the current table entry is NULL.  Also, if the return value
 * is NULL then a null should be stored.
 */
6050 6051 6052
ArrayType *
GUCArrayDelete(ArrayType *array, const char *name)
{
6053
	const char *varname;
B
Bruce Momjian 已提交
6054 6055 6056
	ArrayType  *newarray;
	int			i;
	int			index;
6057 6058 6059 6060 6061 6062

	Assert(name);

	/* test if the option is valid */
	set_config_option(name, NULL,
					  superuser() ? PGC_SUSET : PGC_USERSET,
6063
					  PGC_S_TEST, false, false);
6064

6065 6066 6067 6068
	/* convert name to canonical spelling, so we can use plain strcmp */
	(void) GetConfigOptionByName(name, &varname);
	name = varname;

6069 6070 6071 6072 6073
	/* if array is currently null, then surely nothing to delete */
	if (!array)
		return NULL;

	newarray = NULL;
6074 6075 6076 6077 6078 6079 6080 6081 6082
	index = 1;

	for (i = 1; i <= ARR_DIMS(array)[0]; i++)
	{
		Datum		d;
		char	   *val;
		bool		isnull;

		d = array_ref(array, 1, &i,
B
Bruce Momjian 已提交
6083 6084 6085 6086
					  -1 /* varlenarray */ ,
					  -1 /* TEXT's typlen */ ,
					  false /* TEXT's typbyval */ ,
					  'i' /* TEXT's typalign */ ,
6087
					  &isnull);
6088 6089
		if (isnull)
			continue;
6090 6091
		val = DatumGetCString(DirectFunctionCall1(textout, d));

6092
		/* ignore entry if it's what we want to delete */
B
Bruce Momjian 已提交
6093
		if (strncmp(val, name, strlen(name)) == 0
6094 6095 6096
			&& val[strlen(name)] == '=')
			continue;

6097 6098 6099 6100 6101
		/* else add it to the output array */
		if (newarray)
		{
			newarray = array_set(newarray, 1, &index,
								 d,
6102
								 false,
6103 6104 6105
								 -1 /* varlenarray */ ,
								 -1 /* TEXT's typlen */ ,
								 false /* TEXT's typbyval */ ,
6106
								 'i' /* TEXT's typalign */ );
6107 6108 6109 6110 6111 6112
		}
		else
			newarray = construct_array(&d, 1,
									   TEXTOID,
									   -1, false, 'i');

6113 6114 6115 6116 6117
		index++;
	}

	return newarray;
}
6118

6119 6120 6121 6122 6123

/*
 * assign_hook subroutines
 */

6124 6125 6126
static const char *
assign_log_destination(const char *value, bool doit, GucSource source)
{
B
Bruce Momjian 已提交
6127 6128 6129 6130 6131
	char	   *rawstring;
	List	   *elemlist;
	ListCell   *l;
	int			newlogdest = 0;

6132 6133 6134 6135
	/* Need a modifiable copy of string */
	rawstring = pstrdup(value);

	/* Parse string into list of identifiers */
B
Bruce Momjian 已提交
6136
	if (!SplitIdentifierString(rawstring, ',', &elemlist))
6137 6138 6139
	{
		/* syntax error in list */
		pfree(rawstring);
6140
		list_free(elemlist);
6141 6142 6143
		if (source >= PGC_S_INTERACTIVE)
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
B
Bruce Momjian 已提交
6144
			errmsg("invalid list syntax for parameter \"log_destination\"")));
6145 6146 6147 6148 6149
		return NULL;
	}

	foreach(l, elemlist)
	{
B
Bruce Momjian 已提交
6150 6151 6152
		char	   *tok = (char *) lfirst(l);

		if (pg_strcasecmp(tok, "stderr") == 0)
6153 6154
			newlogdest |= LOG_DESTINATION_STDERR;
#ifdef HAVE_SYSLOG
B
Bruce Momjian 已提交
6155
		else if (pg_strcasecmp(tok, "syslog") == 0)
6156 6157 6158
			newlogdest |= LOG_DESTINATION_SYSLOG;
#endif
#ifdef WIN32
B
Bruce Momjian 已提交
6159
		else if (pg_strcasecmp(tok, "eventlog") == 0)
6160 6161
			newlogdest |= LOG_DESTINATION_EVENTLOG;
#endif
B
Bruce Momjian 已提交
6162 6163
		else
		{
6164 6165 6166
			if (source >= PGC_S_INTERACTIVE)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
B
Bruce Momjian 已提交
6167 6168
				  errmsg("unrecognized \"log_destination\" key word: \"%s\"",
						 tok)));
6169
			pfree(rawstring);
6170
			list_free(elemlist);
6171 6172 6173 6174
			return NULL;
		}
	}

6175 6176 6177
	if (doit)
		Log_destination = newlogdest;

6178
	pfree(rawstring);
6179
	list_free(elemlist);
6180 6181 6182 6183

	return value;
}

6184 6185 6186
#ifdef HAVE_SYSLOG

static const char *
6187
assign_syslog_facility(const char *facility, bool doit, GucSource source)
6188
{
B
Bruce Momjian 已提交
6189
	int			syslog_fac;
6190

6191
	if (pg_strcasecmp(facility, "LOCAL0") == 0)
6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217
		syslog_fac = LOG_LOCAL0;
	else if (pg_strcasecmp(facility, "LOCAL1") == 0)
		syslog_fac = LOG_LOCAL1;
	else if (pg_strcasecmp(facility, "LOCAL2") == 0)
		syslog_fac = LOG_LOCAL2;
	else if (pg_strcasecmp(facility, "LOCAL3") == 0)
		syslog_fac = LOG_LOCAL3;
	else if (pg_strcasecmp(facility, "LOCAL4") == 0)
		syslog_fac = LOG_LOCAL4;
	else if (pg_strcasecmp(facility, "LOCAL5") == 0)
		syslog_fac = LOG_LOCAL5;
	else if (pg_strcasecmp(facility, "LOCAL6") == 0)
		syslog_fac = LOG_LOCAL6;
	else if (pg_strcasecmp(facility, "LOCAL7") == 0)
		syslog_fac = LOG_LOCAL7;
	else
		return NULL;			/* reject */

	if (doit)
	{
		syslog_facility = syslog_fac;
		set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
							  syslog_facility);
	}

	return facility;
6218
}
6219 6220 6221 6222 6223 6224 6225 6226 6227

static const char *
assign_syslog_ident(const char *ident, bool doit, GucSource source)
{
	if (doit)
		set_syslog_parameters(ident, syslog_facility);

	return ident;
}
B
Bruce Momjian 已提交
6228
#endif   /* HAVE_SYSLOG */
6229 6230 6231


static const char *
6232
assign_defaultxactisolevel(const char *newval, bool doit, GucSource source)
6233
{
6234
	if (pg_strcasecmp(newval, "serializable") == 0)
6235 6236 6237 6238
	{
		if (doit)
			DefaultXactIsoLevel = XACT_SERIALIZABLE;
	}
6239
	else if (pg_strcasecmp(newval, "repeatable read") == 0)
6240 6241 6242 6243
	{
		if (doit)
			DefaultXactIsoLevel = XACT_REPEATABLE_READ;
	}
6244
	else if (pg_strcasecmp(newval, "read committed") == 0)
6245 6246 6247 6248
	{
		if (doit)
			DefaultXactIsoLevel = XACT_READ_COMMITTED;
	}
6249
	else if (pg_strcasecmp(newval, "read uncommitted") == 0)
6250 6251 6252 6253
	{
		if (doit)
			DefaultXactIsoLevel = XACT_READ_UNCOMMITTED;
	}
6254 6255 6256 6257 6258
	else
		return NULL;
	return newval;
}

6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285
static const char *
assign_session_replication_role(const char *newval, bool doit, GucSource source)
{
	if (HaveCachedPlans())
		elog(ERROR, "session_replication_role cannot be changed "
					"after prepared plans have been cached");

	if (pg_strcasecmp(newval, "origin") == 0)
	{
		if (doit)
			SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN;
	}
	else if (pg_strcasecmp(newval, "replica") == 0)
	{
		if (doit)
			SessionReplicationRole = SESSION_REPLICATION_ROLE_REPLICA;
	}
	else if (pg_strcasecmp(newval, "local") == 0)
	{
		if (doit)
			SessionReplicationRole = SESSION_REPLICATION_ROLE_LOCAL;
	}
	else
		return NULL;
	return newval;
}

6286
static const char *
6287
assign_log_min_messages(const char *newval,
6288
						bool doit, GucSource source)
6289
{
6290
	return (assign_msglvl(&log_min_messages, newval, doit, source));
6291 6292
}

6293
static const char *
6294
assign_client_min_messages(const char *newval, bool doit, GucSource source)
6295
{
6296
	return (assign_msglvl(&client_min_messages, newval, doit, source));
6297 6298
}

6299
static const char *
6300
assign_min_error_statement(const char *newval, bool doit, GucSource source)
6301
{
6302
	return (assign_msglvl(&log_min_error_statement, newval, doit, source));
6303 6304 6305
}

static const char *
6306
assign_msglvl(int *var, const char *newval, bool doit, GucSource source)
6307
{
6308
	if (pg_strcasecmp(newval, "debug") == 0)
B
Bruce Momjian 已提交
6309 6310
	{
		if (doit)
6311
			(*var) = DEBUG2;
B
Bruce Momjian 已提交
6312
	}
6313
	else if (pg_strcasecmp(newval, "debug5") == 0)
B
Bruce Momjian 已提交
6314 6315 6316 6317
	{
		if (doit)
			(*var) = DEBUG5;
	}
6318
	else if (pg_strcasecmp(newval, "debug4") == 0)
B
Bruce Momjian 已提交
6319 6320 6321 6322
	{
		if (doit)
			(*var) = DEBUG4;
	}
6323
	else if (pg_strcasecmp(newval, "debug3") == 0)
B
Bruce Momjian 已提交
6324 6325 6326 6327
	{
		if (doit)
			(*var) = DEBUG3;
	}
6328
	else if (pg_strcasecmp(newval, "debug2") == 0)
B
Bruce Momjian 已提交
6329 6330 6331 6332
	{
		if (doit)
			(*var) = DEBUG2;
	}
6333
	else if (pg_strcasecmp(newval, "debug1") == 0)
B
Bruce Momjian 已提交
6334 6335 6336 6337
	{
		if (doit)
			(*var) = DEBUG1;
	}
6338
	else if (pg_strcasecmp(newval, "log") == 0)
B
Bruce Momjian 已提交
6339 6340 6341 6342
	{
		if (doit)
			(*var) = LOG;
	}
B
Bruce Momjian 已提交
6343

6344
	/*
B
Bruce Momjian 已提交
6345 6346
	 * Client_min_messages always prints 'info', but we allow it as a value
	 * anyway.
6347
	 */
6348
	else if (pg_strcasecmp(newval, "info") == 0)
B
Bruce Momjian 已提交
6349 6350 6351 6352
	{
		if (doit)
			(*var) = INFO;
	}
6353
	else if (pg_strcasecmp(newval, "notice") == 0)
B
Bruce Momjian 已提交
6354 6355 6356 6357
	{
		if (doit)
			(*var) = NOTICE;
	}
6358
	else if (pg_strcasecmp(newval, "warning") == 0)
B
Bruce Momjian 已提交
6359 6360 6361 6362
	{
		if (doit)
			(*var) = WARNING;
	}
6363
	else if (pg_strcasecmp(newval, "error") == 0)
B
Bruce Momjian 已提交
6364 6365 6366 6367
	{
		if (doit)
			(*var) = ERROR;
	}
6368
	/* We allow FATAL/PANIC for client-side messages too. */
6369
	else if (pg_strcasecmp(newval, "fatal") == 0)
6370 6371 6372 6373
	{
		if (doit)
			(*var) = FATAL;
	}
6374
	else if (pg_strcasecmp(newval, "panic") == 0)
6375 6376 6377 6378
	{
		if (doit)
			(*var) = PANIC;
	}
6379 6380 6381 6382
	else
		return NULL;			/* fail */
	return newval;				/* OK */
}
6383

6384
static const char *
6385
assign_log_error_verbosity(const char *newval, bool doit, GucSource source)
6386
{
6387
	if (pg_strcasecmp(newval, "terse") == 0)
6388 6389 6390 6391
	{
		if (doit)
			Log_error_verbosity = PGERROR_TERSE;
	}
6392
	else if (pg_strcasecmp(newval, "default") == 0)
6393 6394 6395 6396
	{
		if (doit)
			Log_error_verbosity = PGERROR_DEFAULT;
	}
6397
	else if (pg_strcasecmp(newval, "verbose") == 0)
6398 6399 6400 6401 6402 6403 6404 6405 6406
	{
		if (doit)
			Log_error_verbosity = PGERROR_VERBOSE;
	}
	else
		return NULL;			/* fail */
	return newval;				/* OK */
}

6407 6408 6409
static const char *
assign_log_statement(const char *newval, bool doit, GucSource source)
{
6410
	if (pg_strcasecmp(newval, "none") == 0)
6411 6412
	{
		if (doit)
6413
			log_statement = LOGSTMT_NONE;
6414
	}
6415
	else if (pg_strcasecmp(newval, "ddl") == 0)
6416 6417
	{
		if (doit)
6418
			log_statement = LOGSTMT_DDL;
6419
	}
6420
	else if (pg_strcasecmp(newval, "mod") == 0)
6421 6422
	{
		if (doit)
6423
			log_statement = LOGSTMT_MOD;
6424
	}
6425
	else if (pg_strcasecmp(newval, "all") == 0)
6426 6427
	{
		if (doit)
6428
			log_statement = LOGSTMT_ALL;
6429 6430 6431 6432 6433 6434
	}
	else
		return NULL;			/* fail */
	return newval;				/* OK */
}

6435 6436 6437 6438
static const char *
show_num_temp_buffers(void)
{
	/*
B
Bruce Momjian 已提交
6439 6440
	 * We show the GUC var until local buffers have been initialized, and
	 * NLocBuffer afterwards.
6441 6442 6443 6444 6445 6446 6447
	 */
	static char nbuf[32];

	sprintf(nbuf, "%d", NLocBuffer ? NLocBuffer : num_temp_buffers);
	return nbuf;
}

6448
static bool
6449
assign_phony_autocommit(bool newval, bool doit, GucSource source)
6450 6451 6452
{
	if (!newval)
	{
6453
		if (doit && source >= PGC_S_INTERACTIVE)
6454 6455
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
6456
					 errmsg("SET AUTOCOMMIT TO OFF is no longer supported")));
6457 6458 6459 6460 6461
		return false;
	}
	return true;
}

6462 6463 6464
static const char *
assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
{
B
Bruce Momjian 已提交
6465 6466
	/*
	 * Check syntax. newval must be a comma separated list of identifiers.
6467 6468
	 * Whitespace is allowed but skipped.
	 */
B
Bruce Momjian 已提交
6469
	bool		hasSpaceAfterToken = false;
6470
	const char *cp = newval;
B
Bruce Momjian 已提交
6471 6472
	int			symLen = 0;
	int			c;
6473 6474
	StringInfoData buf;

6475 6476 6477 6478 6479 6480 6481
	/*
	 * Resetting custom_variable_classes by removing it from the
	 * configuration file will lead to newval = NULL
	 */
	if (newval == NULL)
		return guc_strdup(ERROR, "");

6482
	initStringInfo(&buf);
B
Bruce Momjian 已提交
6483
	while ((c = *cp++) != 0)
6484
	{
6485
		if (isspace((unsigned char) c))
6486
		{
B
Bruce Momjian 已提交
6487
			if (symLen > 0)
6488 6489 6490 6491
				hasSpaceAfterToken = true;
			continue;
		}

B
Bruce Momjian 已提交
6492
		if (c == ',')
6493 6494
		{
			hasSpaceAfterToken = false;
B
Bruce Momjian 已提交
6495
			if (symLen > 0)
6496 6497 6498 6499 6500 6501 6502
			{
				symLen = 0;
				appendStringInfoChar(&buf, ',');
			}
			continue;
		}

6503
		if (hasSpaceAfterToken || !isalnum((unsigned char) c))
6504
		{
B
Bruce Momjian 已提交
6505
			/*
B
Bruce Momjian 已提交
6506 6507
			 * Syntax error due to token following space after token or non
			 * alpha numeric character
6508
			 */
6509
			ereport(LOG,
6510
					(errcode(ERRCODE_SYNTAX_ERROR),
P
Peter Eisentraut 已提交
6511
					 errmsg("invalid syntax for \"custom_variable_classes\": \"%s\"", newval)));
6512
			pfree(buf.data);
6513 6514 6515
			return NULL;
		}
		symLen++;
B
Bruce Momjian 已提交
6516
		appendStringInfoChar(&buf, (char) c);
6517 6518
	}

6519
	/* Remove stray ',' at end */
B
Bruce Momjian 已提交
6520
	if (symLen == 0 && buf.len > 0)
6521
		buf.data[--buf.len] = '\0';
6522

B
Bruce Momjian 已提交
6523
	if (buf.len == 0)
6524
		newval = NULL;
B
Bruce Momjian 已提交
6525
	else if (doit)
6526
		newval = guc_strdup(ERROR, buf.data);
6527 6528 6529 6530

	pfree(buf.data);
	return newval;
}
6531

6532 6533 6534 6535 6536 6537 6538
static bool
assign_debug_assertions(bool newval, bool doit, GucSource source)
{
#ifndef USE_ASSERT_CHECKING
	if (newval)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
B
Bruce Momjian 已提交
6539
			   errmsg("assertion checking is not supported by this build")));
6540 6541 6542 6543
#endif
	return true;
}

6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555
static bool
assign_ssl(bool newval, bool doit, GucSource source)
{
#ifndef USE_SSL
	if (newval)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("SSL is not supported by this build")));
#endif
	return true;
}

6556 6557 6558
static bool
assign_stage_log_stats(bool newval, bool doit, GucSource source)
{
6559
	if (newval && log_statement_stats)
6560
	{
6561 6562 6563 6564
		if (source >= PGC_S_INTERACTIVE)
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("cannot enable parameter when \"log_statement_stats\" is true")));
6565 6566
		/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
		else if (source != PGC_S_OVERRIDE)
6567
			return false;
6568 6569 6570 6571 6572 6573 6574
	}
	return true;
}

static bool
assign_log_stats(bool newval, bool doit, GucSource source)
{
6575 6576
	if (newval &&
		(log_parser_stats || log_planner_stats || log_executor_stats))
6577
	{
6578 6579 6580 6581 6582 6583
		if (source >= PGC_S_INTERACTIVE)
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("cannot enable \"log_statement_stats\" when "
							"\"log_parser_stats\", \"log_planner_stats\", "
							"or \"log_executor_stats\" is true")));
6584 6585
		/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
		else if (source != PGC_S_OVERRIDE)
6586
			return false;
6587 6588 6589 6590
	}
	return true;
}

6591 6592 6593
static bool
assign_transaction_read_only(bool newval, bool doit, GucSource source)
{
6594 6595 6596 6597 6598 6599 6600
	/* Can't go to r/w mode inside a r/o transaction */
	if (newval == false && XactReadOnly && IsSubTransaction())
	{
		if (source >= PGC_S_INTERACTIVE)
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("cannot set transaction read-write mode inside a read-only transaction")));
6601 6602 6603
		/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
		else if (source != PGC_S_OVERRIDE)
			return false;
6604
	}
6605 6606
	return true;
}
6607

6608 6609 6610 6611 6612
static const char *
assign_canonical_path(const char *newval, bool doit, GucSource source)
{
	if (doit)
	{
B
Bruce Momjian 已提交
6613 6614
		char	   *canon_val = guc_strdup(ERROR, newval);

6615 6616 6617 6618 6619 6620 6621
		canonicalize_path(canon_val);
		return canon_val;
	}
	else
		return newval;
}

6622 6623 6624 6625
static const char *
assign_backslash_quote(const char *newval, bool doit, GucSource source)
{
	BackslashQuoteType bq;
B
Bruce Momjian 已提交
6626
	bool		bqbool;
6627 6628

	/*
B
Bruce Momjian 已提交
6629 6630
	 * Although only "on", "off", and "safe_encoding" are documented, we use
	 * parse_bool so we can accept all the likely variants of "on" and "off".
6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646
	 */
	if (pg_strcasecmp(newval, "safe_encoding") == 0)
		bq = BACKSLASH_QUOTE_SAFE_ENCODING;
	else if (parse_bool(newval, &bqbool))
	{
		bq = bqbool ? BACKSLASH_QUOTE_ON : BACKSLASH_QUOTE_OFF;
	}
	else
		return NULL;			/* reject */

	if (doit)
		backslash_quote = bq;

	return newval;
}

6647 6648 6649
static const char *
assign_timezone_abbreviations(const char *newval, bool doit, GucSource source)
{
6650 6651 6652 6653
	/*
	 * The powerup value shown above for timezone_abbreviations is "UNKNOWN".
	 * When we see this we just do nothing.  If this value isn't overridden
	 * from the config file then pg_timezone_abbrev_initialize() will
B
Bruce Momjian 已提交
6654 6655 6656 6657 6658 6659 6660 6661
	 * eventually replace it with "Default".  This hack has two purposes: to
	 * avoid wasting cycles loading values that might soon be overridden from
	 * the config file, and to avoid trying to read the timezone abbrev files
	 * during InitializeGUCOptions().  The latter doesn't work in an
	 * EXEC_BACKEND subprocess because my_exec_path hasn't been set yet and so
	 * we can't locate PGSHAREDIR.  (Essentially the same hack is used to
	 * delay initializing TimeZone ... if we have any more, we should try to
	 * clean up and centralize this mechanism ...)
6662 6663 6664 6665 6666 6667
	 */
	if (strcmp(newval, "UNKNOWN") == 0)
	{
		return newval;
	}

6668
	/* Loading abbrev file is expensive, so only do it when value changes */
6669 6670
	if (timezone_abbreviations_string == NULL ||
		strcmp(timezone_abbreviations_string, newval) != 0)
6671
	{
B
Bruce Momjian 已提交
6672
		int			elevel;
6673 6674 6675

		/*
		 * If reading config file, only the postmaster should bleat loudly
B
Bruce Momjian 已提交
6676
		 * about problems.	Otherwise, it's just this one process doing it,
6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688
		 * and we use WARNING message level.
		 */
		if (source == PGC_S_FILE)
			elevel = IsUnderPostmaster ? DEBUG2 : LOG;
		else
			elevel = WARNING;
		if (!load_tzoffsets(newval, doit, elevel))
			return NULL;
	}
	return newval;
}

6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704
/*
 * pg_timezone_abbrev_initialize --- set default value if not done already
 *
 * This is called after initial loading of postgresql.conf.  If no
 * timezone_abbreviations setting was found therein, select default.
 */
void
pg_timezone_abbrev_initialize(void)
{
	if (strcmp(timezone_abbreviations_string, "UNKNOWN") == 0)
	{
		SetConfigOption("timezone_abbreviations", "Default",
						PGC_POSTMASTER, PGC_S_ARGV);
	}
}

6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722
static const char *
assign_xmlbinary(const char *newval, bool doit, GucSource source)
{
	XmlBinaryType xb;

	if (pg_strcasecmp(newval, "base64") == 0)
		xb = XMLBINARY_BASE64;
	else if (pg_strcasecmp(newval, "hex") == 0)
		xb = XMLBINARY_HEX;
	else
		return NULL;			/* reject */

	if (doit)
		xmlbinary = xb;

	return newval;
}

6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740
static const char *
assign_xmloption(const char *newval, bool doit, GucSource source)
{
	XmlOptionType xo;

	if (pg_strcasecmp(newval, "document") == 0)
		xo = XMLOPTION_DOCUMENT;
	else if (pg_strcasecmp(newval, "content") == 0)
		xo = XMLOPTION_CONTENT;
	else
		return NULL;			/* reject */

	if (doit)
		xmloption = xo;

	return newval;
}

6741 6742 6743
static bool
assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
{
6744
	if (doit)
6745 6746 6747 6748 6749 6750 6751 6752
		return (pq_setkeepalivesidle(newval, MyProcPort) == STATUS_OK);

	return true;
}

static const char *
show_tcp_keepalives_idle(void)
{
6753 6754 6755
	static char nbuf[16];

	snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesidle(MyProcPort));
6756 6757 6758 6759 6760 6761
	return nbuf;
}

static bool
assign_tcp_keepalives_interval(int newval, bool doit, GucSource source)
{
6762
	if (doit)
6763 6764 6765 6766 6767 6768 6769 6770
		return (pq_setkeepalivesinterval(newval, MyProcPort) == STATUS_OK);

	return true;
}

static const char *
show_tcp_keepalives_interval(void)
{
6771 6772 6773
	static char nbuf[16];

	snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivesinterval(MyProcPort));
6774 6775 6776 6777 6778 6779
	return nbuf;
}

static bool
assign_tcp_keepalives_count(int newval, bool doit, GucSource source)
{
6780
	if (doit)
6781 6782 6783 6784 6785 6786 6787 6788
		return (pq_setkeepalivescount(newval, MyProcPort) == STATUS_OK);

	return true;
}

static const char *
show_tcp_keepalives_count(void)
{
6789 6790 6791
	static char nbuf[16];

	snprintf(nbuf, sizeof(nbuf), "%d", pq_getkeepalivescount(MyProcPort));
6792 6793
	return nbuf;
}
6794

6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821
static bool
assign_maxconnections(int newval, bool doit, GucSource source)
{
	if (doit)
	{
		if (newval + autovacuum_max_workers > INT_MAX / 4)
			return false;

		MaxBackends = newval + autovacuum_max_workers;
	}

	return true;
}

static bool
assign_autovacuum_max_workers(int newval, bool doit, GucSource source)
{
	if (doit)
	{
		if (newval + MaxConnections > INT_MAX / 4)
			return false;

		MaxBackends = newval + MaxConnections;
	}

	return true;
}
6822

6823
#include "guc-file.c"