guc.c 26.1 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.
 *
7
 * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.43 2001/06/27 23:31:39 tgl 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 "fmgr.h"
26
#include "libpq/auth.h"
27
#include "libpq/pqcomm.h"
28 29 30 31 32 33
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "optimizer/geqo.h"
#include "optimizer/paths.h"
#include "optimizer/planmain.h"
#include "parser/parse_expr.h"
34 35
#include "storage/freespace.h"
#include "storage/lock.h"
36 37
#include "storage/proc.h"
#include "tcop/tcopprot.h"
38
#include "utils/datetime.h"
39 40


41
/* XXX these should be in other modules' header files */
42
extern bool Log_connections;
B
Bruce Momjian 已提交
43 44 45
extern int	CheckPointTimeout;
extern int	CommitDelay;
extern int	CommitSiblings;
46 47
extern bool FixBTree;

48 49
#ifdef ENABLE_SYSLOG
extern char *Syslog_facility;
50
extern char *Syslog_ident;
51
static bool check_facility(const char *facility);
52
#endif
V
Vadim B. Mikheev 已提交
53

54 55 56
/*
 * Debugging options
 */
57
#ifdef USE_ASSERT_CHECKING
B
Bruce Momjian 已提交
58
bool		assert_enabled = true;
59
#endif
B
Bruce Momjian 已提交
60 61 62 63 64
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;
65

B
Bruce Momjian 已提交
66 67 68 69 70 71
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;
72

B
Bruce Momjian 已提交
73
bool		SQL_inheritance = true;
74

75 76
bool		Australian_timezones = false;

77
#ifndef PG_KRB_SRVTAB
B
Bruce Momjian 已提交
78
#define PG_KRB_SRVTAB ""
79 80 81
#endif


82 83 84
/*
 * Declarations for GUC tables
 */
85 86
enum config_type
{
87 88 89 90 91
	PGC_NONE = 0,
	PGC_BOOL,
	PGC_INT,
	PGC_REAL,
	PGC_STRING
92 93 94 95 96
};


struct config_generic
{
97
	const char *name;
B
Bruce Momjian 已提交
98 99
	GucContext	context;
	void	   *variable;
100 101 102 103 104
};


struct config_bool
{
105
	const char *name;
B
Bruce Momjian 已提交
106 107 108
	GucContext	context;
	bool	   *variable;
	bool		default_val;
109 110
	/* No need for parse_hook ... presumably both values are legal */
	void		(*assign_hook) (bool newval);
111 112 113 114 115
};


struct config_int
{
116
	const char *name;
B
Bruce Momjian 已提交
117 118 119 120 121
	GucContext	context;
	int		   *variable;
	int			default_val;
	int			min;
	int			max;
122 123
	bool		(*parse_hook) (int proposed);
	void		(*assign_hook) (int newval);
124 125 126 127 128
};


struct config_real
{
129
	const char *name;
B
Bruce Momjian 已提交
130 131 132 133 134
	GucContext	context;
	double	   *variable;
	double		default_val;
	double		min;
	double		max;
135 136
	bool		(*parse_hook) (double proposed);
	void		(*assign_hook) (double newval);
137 138 139 140 141 142 143 144 145 146
};

/*
 * 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
{
147
	const char *name;
B
Bruce Momjian 已提交
148 149
	GucContext	context;
	char	  **variable;
150
	const char *boot_default_val;
B
Bruce Momjian 已提交
151 152
	bool		(*parse_hook) (const char *proposed);
	void		(*assign_hook) (const char *newval);
153
	char		*default_val;
154 155 156
};


157 158 159 160 161 162 163 164 165 166 167 168 169 170
/*
 * 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.
 *
171 172 173 174 175 176
 * 5. Add it to postgresql.conf.sample
 *
 * 6. Don't forget to document that option.
 *
 * WHEN MAKING MODIFICATIONS, remember to update postgresql.conf.sample
 *
177 178
 */

179 180 181 182

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

static struct config_bool
B
Bruce Momjian 已提交
183
			ConfigureNamesBool[] =
184
{
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
	{"enable_seqscan", PGC_USERSET, &enable_seqscan, true, NULL},
	{"enable_indexscan", PGC_USERSET, &enable_indexscan, true, NULL},
	{"enable_tidscan", PGC_USERSET, &enable_tidscan, true, NULL},
	{"enable_sort", PGC_USERSET, &enable_sort, true, NULL},
	{"enable_nestloop", PGC_USERSET, &enable_nestloop, true, NULL},
	{"enable_mergejoin", PGC_USERSET, &enable_mergejoin, true, NULL},
	{"enable_hashjoin", PGC_USERSET, &enable_hashjoin, true, NULL},

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

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

201
	{"log_connections", PGC_BACKEND, &Log_connections, false, NULL},
202 203
	{"log_timestamp", PGC_SIGHUP, &Log_timestamp, false, NULL},
	{"log_pid", PGC_SIGHUP, &Log_pid, false, NULL},
204

205
#ifdef USE_ASSERT_CHECKING
206
	{"debug_assertions", PGC_USERSET, &assert_enabled, true, NULL},
207 208
#endif

209 210 211 212 213
	{"debug_print_query", PGC_USERSET, &Debug_print_query, false, NULL},
	{"debug_print_parse", PGC_USERSET, &Debug_print_parse, false, NULL},
	{"debug_print_rewritten", PGC_USERSET, &Debug_print_rewritten, false, NULL},
	{"debug_print_plan", PGC_USERSET, &Debug_print_plan, false, NULL},
	{"debug_pretty_print", PGC_USERSET, &Debug_pretty_print, false, NULL},
214

215 216 217 218
	{"show_parser_stats", PGC_USERSET, &Show_parser_stats, false, NULL},
	{"show_planner_stats", PGC_USERSET, &Show_planner_stats, false, NULL},
	{"show_executor_stats", PGC_USERSET, &Show_executor_stats, false, NULL},
	{"show_query_stats", PGC_USERSET, &Show_query_stats, false, NULL},
219
#ifdef BTREE_BUILD_STATS
220
	{"show_btree_build_stats", PGC_SUSET, &Show_btree_build_stats, false, NULL},
221 222
#endif

223
	{"trace_notify", PGC_USERSET, &Trace_notify, false, NULL},
224 225

#ifdef LOCK_DEBUG
226 227 228 229
	{"trace_locks", PGC_SUSET, &Trace_locks, false, NULL},
	{"trace_userlocks", PGC_SUSET, &Trace_userlocks, false, NULL},
	{"trace_spinlocks", PGC_SUSET, &Trace_spinlocks, false, NULL},
	{"debug_deadlocks", PGC_SUSET, &Debug_deadlocks, false, NULL},
230 231
#endif

232 233
	{"hostname_lookup", PGC_SIGHUP, &HostnameLookup, false, NULL},
	{"show_source_port", PGC_SIGHUP, &ShowPortNumber, false, NULL},
234

235
	{"sql_inheritance", PGC_USERSET, &SQL_inheritance, true, NULL},
236

237 238 239
	{"australian_timezones", PGC_USERSET, &Australian_timezones,
	false, ClearDateCache},

240
	{"fixbtree", PGC_POSTMASTER, &FixBTree, true, NULL},
241

242
	{NULL, 0, NULL, false, NULL}
243 244 245 246
};


static struct config_int
B
Bruce Momjian 已提交
247
			ConfigureNamesInt[] =
248
{
B
Bruce Momjian 已提交
249
	{"geqo_threshold", PGC_USERSET, &geqo_rels,
250
	DEFAULT_GEQO_RELS, 2, INT_MAX, NULL, NULL},
B
Bruce Momjian 已提交
251
	{"geqo_pool_size", PGC_USERSET, &Geqo_pool_size,
252
	DEFAULT_GEQO_POOL_SIZE, 0, MAX_GEQO_POOL_SIZE, NULL, NULL},
B
Bruce Momjian 已提交
253
	{"geqo_effort", PGC_USERSET, &Geqo_effort,
254
	1, 1, INT_MAX, NULL, NULL},
B
Bruce Momjian 已提交
255
	{"geqo_generations", PGC_USERSET, &Geqo_generations,
256
	0, 0, INT_MAX, NULL, NULL},
B
Bruce Momjian 已提交
257
	{"geqo_random_seed", PGC_USERSET, &Geqo_random_seed,
258
	-1, INT_MIN, INT_MAX, NULL, NULL},
B
Bruce Momjian 已提交
259 260

	{"deadlock_timeout", PGC_POSTMASTER, &DeadlockTimeout,
261
	1000, 0, INT_MAX, NULL, NULL},
262 263

#ifdef ENABLE_SYSLOG
B
Bruce Momjian 已提交
264
	{"syslog", PGC_SIGHUP, &Use_syslog,
265
	0, 0, 2, NULL, NULL},
266 267 268
#endif

	/*
B
Bruce Momjian 已提交
269 270 271
	 * 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.
272
	 */
B
Bruce Momjian 已提交
273
	{"max_connections", PGC_POSTMASTER, &MaxBackends,
274
	DEF_MAXBACKENDS, 1, MAXBACKENDS, NULL, NULL},
275

B
Bruce Momjian 已提交
276
	{"shared_buffers", PGC_POSTMASTER, &NBuffers,
277
	DEF_NBUFFERS, 16, INT_MAX, NULL, NULL},
278

B
Bruce Momjian 已提交
279
	{"port", PGC_POSTMASTER, &PostPortNumber,
280
	DEF_PGPORT, 1, 65535, NULL, NULL},
281

282 283 284
	{"unix_socket_permissions", PGC_POSTMASTER, &Unix_socket_permissions,
	0777, 0000, 0777, NULL, NULL},

B
Bruce Momjian 已提交
285
	{"sort_mem", PGC_USERSET, &SortMem,
286
	512, 4*BLCKSZ/1024, INT_MAX, NULL, NULL},
287

B
Bruce Momjian 已提交
288
	{"debug_level", PGC_USERSET, &DebugLvl,
289
	0, 0, 16, NULL, NULL},
290 291

#ifdef LOCK_DEBUG
B
Bruce Momjian 已提交
292
	{"trace_lock_oidmin", PGC_SUSET, &Trace_lock_oidmin,
293
	BootstrapObjectIdData, 1, INT_MAX, NULL, NULL},
B
Bruce Momjian 已提交
294
	{"trace_lock_table", PGC_SUSET, &Trace_lock_table,
295
	0, 0, INT_MAX, NULL, NULL},
296
#endif
B
Bruce Momjian 已提交
297
	{"max_expr_depth", PGC_USERSET, &max_expr_depth,
298
	DEFAULT_MAX_EXPR_DEPTH, 10, INT_MAX, NULL, NULL},
299

300 301 302 303 304 305 306
	{"max_fsm_relations", PGC_POSTMASTER, &MaxFSMRelations,
	 100, 10, INT_MAX, NULL, NULL},
	{"max_fsm_pages", PGC_POSTMASTER, &MaxFSMPages,
	 10000, 1000, INT_MAX, NULL, NULL},

	{"max_locks_per_xact", PGC_POSTMASTER, &max_locks_per_xact,
	 64, 10, INT_MAX, NULL, NULL},
307

B
Bruce Momjian 已提交
308
	{"checkpoint_segments", PGC_SIGHUP, &CheckPointSegments,
309
	3, 1, INT_MAX, NULL, NULL},
T
Tom Lane 已提交
310

B
Bruce Momjian 已提交
311
	{"checkpoint_timeout", PGC_SIGHUP, &CheckPointTimeout,
312
	300, 30, 3600, NULL, NULL},
V
Vadim B. Mikheev 已提交
313

B
Bruce Momjian 已提交
314
	{"wal_buffers", PGC_POSTMASTER, &XLOGbuffers,
315
	8, 4, INT_MAX, NULL, NULL},
V
Vadim B. Mikheev 已提交
316

B
Bruce Momjian 已提交
317
	{"wal_files", PGC_SIGHUP, &XLOGfiles,
318
	0, 0, 64, NULL, NULL},
319

B
Bruce Momjian 已提交
320
	{"wal_debug", PGC_SUSET, &XLOG_DEBUG,
321
	0, 0, 16, NULL, NULL},
V
Vadim B. Mikheev 已提交
322

B
Bruce Momjian 已提交
323
	{"commit_delay", PGC_USERSET, &CommitDelay,
324
	0, 0, 100000, NULL, NULL},
V
Vadim B. Mikheev 已提交
325

B
Bruce Momjian 已提交
326
	{"commit_siblings", PGC_USERSET, &CommitSiblings,
327
	5, 1, 1000, NULL, NULL},
328

329
	{NULL, 0, NULL, 0, 0, 0, NULL, NULL}
330 331 332 333
};


static struct config_real
B
Bruce Momjian 已提交
334
			ConfigureNamesReal[] =
335
{
B
Bruce Momjian 已提交
336
	{"effective_cache_size", PGC_USERSET, &effective_cache_size,
337
	DEFAULT_EFFECTIVE_CACHE_SIZE, 0, DBL_MAX, NULL, NULL},
B
Bruce Momjian 已提交
338
	{"random_page_cost", PGC_USERSET, &random_page_cost,
339
	DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX, NULL, NULL},
B
Bruce Momjian 已提交
340
	{"cpu_tuple_cost", PGC_USERSET, &cpu_tuple_cost,
341
	DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX, NULL, NULL},
B
Bruce Momjian 已提交
342
	{"cpu_index_tuple_cost", PGC_USERSET, &cpu_index_tuple_cost,
343
	DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX, NULL, NULL},
B
Bruce Momjian 已提交
344
	{"cpu_operator_cost", PGC_USERSET, &cpu_operator_cost,
345
	DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX, NULL, NULL},
B
Bruce Momjian 已提交
346 347

	{"geqo_selection_bias", PGC_USERSET, &Geqo_selection_bias,
348 349
	DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS,
	MAX_GEQO_SELECTION_BIAS, NULL, NULL},
350

351
	{NULL, 0, NULL, 0.0, 0.0, 0.0, NULL, NULL}
352 353 354 355
};


static struct config_string
B
Bruce Momjian 已提交
356
			ConfigureNamesString[] =
357
{
358 359 360
	{"dynamic_library_path", PGC_SUSET, &Dynamic_library_path,
	 "$libdir", NULL, NULL},

B
Bruce Momjian 已提交
361 362
	{"krb_server_keyfile", PGC_POSTMASTER, &pg_krb_server_keyfile,
	PG_KRB_SRVTAB, NULL, NULL},
363

364
#ifdef ENABLE_SYSLOG
B
Bruce Momjian 已提交
365
	{"syslog_facility", PGC_POSTMASTER, &Syslog_facility,
366
	"LOCAL0", check_facility, NULL},
B
Bruce Momjian 已提交
367
	{"syslog_ident", PGC_POSTMASTER, &Syslog_ident,
368
	"postgres", NULL, NULL},
369
#endif
370

B
Bruce Momjian 已提交
371 372
	{"unix_socket_group", PGC_POSTMASTER, &Unix_socket_group,
	"", NULL, NULL},
373

B
Bruce Momjian 已提交
374 375
	{"unix_socket_directory", PGC_POSTMASTER, &UnixSocketDir,
	"", NULL, NULL},
376

B
Bruce Momjian 已提交
377 378
	{"virtual_host", PGC_POSTMASTER, &VirtualHost,
	"", NULL, NULL},
379

B
Bruce Momjian 已提交
380
	{"wal_sync_method", PGC_SIGHUP, &XLOG_sync_method,
381 382
	XLOG_sync_method_default, check_xlog_sync_method,
	assign_xlog_sync_method},
383 384

	{NULL, 0, NULL, NULL, NULL, NULL}
385 386 387 388 389 390 391 392 393 394 395 396
};

/******** 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 已提交
397
find_option(const char *name, struct config_generic ** record)
398
{
B
Bruce Momjian 已提交
399
	int			i;
400 401 402 403

	Assert(name);

	for (i = 0; ConfigureNamesBool[i].name; i++)
B
Bruce Momjian 已提交
404
		if (strcasecmp(ConfigureNamesBool[i].name, name) == 0)
405 406
		{
			if (record)
B
Bruce Momjian 已提交
407
				*record = (struct config_generic *) & ConfigureNamesBool[i];
408 409 410 411
			return PGC_BOOL;
		}

	for (i = 0; ConfigureNamesInt[i].name; i++)
B
Bruce Momjian 已提交
412
		if (strcasecmp(ConfigureNamesInt[i].name, name) == 0)
413 414
		{
			if (record)
B
Bruce Momjian 已提交
415
				*record = (struct config_generic *) & ConfigureNamesInt[i];
416 417 418 419
			return PGC_INT;
		}

	for (i = 0; ConfigureNamesReal[i].name; i++)
B
Bruce Momjian 已提交
420
		if (strcasecmp(ConfigureNamesReal[i].name, name) == 0)
421 422
		{
			if (record)
B
Bruce Momjian 已提交
423
				*record = (struct config_generic *) & ConfigureNamesReal[i];
424 425
			return PGC_REAL;
		}
426 427

	for (i = 0; ConfigureNamesString[i].name; i++)
B
Bruce Momjian 已提交
428
		if (strcasecmp(ConfigureNamesString[i].name, name) == 0)
429 430
		{
			if (record)
B
Bruce Momjian 已提交
431
				*record = (struct config_generic *) & ConfigureNamesString[i];
432 433 434 435
			return PGC_STRING;
		}

	return PGC_NONE;
436 437 438 439 440
}



/*
441 442 443
 * Reset all options to their specified default values.  Must be called
 * with isStartup = true at program startup.  May be called later with
 * isStartup = false to reset all resettable options.
444 445
 */
void
446
ResetAllOptions(bool isStartup)
447
{
B
Bruce Momjian 已提交
448
	int			i;
449

450
	for (i = 0; ConfigureNamesBool[i].name; i++)
451 452 453 454 455 456 457 458 459 460 461
	{
		struct config_bool *conf = &ConfigureNamesBool[i];

		if (isStartup ||
			conf->context == PGC_SUSET || conf->context == PGC_USERSET)
		{
			if (conf->assign_hook)
				(conf->assign_hook) (conf->default_val);
			*conf->variable = conf->default_val;
		}
	}
462

463
	for (i = 0; ConfigureNamesInt[i].name; i++)
464 465 466 467 468 469 470 471 472 473 474
	{
		struct config_int *conf = &ConfigureNamesInt[i];

		if (isStartup ||
			conf->context == PGC_SUSET || conf->context == PGC_USERSET)
		{
			if (conf->assign_hook)
				(conf->assign_hook) (conf->default_val);
			*conf->variable = conf->default_val;
		}
	}
475

476
	for (i = 0; ConfigureNamesReal[i].name; i++)
477 478 479 480 481 482 483 484 485 486 487
	{
		struct config_real *conf = &ConfigureNamesReal[i];

		if (isStartup ||
			conf->context == PGC_SUSET || conf->context == PGC_USERSET)
		{
			if (conf->assign_hook)
				(conf->assign_hook) (conf->default_val);
			*conf->variable = conf->default_val;
		}
	}
488

489
	for (i = 0; ConfigureNamesString[i].name; i++)
490
	{
491
		struct config_string *conf = &ConfigureNamesString[i];
492

493 494
		if (isStartup ||
			conf->context == PGC_SUSET || conf->context == PGC_USERSET)
495
		{
496
			char	   *str = NULL;
497

498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
			if (conf->default_val == NULL &&
				conf->boot_default_val)
			{
				str = strdup(conf->boot_default_val);
				if (str == NULL)
					elog(ERROR, "out of memory");
				conf->default_val = str;
			}
			if (conf->default_val)
			{
				str = strdup(conf->default_val);
				if (str == NULL)
					elog(ERROR, "out of memory");
			}
			if (conf->assign_hook)
				(conf->assign_hook) (str);
			if (*conf->variable)
				free(*conf->variable);
			*conf->variable = str;
517 518 519 520 521 522 523 524 525 526 527 528 529
		}
	}
}



/*
 * 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 已提交
530
parse_bool(const char *value, bool *result)
531
{
B
Bruce Momjian 已提交
532
	size_t		len = strlen(value);
533

B
Bruce Momjian 已提交
534
	if (strncasecmp(value, "true", len) == 0)
535 536 537 538
	{
		if (result)
			*result = true;
	}
B
Bruce Momjian 已提交
539
	else if (strncasecmp(value, "false", len) == 0)
540 541 542 543 544
	{
		if (result)
			*result = false;
	}

B
Bruce Momjian 已提交
545
	else if (strncasecmp(value, "yes", len) == 0)
546 547 548 549
	{
		if (result)
			*result = true;
	}
B
Bruce Momjian 已提交
550
	else if (strncasecmp(value, "no", len) == 0)
551 552 553 554 555
	{
		if (result)
			*result = false;
	}

B
Bruce Momjian 已提交
556
	else if (strcasecmp(value, "on") == 0)
557 558 559 560
	{
		if (result)
			*result = true;
	}
B
Bruce Momjian 已提交
561
	else if (strcasecmp(value, "off") == 0)
562 563 564 565 566
	{
		if (result)
			*result = false;
	}

B
Bruce Momjian 已提交
567
	else if (strcasecmp(value, "1") == 0)
568 569 570 571
	{
		if (result)
			*result = true;
	}
B
Bruce Momjian 已提交
572
	else if (strcasecmp(value, "0") == 0)
573 574 575 576 577 578 579 580
	{
		if (result)
			*result = false;
	}

	else
		return false;
	return true;
581 582 583 584 585 586 587 588 589 590 591
}



/*
 * 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 已提交
592
parse_int(const char *value, int *result)
593
{
B
Bruce Momjian 已提交
594 595
	long		val;
	char	   *endptr;
596 597 598

	errno = 0;
	val = strtol(value, &endptr, 0);
599 600 601 602 603 604
	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
	   )
605 606
		return false;
	if (result)
B
Bruce Momjian 已提交
607
		*result = (int) val;
608
	return true;
609 610 611 612 613 614
}



/*
 * Try to parse value as a floating point constant in the usual
B
Bruce Momjian 已提交
615
 * format.	If the value parsed okay return true, else false.  If
616 617 618
 * result is not NULL, return the semantic value there.
 */
static bool
B
Bruce Momjian 已提交
619
parse_real(const char *value, double *result)
620
{
B
Bruce Momjian 已提交
621 622
	double		val;
	char	   *endptr;
623 624 625 626 627 628 629 630

	errno = 0;
	val = strtod(value, &endptr);
	if (endptr == value || *endptr != '\0' || errno == ERANGE)
		return false;
	if (result)
		*result = val;
	return true;
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
}



/*
 * 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
656 657
set_config_option(const char *name, const char *value,
				  GucContext context, bool DoIt, bool makeDefault)
658
{
B
Bruce Momjian 已提交
659
	struct config_generic *record;
660
	enum config_type type;
B
Bruce Momjian 已提交
661
	int			elevel;
662 663 664

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

665 666
	type = find_option(name, &record);
	if (type == PGC_NONE)
667
	{
668
		elog(elevel, "'%s' is not a valid option name", name);
669 670 671
		return false;
	}

672 673
	/*
	 * Check if the option can be set at this time. See guc.h for the
B
Bruce Momjian 已提交
674 675
	 * 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.
676
	 */
677
	if (record->context == PGC_POSTMASTER && context != PGC_POSTMASTER)
678
	{
679
		if (context != PGC_SIGHUP)
680
			elog(ERROR, "'%s' cannot be changed after server start", name);
681 682
		else
			return true;
683
	}
684 685 686
	else if (record->context == PGC_SIGHUP && context != PGC_SIGHUP &&
			 context != PGC_POSTMASTER)
	{
687
		elog(ERROR, "'%s' cannot be changed now", name);
B
Bruce Momjian 已提交
688 689 690 691 692 693 694

		/*
		 * 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.
		 */
695 696 697 698 699
	}
	else if (record->context == PGC_BACKEND && context != PGC_BACKEND
			 && context != PGC_POSTMASTER)
	{
		if (context != PGC_SIGHUP)
700
			elog(ERROR, "'%s' cannot be set after connection start", name);
701 702 703
		else
			return true;
	}
704 705
	else if (record->context == PGC_SUSET &&
			 (context == PGC_USERSET || context == PGC_BACKEND))
706 707
		elog(ERROR, "permission denied");

708

709 710 711
	/*
	 * Evaluate value and set variable
	 */
B
Bruce Momjian 已提交
712
	switch (type)
713 714 715
	{
		case PGC_BOOL:
			{
B
Bruce Momjian 已提交
716 717 718
				struct config_bool *conf = (struct config_bool *) record;

				if (value)
719
				{
B
Bruce Momjian 已提交
720 721 722 723 724 725 726
					bool		boolval;

					if (!parse_bool(value, &boolval))
					{
						elog(elevel, "option '%s' requires a boolean value", name);
						return false;
					}
727
					/* no parse_hook needed for booleans */
B
Bruce Momjian 已提交
728
					if (DoIt)
729
					{
730 731
						if (conf->assign_hook)
							(conf->assign_hook) (boolval);
B
Bruce Momjian 已提交
732
						*conf->variable = boolval;
733 734 735
						if (makeDefault)
							conf->default_val = boolval;
					}
736
				}
B
Bruce Momjian 已提交
737
				else if (DoIt)
738 739 740
				{
					if (conf->assign_hook)
						(conf->assign_hook) (conf->default_val);
B
Bruce Momjian 已提交
741
					*conf->variable = conf->default_val;
742
				}
B
Bruce Momjian 已提交
743
				break;
744
			}
745 746

		case PGC_INT:
747
			{
B
Bruce Momjian 已提交
748
				struct config_int *conf = (struct config_int *) record;
749

B
Bruce Momjian 已提交
750
				if (value)
751
				{
B
Bruce Momjian 已提交
752 753 754 755 756 757 758 759 760 761 762 763 764 765
					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;
					}
766 767 768 769 770 771
					if (conf->parse_hook && !(conf->parse_hook) (intval))
					{
						elog(elevel, "invalid value for option '%s': %d",
							 name, intval);
						return false;
					}
B
Bruce Momjian 已提交
772
					if (DoIt)
773
					{
774 775
						if (conf->assign_hook)
							(conf->assign_hook) (intval);
B
Bruce Momjian 已提交
776
						*conf->variable = intval;
777 778 779
						if (makeDefault)
							conf->default_val = intval;
					}
780
				}
B
Bruce Momjian 已提交
781
				else if (DoIt)
782 783 784
				{
					if (conf->assign_hook)
						(conf->assign_hook) (conf->default_val);
B
Bruce Momjian 已提交
785
					*conf->variable = conf->default_val;
786
				}
B
Bruce Momjian 已提交
787
				break;
788
			}
789 790

		case PGC_REAL:
791
			{
B
Bruce Momjian 已提交
792
				struct config_real *conf = (struct config_real *) record;
793

B
Bruce Momjian 已提交
794
				if (value)
795
				{
B
Bruce Momjian 已提交
796 797 798 799 800 801 802 803 804 805 806 807 808 809
					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;
					}
810 811 812 813 814 815
					if (conf->parse_hook && !(conf->parse_hook) (dval))
					{
						elog(elevel, "invalid value for option '%s': %g",
							 name, dval);
						return false;
					}
B
Bruce Momjian 已提交
816
					if (DoIt)
817
					{
818 819
						if (conf->assign_hook)
							(conf->assign_hook) (dval);
B
Bruce Momjian 已提交
820
						*conf->variable = dval;
821 822 823
						if (makeDefault)
							conf->default_val = dval;
					}
824
				}
B
Bruce Momjian 已提交
825
				else if (DoIt)
826 827 828
				{
					if (conf->assign_hook)
						(conf->assign_hook) (conf->default_val);
B
Bruce Momjian 已提交
829
					*conf->variable = conf->default_val;
830
				}
B
Bruce Momjian 已提交
831
				break;
832
			}
833 834 835

		case PGC_STRING:
			{
B
Bruce Momjian 已提交
836 837 838
				struct config_string *conf = (struct config_string *) record;

				if (value)
839
				{
B
Bruce Momjian 已提交
840 841
					if (conf->parse_hook && !(conf->parse_hook) (value))
					{
842 843
						elog(elevel, "invalid value for option '%s': '%s'",
							 name, value);
B
Bruce Momjian 已提交
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
						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;
861 862 863 864 865 866 867
						if (makeDefault)
						{
							str = strdup(value);
							if (str == NULL) {
								elog(elevel, "out of memory");
								return false;
							}
868 869
							if (conf->default_val)
								free(conf->default_val);
870 871
							conf->default_val = str;
						}
B
Bruce Momjian 已提交
872
					}
873
				}
B
Bruce Momjian 已提交
874
				else if (DoIt)
875
				{
B
Bruce Momjian 已提交
876
					char	   *str;
877

878 879 880 881 882 883 884 885
					if (!conf->default_val && conf->boot_default_val)
					{
						str = strdup(conf->boot_default_val);
						if (str == NULL)
						{
							elog(elevel, "out of memory");
							return false;
						}
886
						conf->default_val = str;
887
					}
B
Bruce Momjian 已提交
888
					str = strdup(conf->default_val);
889 890 891 892 893
					if (str == NULL)
					{
						elog(elevel, "out of memory");
						return false;
					}
894
					if (conf->assign_hook)
B
Bruce Momjian 已提交
895
						(conf->assign_hook) (str);
896 897
					if (*conf->variable)
						free(*conf->variable);
898
					*conf->variable = str;
899
				}
B
Bruce Momjian 已提交
900
				break;
901 902
			}

B
Bruce Momjian 已提交
903
		default:;
904
	}
905 906 907 908 909 910 911 912 913 914
	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
915 916
SetConfigOption(const char *name, const char *value,
				GucContext context, bool makeDefault)
917
{
918
	(void) set_config_option(name, value, context, true, makeDefault);
919 920 921 922 923 924 925
}



/*
 * 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
926
 * elog and don't return.
927 928 929 930 931
 *
 * 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 已提交
932
GetConfigOption(const char *name)
933
{
B
Bruce Momjian 已提交
934
	struct config_generic *record;
935 936 937
	static char buffer[256];
	enum config_type opttype;

938
	opttype = find_option(name, &record);
939
	if (opttype == PGC_NONE)
940
		elog(ERROR, "Option '%s' is not recognized", name);
941

B
Bruce Momjian 已提交
942
	switch (opttype)
943 944
	{
		case PGC_BOOL:
B
Bruce Momjian 已提交
945
			return *((struct config_bool *) record)->variable ? "on" : "off";
946

947
		case PGC_INT:
948 949
			snprintf(buffer, sizeof(buffer), "%d",
					 *((struct config_int *) record)->variable);
950 951
			return buffer;

952
		case PGC_REAL:
953 954
			snprintf(buffer, sizeof(buffer), "%g",
					 *((struct config_real *) record)->variable);
955 956 957
			return buffer;

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

960
		default:
961
			;
962 963 964
	}
	return NULL;
}
965

966 967 968
static void
_ShowOption(enum config_type opttype, struct config_generic *record)
{
969
	char buffer[256];
970 971 972 973 974 975 976
	char *val;

	switch (opttype)
	{
		case PGC_BOOL:
			val = *((struct config_bool *) record)->variable ? "on" : "off";
			break;
977

978
		case PGC_INT:
979 980
			snprintf(buffer, sizeof(buffer), "%d",
					 *((struct config_int *) record)->variable);
981 982 983 984
			val = buffer;
			break;

		case PGC_REAL:
985 986
			snprintf(buffer, sizeof(buffer), "%g",
					 *((struct config_real *) record)->variable);
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
			val = buffer;
			break;

		case PGC_STRING:
			val = strlen(*((struct config_string *) record)->variable) != 0 ?
				*((struct config_string *) record)->variable : "unset";
			break;

		default:
			val = "???";
	}
	elog(NOTICE, "%s is %s", record->name, val);
}

void
ShowAllGUCConfig(void)
{
	int			i;

	for (i = 0; ConfigureNamesBool[i].name; i++)
		_ShowOption(PGC_BOOL, (struct config_generic *)&ConfigureNamesBool[i]);

	for (i = 0; ConfigureNamesInt[i].name; i++)
		_ShowOption(PGC_INT, (struct config_generic *)&ConfigureNamesInt[i]);

	for (i = 0; ConfigureNamesReal[i].name; i++)
		_ShowOption(PGC_REAL, (struct config_generic *)&ConfigureNamesReal[i]);

	for (i = 0; ConfigureNamesString[i].name; i++)
		_ShowOption(PGC_STRING, (struct config_generic *)&ConfigureNamesString[i]);
}



1021 1022 1023 1024 1025 1026 1027 1028 1029 1030


/*
 * 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 已提交
1031
ParseLongOption(const char *string, char **name, char **value)
1032
{
B
Bruce Momjian 已提交
1033 1034
	size_t		equal_pos;
	char	   *cp;
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053

	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 已提交
1054
	else
1055
	{
1056
		/* no equal sign in string */
1057 1058 1059 1060 1061 1062
		*name = strdup(string);
		if (!*name)
			elog(FATAL, "out of memory");
		*value = NULL;
	}

B
Bruce Momjian 已提交
1063
	for (cp = *name; *cp; cp++)
1064 1065 1066
		if (*cp == '-')
			*cp = '_';
}
1067 1068 1069



1070
#ifdef ENABLE_SYSLOG
1071

1072
static bool
1073 1074
check_facility(const char *facility)
{
B
Bruce Momjian 已提交
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
	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;
1091 1092
	return false;
}
B
Bruce Momjian 已提交
1093

1094
#endif