guc.c 20.8 KB
Newer Older
1 2 3 4 5 6
/*--------------------------------------------------------------------
 * guc.c
 *
 * Support for grand unified configuration scheme, including SET
 * command, configuration file, and command line options.
 *
B
Bruce Momjian 已提交
7
 * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.34 2001/03/22 04:00:06 momjian Exp $
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * Copyright 2000 by PostgreSQL Global Development Group
 * Written by Peter Eisentraut <peter_e@gmx.net>.
 *--------------------------------------------------------------------
 */

#include "postgres.h"

#include <errno.h>
#include <float.h>
#include <limits.h>
#include <unistd.h>

#include "utils/guc.h"

23
#include "access/xlog.h"
24
#include "commands/async.h"
25
#include "libpq/auth.h"
26
#include "libpq/pqcomm.h"
27 28 29 30 31 32 33 34 35 36
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "optimizer/geqo.h"
#include "optimizer/paths.h"
#include "optimizer/planmain.h"
#include "parser/parse_expr.h"
#include "storage/proc.h"
#include "tcop/tcopprot.h"


37
/* XXX these should be in other modules' header files */
38
extern bool Log_connections;
B
Bruce Momjian 已提交
39 40 41
extern int	CheckPointTimeout;
extern int	CommitDelay;
extern int	CommitSiblings;
42 43
extern bool FixBTree;

44 45
#ifdef ENABLE_SYSLOG
extern char *Syslog_facility;
46
extern char *Syslog_ident;
47
static bool check_facility(const char *facility);
B
Bruce Momjian 已提交
48

49
#endif
V
Vadim B. Mikheev 已提交
50

51 52 53
/*
 * Debugging options
 */
54
#ifdef USE_ASSERT_CHECKING
B
Bruce Momjian 已提交
55 56
bool		assert_enabled = true;

57
#endif
B
Bruce Momjian 已提交
58 59 60 61 62
bool		Debug_print_query = false;
bool		Debug_print_plan = false;
bool		Debug_print_parse = false;
bool		Debug_print_rewritten = false;
bool		Debug_pretty_print = false;
63

B
Bruce Momjian 已提交
64 65 66 67 68 69
bool		Show_parser_stats = false;
bool		Show_planner_stats = false;
bool		Show_executor_stats = false;
bool		Show_query_stats = false;	/* this is sort of all three above
										 * together */
bool		Show_btree_build_stats = false;
70

B
Bruce Momjian 已提交
71
bool		SQL_inheritance = true;
72

73
#ifndef PG_KRB_SRVTAB
B
Bruce Momjian 已提交
74
#define PG_KRB_SRVTAB ""
75 76 77
#endif


78 79 80

enum config_type
{
81 82 83 84 85
	PGC_NONE = 0,
	PGC_BOOL,
	PGC_INT,
	PGC_REAL,
	PGC_STRING
86 87 88 89 90
};


struct config_generic
{
91
	const char *name;
B
Bruce Momjian 已提交
92 93
	GucContext	context;
	void	   *variable;
94 95 96 97 98
};


struct config_bool
{
99
	const char *name;
B
Bruce Momjian 已提交
100 101 102
	GucContext	context;
	bool	   *variable;
	bool		default_val;
103 104 105 106 107
};


struct config_int
{
108
	const char *name;
B
Bruce Momjian 已提交
109 110 111 112 113
	GucContext	context;
	int		   *variable;
	int			default_val;
	int			min;
	int			max;
114 115 116 117 118
};


struct config_real
{
119
	const char *name;
B
Bruce Momjian 已提交
120 121 122 123 124
	GucContext	context;
	double	   *variable;
	double		default_val;
	double		min;
	double		max;
125 126 127 128 129 130 131 132 133 134
};

/*
 * String value options are allocated with strdup, not with the
 * pstrdup/palloc mechanisms. That is because configuration settings
 * are already in place before the memory subsystem is up. It would
 * perhaps be an idea to change that sometime.
 */
struct config_string
{
135
	const char *name;
B
Bruce Momjian 已提交
136 137
	GucContext	context;
	char	  **variable;
138
	const char *default_val;
B
Bruce Momjian 已提交
139 140
	bool		(*parse_hook) (const char *proposed);
	void		(*assign_hook) (const char *newval);
141 142 143
};


144 145 146 147 148 149 150 151 152 153 154 155 156 157
/*
 * TO ADD AN OPTION:
 *
 * 1. Declare a global variable of type bool, int, double, or char*
 * and make use of it.
 *
 * 2. Decide at what times it's safe to set the option. See guc.h for
 * details.
 *
 * 3. Decide on a name, a default value, upper and lower bounds (if
 * applicable), etc.
 *
 * 4. Add a record below.
 *
158 159 160 161 162 163
 * 5. Add it to postgresql.conf.sample
 *
 * 6. Don't forget to document that option.
 *
 * WHEN MAKING MODIFICATIONS, remember to update postgresql.conf.sample
 *
164 165
 */

166 167 168 169

/******** option names follow ********/

static struct config_bool
B
Bruce Momjian 已提交
170
			ConfigureNamesBool[] =
171
{
B
Bruce Momjian 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
	{"enable_seqscan", PGC_USERSET, &enable_seqscan, true},
	{"enable_indexscan", PGC_USERSET, &enable_indexscan, true},
	{"enable_tidscan", PGC_USERSET, &enable_tidscan, true},
	{"enable_sort", PGC_USERSET, &enable_sort, true},
	{"enable_nestloop", PGC_USERSET, &enable_nestloop, true},
	{"enable_mergejoin", PGC_USERSET, &enable_mergejoin, true},
	{"enable_hashjoin", PGC_USERSET, &enable_hashjoin, true},

	{"ksqo", PGC_USERSET, &_use_keyset_query_optimizer, false},
	{"geqo", PGC_USERSET, &enable_geqo, true},

	{"tcpip_socket", PGC_POSTMASTER, &NetServer, false},
	{"ssl", PGC_POSTMASTER, &EnableSSL, false},
	{"fsync", PGC_SIGHUP, &enableFsync, true},
	{"silent_mode", PGC_POSTMASTER, &SilentMode, false},

	{"log_connections", PGC_SIGHUP, &Log_connections, false},
	{"log_timestamp", PGC_SIGHUP, &Log_timestamp, false},
	{"log_pid", PGC_SIGHUP, &Log_pid, false},
191

192
#ifdef USE_ASSERT_CHECKING
B
Bruce Momjian 已提交
193
	{"debug_assertions", PGC_USERSET, &assert_enabled, true},
194 195
#endif

B
Bruce Momjian 已提交
196 197 198 199 200
	{"debug_print_query", PGC_USERSET, &Debug_print_query, false},
	{"debug_print_parse", PGC_USERSET, &Debug_print_parse, false},
	{"debug_print_rewritten", PGC_USERSET, &Debug_print_rewritten, false},
	{"debug_print_plan", PGC_USERSET, &Debug_print_plan, false},
	{"debug_pretty_print", PGC_USERSET, &Debug_pretty_print, false},
201

B
Bruce Momjian 已提交
202 203 204 205
	{"show_parser_stats", PGC_USERSET, &Show_parser_stats, false},
	{"show_planner_stats", PGC_USERSET, &Show_planner_stats, false},
	{"show_executor_stats", PGC_USERSET, &Show_executor_stats, false},
	{"show_query_stats", PGC_USERSET, &Show_query_stats, false},
206
#ifdef BTREE_BUILD_STATS
B
Bruce Momjian 已提交
207
	{"show_btree_build_stats", PGC_SUSET, &Show_btree_build_stats, false},
208 209
#endif

B
Bruce Momjian 已提交
210
	{"trace_notify", PGC_USERSET, &Trace_notify, false},
211 212

#ifdef LOCK_DEBUG
B
Bruce Momjian 已提交
213 214 215 216
	{"trace_locks", PGC_SUSET, &Trace_locks, false},
	{"trace_userlocks", PGC_SUSET, &Trace_userlocks, false},
	{"trace_spinlocks", PGC_SUSET, &Trace_spinlocks, false},
	{"debug_deadlocks", PGC_SUSET, &Debug_deadlocks, false},
217 218
#endif

B
Bruce Momjian 已提交
219 220
	{"hostname_lookup", PGC_SIGHUP, &HostnameLookup, false},
	{"show_source_port", PGC_SIGHUP, &ShowPortNumber, false},
221

B
Bruce Momjian 已提交
222
	{"sql_inheritance", PGC_USERSET, &SQL_inheritance, true},
223

B
Bruce Momjian 已提交
224
	{"fixbtree", PGC_POSTMASTER, &FixBTree, true},
225

226 227 228 229 230
	{NULL, 0, NULL, false}
};


static struct config_int
B
Bruce Momjian 已提交
231
			ConfigureNamesInt[] =
232
{
B
Bruce Momjian 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245
	{"geqo_threshold", PGC_USERSET, &geqo_rels,
	DEFAULT_GEQO_RELS, 2, INT_MAX},
	{"geqo_pool_size", PGC_USERSET, &Geqo_pool_size,
	DEFAULT_GEQO_POOL_SIZE, 0, MAX_GEQO_POOL_SIZE},
	{"geqo_effort", PGC_USERSET, &Geqo_effort,
	1, 1, INT_MAX},
	{"geqo_generations", PGC_USERSET, &Geqo_generations,
	0, 0, INT_MAX},
	{"geqo_random_seed", PGC_USERSET, &Geqo_random_seed,
	-1, INT_MIN, INT_MAX},

	{"deadlock_timeout", PGC_POSTMASTER, &DeadlockTimeout,
	1000, 0, INT_MAX},
246 247

#ifdef ENABLE_SYSLOG
B
Bruce Momjian 已提交
248 249
	{"syslog", PGC_SIGHUP, &Use_syslog,
	0, 0, 2},
250 251 252
#endif

	/*
B
Bruce Momjian 已提交
253 254 255
	 * Note: There is some postprocessing done in PostmasterMain() to make
	 * sure the buffers are at least twice the number of backends, so the
	 * constraints here are partially unused.
256
	 */
B
Bruce Momjian 已提交
257 258 259 260 261 262
	{"max_connections", PGC_POSTMASTER, &MaxBackends,
	DEF_MAXBACKENDS, 1, MAXBACKENDS},
	{"shared_buffers", PGC_POSTMASTER, &NBuffers,
	DEF_NBUFFERS, 16, INT_MAX},
	{"port", PGC_POSTMASTER, &PostPortNumber,
	DEF_PGPORT, 1, 65535},
263

B
Bruce Momjian 已提交
264 265
	{"sort_mem", PGC_USERSET, &SortMem,
	512, 1, INT_MAX},
266

B
Bruce Momjian 已提交
267 268
	{"debug_level", PGC_USERSET, &DebugLvl,
	0, 0, 16},
269 270

#ifdef LOCK_DEBUG
B
Bruce Momjian 已提交
271 272 273 274
	{"trace_lock_oidmin", PGC_SUSET, &Trace_lock_oidmin,
	BootstrapObjectIdData, 1, INT_MAX},
	{"trace_lock_table", PGC_SUSET, &Trace_lock_table,
	0, 0, INT_MAX},
275
#endif
B
Bruce Momjian 已提交
276 277
	{"max_expr_depth", PGC_USERSET, &max_expr_depth,
	DEFAULT_MAX_EXPR_DEPTH, 10, INT_MAX},
278

B
Bruce Momjian 已提交
279 280
	{"unix_socket_permissions", PGC_POSTMASTER, &Unix_socket_permissions,
	0777, 0000, 0777},
281

B
Bruce Momjian 已提交
282 283
	{"checkpoint_segments", PGC_SIGHUP, &CheckPointSegments,
	3, 1, INT_MAX},
T
Tom Lane 已提交
284

B
Bruce Momjian 已提交
285 286
	{"checkpoint_timeout", PGC_SIGHUP, &CheckPointTimeout,
	300, 30, 3600},
V
Vadim B. Mikheev 已提交
287

B
Bruce Momjian 已提交
288 289
	{"wal_buffers", PGC_POSTMASTER, &XLOGbuffers,
	8, 4, INT_MAX},
V
Vadim B. Mikheev 已提交
290

B
Bruce Momjian 已提交
291 292
	{"wal_files", PGC_SIGHUP, &XLOGfiles,
	0, 0, 64},
293

B
Bruce Momjian 已提交
294 295
	{"wal_debug", PGC_SUSET, &XLOG_DEBUG,
	0, 0, 16},
V
Vadim B. Mikheev 已提交
296

B
Bruce Momjian 已提交
297 298
	{"commit_delay", PGC_USERSET, &CommitDelay,
	0, 0, 100000},
V
Vadim B. Mikheev 已提交
299

B
Bruce Momjian 已提交
300 301
	{"commit_siblings", PGC_USERSET, &CommitSiblings,
	5, 1, 1000},
302

303
	{NULL, 0, NULL, 0, 0, 0}
304 305 306 307
};


static struct config_real
B
Bruce Momjian 已提交
308
			ConfigureNamesReal[] =
309
{
B
Bruce Momjian 已提交
310 311 312 313 314 315 316 317 318 319 320 321 322
	{"effective_cache_size", PGC_USERSET, &effective_cache_size,
	DEFAULT_EFFECTIVE_CACHE_SIZE, 0, DBL_MAX},
	{"random_page_cost", PGC_USERSET, &random_page_cost,
	DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX},
	{"cpu_tuple_cost", PGC_USERSET, &cpu_tuple_cost,
	DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX},
	{"cpu_index_tuple_cost", PGC_USERSET, &cpu_index_tuple_cost,
	DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX},
	{"cpu_operator_cost", PGC_USERSET, &cpu_operator_cost,
	DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX},

	{"geqo_selection_bias", PGC_USERSET, &Geqo_selection_bias,
	DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS, MAX_GEQO_SELECTION_BIAS},
323 324

	{NULL, 0, NULL, 0.0, 0.0, 0.0}
325 326 327 328
};


static struct config_string
B
Bruce Momjian 已提交
329
			ConfigureNamesString[] =
330
{
B
Bruce Momjian 已提交
331 332
	{"krb_server_keyfile", PGC_POSTMASTER, &pg_krb_server_keyfile,
	PG_KRB_SRVTAB, NULL, NULL},
333

334
#ifdef ENABLE_SYSLOG
B
Bruce Momjian 已提交
335
	{"syslog_facility", PGC_POSTMASTER, &Syslog_facility,
336
	"LOCAL0", check_facility, NULL},
B
Bruce Momjian 已提交
337
	{"syslog_ident", PGC_POSTMASTER, &Syslog_ident,
338
	"postgres", NULL, NULL},
339
#endif
340

B
Bruce Momjian 已提交
341 342
	{"unix_socket_group", PGC_POSTMASTER, &Unix_socket_group,
	"", NULL, NULL},
343

B
Bruce Momjian 已提交
344 345
	{"unix_socket_directory", PGC_POSTMASTER, &UnixSocketDir,
	"", NULL, NULL},
346

B
Bruce Momjian 已提交
347 348
	{"virtual_host", PGC_POSTMASTER, &VirtualHost,
	"", NULL, NULL},
349

B
Bruce Momjian 已提交
350 351 352
	{"wal_sync_method", PGC_SIGHUP, &XLOG_sync_method,
		XLOG_sync_method_default,
	check_xlog_sync_method, assign_xlog_sync_method},
353 354

	{NULL, 0, NULL, NULL, NULL, NULL}
355 356 357 358 359 360 361 362 363 364 365 366
};

/******** end of options list ********/



/*
 * Look up option NAME. If it exists, return it's data type, else
 * PGC_NONE (zero). If record is not NULL, store the description of
 * the option there.
 */
static enum config_type
B
Bruce Momjian 已提交
367
find_option(const char *name, struct config_generic ** record)
368
{
B
Bruce Momjian 已提交
369
	int			i;
370 371 372 373

	Assert(name);

	for (i = 0; ConfigureNamesBool[i].name; i++)
B
Bruce Momjian 已提交
374
		if (strcasecmp(ConfigureNamesBool[i].name, name) == 0)
375 376
		{
			if (record)
B
Bruce Momjian 已提交
377
				*record = (struct config_generic *) & ConfigureNamesBool[i];
378 379 380 381
			return PGC_BOOL;
		}

	for (i = 0; ConfigureNamesInt[i].name; i++)
B
Bruce Momjian 已提交
382
		if (strcasecmp(ConfigureNamesInt[i].name, name) == 0)
383 384
		{
			if (record)
B
Bruce Momjian 已提交
385
				*record = (struct config_generic *) & ConfigureNamesInt[i];
386 387 388 389
			return PGC_INT;
		}

	for (i = 0; ConfigureNamesReal[i].name; i++)
B
Bruce Momjian 已提交
390
		if (strcasecmp(ConfigureNamesReal[i].name, name) == 0)
391 392
		{
			if (record)
B
Bruce Momjian 已提交
393
				*record = (struct config_generic *) & ConfigureNamesReal[i];
394 395
			return PGC_REAL;
		}
396 397

	for (i = 0; ConfigureNamesString[i].name; i++)
B
Bruce Momjian 已提交
398
		if (strcasecmp(ConfigureNamesString[i].name, name) == 0)
399 400
		{
			if (record)
B
Bruce Momjian 已提交
401
				*record = (struct config_generic *) & ConfigureNamesString[i];
402 403 404 405
			return PGC_STRING;
		}

	return PGC_NONE;
406 407 408 409 410 411 412 413 414 415 416
}



/*
 * Reset all options to their specified default values. Should only be
 * called at program startup.
 */
void
ResetAllOptions(void)
{
B
Bruce Momjian 已提交
417
	int			i;
418

419 420
	for (i = 0; ConfigureNamesBool[i].name; i++)
		*(ConfigureNamesBool[i].variable) = ConfigureNamesBool[i].default_val;
421

422 423
	for (i = 0; ConfigureNamesInt[i].name; i++)
		*(ConfigureNamesInt[i].variable) = ConfigureNamesInt[i].default_val;
424

425 426
	for (i = 0; ConfigureNamesReal[i].name; i++)
		*(ConfigureNamesReal[i].variable) = ConfigureNamesReal[i].default_val;
427

428
	for (i = 0; ConfigureNamesString[i].name; i++)
429
	{
B
Bruce Momjian 已提交
430
		char	   *str = NULL;
431 432 433 434 435 436 437

		if (ConfigureNamesString[i].default_val)
		{
			str = strdup(ConfigureNamesString[i].default_val);
			if (str == NULL)
				elog(ERROR, "out of memory");
		}
438
		*(ConfigureNamesString[i].variable) = str;
439
	}
440 441

	if (getenv("PGPORT"))
B
Bruce Momjian 已提交
442
		PostPortNumber = atoi(getenv("PGPORT"));
443 444 445 446 447 448 449 450 451 452 453
}



/*
 * 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
B
Bruce Momjian 已提交
454
parse_bool(const char *value, bool *result)
455
{
B
Bruce Momjian 已提交
456
	size_t		len = strlen(value);
457

B
Bruce Momjian 已提交
458
	if (strncasecmp(value, "true", len) == 0)
459 460 461 462
	{
		if (result)
			*result = true;
	}
B
Bruce Momjian 已提交
463
	else if (strncasecmp(value, "false", len) == 0)
464 465 466 467 468
	{
		if (result)
			*result = false;
	}

B
Bruce Momjian 已提交
469
	else if (strncasecmp(value, "yes", len) == 0)
470 471 472 473
	{
		if (result)
			*result = true;
	}
B
Bruce Momjian 已提交
474
	else if (strncasecmp(value, "no", len) == 0)
475 476 477 478 479
	{
		if (result)
			*result = false;
	}

B
Bruce Momjian 已提交
480
	else if (strcasecmp(value, "on") == 0)
481 482 483 484
	{
		if (result)
			*result = true;
	}
B
Bruce Momjian 已提交
485
	else if (strcasecmp(value, "off") == 0)
486 487 488 489 490
	{
		if (result)
			*result = false;
	}

B
Bruce Momjian 已提交
491
	else if (strcasecmp(value, "1") == 0)
492 493 494 495
	{
		if (result)
			*result = true;
	}
B
Bruce Momjian 已提交
496
	else if (strcasecmp(value, "0") == 0)
497 498 499 500 501 502 503 504
	{
		if (result)
			*result = false;
	}

	else
		return false;
	return true;
505 506 507 508 509 510 511 512 513 514 515
}



/*
 * 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
B
Bruce Momjian 已提交
516
parse_int(const char *value, int *result)
517
{
B
Bruce Momjian 已提交
518 519
	long		val;
	char	   *endptr;
520 521 522 523 524 525

	errno = 0;
	val = strtol(value, &endptr, 0);
	if (endptr == value || *endptr != '\0' || errno == ERANGE)
		return false;
	if (result)
B
Bruce Momjian 已提交
526
		*result = (int) val;
527
	return true;
528 529 530 531 532 533
}



/*
 * Try to parse value as a floating point constant in the usual
B
Bruce Momjian 已提交
534
 * format.	If the value parsed okay return true, else false.  If
535 536 537
 * result is not NULL, return the semantic value there.
 */
static bool
B
Bruce Momjian 已提交
538
parse_real(const char *value, double *result)
539
{
B
Bruce Momjian 已提交
540 541
	double		val;
	char	   *endptr;
542 543 544 545 546 547 548 549

	errno = 0;
	val = strtod(value, &endptr);
	if (endptr == value || *endptr != '\0' || errno == ERANGE)
		return false;
	if (result)
		*result = val;
	return true;
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
}



/*
 * 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. Parameter context should 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 DoIt 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
 * elog(ERROR) is thrown *unless* this is called as part of the
 * configuration file re-read in the SIGHUP handler, in which case we
 * simply write the error message via elog(DEBUG) and return false. In
 * all other cases the function returns true. This is working around
 * the deficiencies in the elog mechanism, so don't blame me.
 *
 * See also SetConfigOption for an external interface.
 */
bool
B
Bruce Momjian 已提交
575
set_config_option(const char *name, const char *value, GucContext
576 577
				  context, bool DoIt)
{
B
Bruce Momjian 已提交
578
	struct config_generic *record;
579
	enum config_type type;
B
Bruce Momjian 已提交
580
	int			elevel;
581 582 583

	elevel = (context == PGC_SIGHUP) ? DEBUG : ERROR;

584 585
	type = find_option(name, &record);
	if (type == PGC_NONE)
586
	{
587
		elog(elevel, "'%s' is not a valid option name", name);
588 589 590
		return false;
	}

591 592
	/*
	 * Check if the option can be set at this time. See guc.h for the
B
Bruce Momjian 已提交
593 594
	 * 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.
595
	 */
596
	if (record->context == PGC_POSTMASTER && context != PGC_POSTMASTER)
597
	{
598
		if (context != PGC_SIGHUP)
599
			elog(ERROR, "'%s' cannot be changed after server start", name);
600 601
		else
			return true;
602
	}
603 604 605
	else if (record->context == PGC_SIGHUP && context != PGC_SIGHUP &&
			 context != PGC_POSTMASTER)
	{
606
		elog(ERROR, "'%s' cannot be changed now", name);
B
Bruce Momjian 已提交
607 608 609 610 611 612 613

		/*
		 * 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.
		 */
614 615 616 617 618
	}
	else if (record->context == PGC_BACKEND && context != PGC_BACKEND
			 && context != PGC_POSTMASTER)
	{
		if (context != PGC_SIGHUP)
619
			elog(ERROR, "'%s' cannot be set after connection start", name);
620 621 622 623 624 625 626
		else
			return true;
	}
	else if (record->context == PGC_SUSET && (context == PGC_USERSET
											  || context == PGC_BACKEND))
		elog(ERROR, "permission denied");

627

628 629 630
	/*
	 * Evaluate value and set variable
	 */
B
Bruce Momjian 已提交
631
	switch (type)
632 633 634
	{
		case PGC_BOOL:
			{
B
Bruce Momjian 已提交
635 636 637
				struct config_bool *conf = (struct config_bool *) record;

				if (value)
638
				{
B
Bruce Momjian 已提交
639 640 641 642 643 644 645 646 647
					bool		boolval;

					if (!parse_bool(value, &boolval))
					{
						elog(elevel, "option '%s' requires a boolean value", name);
						return false;
					}
					if (DoIt)
						*conf->variable = boolval;
648
				}
B
Bruce Momjian 已提交
649 650 651
				else if (DoIt)
					*conf->variable = conf->default_val;
				break;
652
			}
653 654

		case PGC_INT:
655
			{
B
Bruce Momjian 已提交
656
				struct config_int *conf = (struct config_int *) record;
657

B
Bruce Momjian 已提交
658
				if (value)
659
				{
B
Bruce Momjian 已提交
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
					int			intval;

					if (!parse_int(value, &intval))
					{
						elog(elevel, "option '%s' expects an integer value", name);
						return false;
					}
					if (intval < conf->min || intval > conf->max)
					{
						elog(elevel, "option '%s' value %d is outside"
							 " of permissible range [%d .. %d]",
							 name, intval, conf->min, conf->max);
						return false;
					}
					if (DoIt)
						*conf->variable = intval;
676
				}
B
Bruce Momjian 已提交
677 678 679
				else if (DoIt)
					*conf->variable = conf->default_val;
				break;
680
			}
681 682

		case PGC_REAL:
683
			{
B
Bruce Momjian 已提交
684
				struct config_real *conf = (struct config_real *) record;
685

B
Bruce Momjian 已提交
686
				if (value)
687
				{
B
Bruce Momjian 已提交
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
					double		dval;

					if (!parse_real(value, &dval))
					{
						elog(elevel, "option '%s' expects a real number", name);
						return false;
					}
					if (dval < conf->min || dval > conf->max)
					{
						elog(elevel, "option '%s' value %g is outside"
							 " of permissible range [%g .. %g]",
							 name, dval, conf->min, conf->max);
						return false;
					}
					if (DoIt)
						*conf->variable = dval;
704
				}
B
Bruce Momjian 已提交
705 706 707
				else if (DoIt)
					*conf->variable = conf->default_val;
				break;
708
			}
709 710 711

		case PGC_STRING:
			{
B
Bruce Momjian 已提交
712 713 714
				struct config_string *conf = (struct config_string *) record;

				if (value)
715
				{
B
Bruce Momjian 已提交
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
					if (conf->parse_hook && !(conf->parse_hook) (value))
					{
						elog(elevel, "invalid value for option '%s': '%s'", name, value);
						return false;
					}
					if (DoIt)
					{
						char	   *str;

						str = strdup(value);
						if (str == NULL)
						{
							elog(elevel, "out of memory");
							return false;
						}
						if (conf->assign_hook)
							(conf->assign_hook) (str);
						if (*conf->variable)
							free(*conf->variable);
						*conf->variable = str;
					}
737
				}
B
Bruce Momjian 已提交
738
				else if (DoIt)
739
				{
B
Bruce Momjian 已提交
740
					char	   *str;
741

B
Bruce Momjian 已提交
742
					str = strdup(conf->default_val);
743 744 745 746 747
					if (str == NULL)
					{
						elog(elevel, "out of memory");
						return false;
					}
748
					if (conf->assign_hook)
B
Bruce Momjian 已提交
749
						(conf->assign_hook) (str);
750 751
					if (*conf->variable)
						free(*conf->variable);
752
					*conf->variable = str;
753
				}
B
Bruce Momjian 已提交
754
				break;
755 756
			}

B
Bruce Momjian 已提交
757
		default:;
758
	}
759 760 761 762 763 764 765 766 767 768
	return true;
}



/*
 * Set a config option to the given value. See also set_config_option,
 * this is just the wrapper to be called from the outside.
 */
void
B
Bruce Momjian 已提交
769
SetConfigOption(const char *name, const char *value, GucContext
770 771
				context)
{
B
Bruce Momjian 已提交
772
	(void) set_config_option(name, value, context, true);
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
}



/*
 * This is more or less the SHOW command. It returns a string with the
 * value of the option `name'. If the option doesn't exist, throw an
 * elog and don't return. issuper should be true if and only if the
 * current user is a superuser. Normal users don't have read
 * permission on all options.
 *
 * 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 已提交
788
GetConfigOption(const char *name)
789
{
B
Bruce Momjian 已提交
790
	struct config_generic *record;
791 792 793
	static char buffer[256];
	enum config_type opttype;

794
	opttype = find_option(name, &record);
795
	if (opttype == PGC_NONE)
796
		elog(ERROR, "Option '%s' is not recognized", name);
797

B
Bruce Momjian 已提交
798
	switch (opttype)
799 800
	{
		case PGC_BOOL:
B
Bruce Momjian 已提交
801
			return *((struct config_bool *) record)->variable ? "on" : "off";
802

803
		case PGC_INT:
B
Bruce Momjian 已提交
804
			snprintf(buffer, 256, "%d", *((struct config_int *) record)->variable);
805 806
			return buffer;

807
		case PGC_REAL:
B
Bruce Momjian 已提交
808
			snprintf(buffer, 256, "%g", *((struct config_real *) record)->variable);
809 810 811
			return buffer;

		case PGC_STRING:
B
Bruce Momjian 已提交
812
			return *((struct config_string *) record)->variable;
813

814
		default:
815
			;
816 817 818
	}
	return NULL;
}
819 820 821 822 823 824 825 826 827 828 829



/*
 * 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 已提交
830
ParseLongOption(const char *string, char **name, char **value)
831
{
B
Bruce Momjian 已提交
832 833
	size_t		equal_pos;
	char	   *cp;
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852

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

	equal_pos = strcspn(string, "=");

	if (string[equal_pos] == '=')
	{
		*name = malloc(equal_pos + 1);
		if (!*name)
			elog(FATAL, "out of memory");
		strncpy(*name, string, equal_pos);
		(*name)[equal_pos] = '\0';

		*value = strdup(&string[equal_pos + 1]);
		if (!*value)
			elog(FATAL, "out of memory");
	}
B
Bruce Momjian 已提交
853 854
	else
/* no equal sign in string */
855 856 857 858 859 860 861
	{
		*name = strdup(string);
		if (!*name)
			elog(FATAL, "out of memory");
		*value = NULL;
	}

B
Bruce Momjian 已提交
862
	for (cp = *name; *cp; cp++)
863 864 865
		if (*cp == '-')
			*cp = '_';
}
866 867 868



869
#ifdef ENABLE_SYSLOG
870
static bool
871 872
check_facility(const char *facility)
{
B
Bruce Momjian 已提交
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
	if (strcasecmp(facility, "LOCAL0") == 0)
		return true;
	if (strcasecmp(facility, "LOCAL1") == 0)
		return true;
	if (strcasecmp(facility, "LOCAL2") == 0)
		return true;
	if (strcasecmp(facility, "LOCAL3") == 0)
		return true;
	if (strcasecmp(facility, "LOCAL4") == 0)
		return true;
	if (strcasecmp(facility, "LOCAL5") == 0)
		return true;
	if (strcasecmp(facility, "LOCAL6") == 0)
		return true;
	if (strcasecmp(facility, "LOCAL7") == 0)
		return true;
889 890
	return false;
}
B
Bruce Momjian 已提交
891

892
#endif