X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fbackend%2Futils%2Fmisc%2Fguc.c;h=38d577f87bb9a892a8908bc8f7d3dcc2eafe02bb;hb=901be0fad4034c9cf8a3588fd6cf2ece82e4b8ce;hp=66904e6b091c52dc961e4f7fccdcf773c8ce595b;hpb=25ec228ef760eb91c094cc3b6dea7257cc22ffb5;p=postgresql diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 66904e6b09..38d577f87b 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -6,11 +6,11 @@ * See src/backend/utils/misc/README for more information. * * - * Copyright (c) 2000-2009, PostgreSQL Global Development Group + * Copyright (c) 2000-2010, PostgreSQL Global Development Group * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.513 2009/08/31 02:23:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.532 2010/01/07 04:53:35 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -38,6 +38,7 @@ #include "commands/trigger.h" #include "funcapi.h" #include "libpq/auth.h" +#include "libpq/be-fsstubs.h" #include "libpq/pqformat.h" #include "miscadmin.h" #include "optimizer/cost.h" @@ -45,7 +46,6 @@ #include "optimizer/paths.h" #include "optimizer/planmain.h" #include "parser/parse_expr.h" -#include "parser/parse_relation.h" #include "parser/parse_type.h" #include "parser/parser.h" #include "parser/scansup.h" @@ -55,7 +55,6 @@ #include "postmaster/postmaster.h" #include "postmaster/syslogger.h" #include "postmaster/walwriter.h" -#include "regex/regex.h" #include "storage/bufmgr.h" #include "storage/fd.h" #include "tcop/tcopprot.h" @@ -88,7 +87,8 @@ #endif /* upper limit for GUC variables measured in kilobytes of memory */ -#if SIZEOF_SIZE_T > 4 +/* note that various places assume the byte size fits in a "long" variable */ +#if SIZEOF_SIZE_T > 4 && SIZEOF_LONG > 4 #define MAX_KILOBYTES INT_MAX #else #define MAX_KILOBYTES (INT_MAX / 1024) @@ -115,6 +115,9 @@ extern char *default_tablespace; extern char *temp_tablespaces; extern bool synchronize_seqscans; extern bool fullPageWrites; +extern int vacuum_defer_cleanup_age; + +int trace_recovery_messages = LOG; #ifdef TRACE_SORT extern bool trace_sort; @@ -152,6 +155,7 @@ static bool assign_phony_autocommit(bool newval, bool doit, GucSource source); static const char *assign_custom_variable_classes(const char *newval, bool doit, GucSource source); static bool assign_debug_assertions(bool newval, bool doit, GucSource source); +static bool assign_bonjour(bool newval, bool doit, GucSource source); static bool assign_ssl(bool newval, bool doit, GucSource source); static bool assign_stage_log_stats(bool newval, bool doit, GucSource source); static bool assign_log_stats(bool newval, bool doit, GucSource source); @@ -169,6 +173,7 @@ static bool assign_maxconnections(int newval, bool doit, GucSource source); static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source); static bool assign_effective_io_concurrency(int newval, bool doit, GucSource source); static const char *assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source); +static const char *assign_application_name(const char *newval, bool doit, GucSource source); static char *config_enum_get_options(struct config_enum * record, const char *prefix, const char *suffix, @@ -248,13 +253,6 @@ static const struct config_enum_entry log_statement_options[] = { {NULL, 0, false} }; -static const struct config_enum_entry regex_flavor_options[] = { - {"advanced", REG_ADVANCED, false}, - {"extended", REG_EXTENDED, false}, - {"basic", REG_BASIC, false}, - {NULL, 0, false} -}; - static const struct config_enum_entry isolation_level_options[] = { {"serializable", XACT_SERIALIZABLE, false}, {"repeatable read", XACT_REPEATABLE_READ, false}, @@ -384,6 +382,10 @@ char *external_pid_file; char *pgstat_temp_directory; +char *default_do_language; + +char *application_name; + int tcp_keepalives_idle; int tcp_keepalives_interval; int tcp_keepalives_count; @@ -457,6 +459,7 @@ const char *const GucSource_Names[] = /* PGC_S_ARGV */ "command line", /* PGC_S_DATABASE */ "database", /* PGC_S_USER */ "user", + /* PGC_S_DATABASE_USER */ "database user", /* PGC_S_CLIENT */ "client", /* PGC_S_OVERRIDE */ "override", /* PGC_S_INTERACTIVE */ "interactive", @@ -681,6 +684,14 @@ static struct config_bool ConfigureNamesBool[] = &session_auth_is_superuser, false, NULL, NULL }, + { + {"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS, + gettext_noop("Enables advertising the server via Bonjour."), + NULL + }, + &enable_bonjour, + false, assign_bonjour, NULL + }, { {"ssl", PGC_POSTMASTER, CONN_AUTH_SECURITY, gettext_noop("Enables SSL connections."), @@ -1045,14 +1056,6 @@ static struct config_bool ConfigureNamesBool[] = &XactReadOnly, false, assign_transaction_read_only, NULL }, - { - {"add_missing_from", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS, - gettext_noop("Automatically adds missing table references to FROM clauses."), - NULL - }, - &add_missing_from, - false, NULL, NULL - }, { {"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Check function bodies during CREATE FUNCTION."), @@ -1207,6 +1210,17 @@ static struct config_bool ConfigureNamesBool[] = false, NULL, NULL }, + { + {"recovery_connections", PGC_POSTMASTER, WAL_SETTINGS, + gettext_noop("During recovery, allows connections and queries. " + " During normal running, causes additional info to be written" + " to WAL to enable hot standby mode on WAL standby nodes."), + NULL + }, + &XLogRequestRecoveryConnections, + true, NULL, NULL + }, + { {"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS, gettext_noop("Allows modifications of the structure of system tables."), @@ -1228,6 +1242,16 @@ static struct config_bool ConfigureNamesBool[] = false, NULL, NULL }, + { + {"lo_compat_privileges", PGC_SUSET, COMPAT_OPTIONS_PREVIOUS, + gettext_noop("Enables backward compatibility mode for privilege checks on large objects"), + gettext_noop("Skips privilege checks when reading or modifying large objects, " + "for compatibility with PostgreSQL releases prior to 8.5.") + }, + &lo_compat_privileges, + false, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL @@ -1335,9 +1359,11 @@ static struct config_int ConfigureNamesInt[] = * Note: MaxBackends is limited to INT_MAX/4 because some places compute * 4*MaxBackends without any overflow check. This check is made in * assign_maxconnections, since MaxBackends is computed as MaxConnections - * plus autovacuum_max_workers. + * plus autovacuum_max_workers plus one (for the autovacuum launcher). * * Likewise we have to limit NBuffers to INT_MAX/2. + * + * See also CheckRequiredParameterValues() if this parameter changes */ { {"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS, @@ -1348,6 +1374,15 @@ static struct config_int ConfigureNamesInt[] = 100, 1, INT_MAX / 4, assign_maxconnections, NULL }, + { + {"max_standby_delay", PGC_SIGHUP, WAL_SETTINGS, + gettext_noop("Sets the maximum delay to avoid conflict processing on Hot Standby servers."), + NULL + }, + &MaxStandbyDelay, + 30, -1, INT_MAX, NULL, NULL + }, + { {"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS, gettext_noop("Sets the number of connection slots reserved for superusers."), @@ -1505,6 +1540,9 @@ static struct config_int ConfigureNamesInt[] = 1000, 25, INT_MAX, NULL, NULL }, + /* + * See also CheckRequiredParameterValues() if this parameter changes + */ { {"max_prepared_transactions", PGC_POSTMASTER, RESOURCES, gettext_noop("Sets the maximum number of simultaneously prepared transactions."), @@ -1563,6 +1601,18 @@ static struct config_int ConfigureNamesInt[] = 150000000, 0, 2000000000, NULL, NULL }, + { + {"vacuum_defer_cleanup_age", PGC_USERSET, CLIENT_CONN_STATEMENT, + gettext_noop("Age by which VACUUM and HOT cleanup should be deferred, if any."), + NULL + }, + &vacuum_defer_cleanup_age, + 0, 0, 1000000, NULL, NULL + }, + + /* + * See also CheckRequiredParameterValues() if this parameter changes + */ { {"max_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT, gettext_noop("Sets the maximum number of locks per transaction."), @@ -1675,7 +1725,7 @@ static struct config_int ConfigureNamesInt[] = "(FLT_DIG or DBL_DIG as appropriate).") }, &extra_float_digits, - 0, -15, 2, NULL, NULL + 0, -15, 3, NULL, NULL }, { @@ -2199,7 +2249,7 @@ static struct config_string ConfigureNamesString[] = { {"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS, - gettext_noop("Sets the Bonjour broadcast service name."), + gettext_noop("Sets the Bonjour service name."), NULL }, &bonjour_name, @@ -2321,7 +2371,7 @@ static struct config_string ConfigureNamesString[] = {"role", PGC_USERSET, UNGROUPED, gettext_noop("Sets the current role."), NULL, - GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST }, &role_string, "none", assign_role, show_role @@ -2332,7 +2382,7 @@ static struct config_string ConfigureNamesString[] = {"session_authorization", PGC_USERSET, UNGROUPED, gettext_noop("Sets the session user name."), NULL, - GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST }, &session_authorization_string, NULL, assign_session_authorization, show_session_authorization @@ -2530,6 +2580,25 @@ static struct config_string ConfigureNamesString[] = }, #endif /* USE_SSL */ + { + {"default_do_language", PGC_USERSET, CLIENT_CONN_STATEMENT, + gettext_noop("Sets the language used in DO statement if LANGUAGE is not specified."), + NULL + }, + &default_do_language, + "plpgsql", NULL, NULL + }, + + { + {"application_name", PGC_USERSET, LOGGING, + gettext_noop("Sets the application name to be reported in statistics and logs."), + NULL, + GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE + }, + &application_name, + "", assign_application_name, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL @@ -2646,15 +2715,6 @@ static struct config_enum ConfigureNamesEnum[] = }, #endif - { - {"regex_flavor", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS, - gettext_noop("Sets the regular expression \"flavor\"."), - NULL - }, - ®ex_flavor, - REG_ADVANCED, regex_flavor_options, NULL, NULL - }, - { {"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the session's behavior for triggers and rewrite rules."), @@ -2665,6 +2725,16 @@ static struct config_enum ConfigureNamesEnum[] = assign_session_replication_role, NULL }, + { + {"trace_recovery_messages", PGC_SUSET, LOGGING_WHEN, + gettext_noop("Sets the message levels that are logged during recovery."), + gettext_noop("Each level includes all the levels that follow it. The later" + " the level, the fewer messages are sent.") + }, + &trace_recovery_messages, + DEBUG1, server_message_level_options, NULL, NULL + }, + { {"track_functions", PGC_SUSET, STATS_COLLECTOR, gettext_noop("Collects function-level statistics on database activity."), @@ -4170,10 +4240,6 @@ parse_int(const char *value, int *result, int flags, const char **hintmsg) /* * Note: the multiple-switch coding technique here is a bit tedious, * but seems necessary to avoid intermediate-value overflows. - * - * If INT64_IS_BUSTED (ie, it's really int32) we will fail to detect - * overflow due to units conversion, but there are few enough such - * machines that it does not seem worth trying to be smarter. */ if (flags & GUC_UNIT_MEMORY) { @@ -4536,7 +4602,8 @@ set_config_option(const char *name, const char *value, */ elevel = IsUnderPostmaster ? DEBUG3 : LOG; } - else if (source == PGC_S_DATABASE || source == PGC_S_USER) + else if (source == PGC_S_DATABASE || source == PGC_S_USER || + source == PGC_S_DATABASE_USER) elevel = WARNING; else elevel = ERROR; @@ -4590,18 +4657,16 @@ set_config_option(const char *name, const char *value, if (changeVal && !is_newvalue_equal(record, value)) ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), - errmsg("attempted change of parameter \"%s\" ignored", - name), - errdetail("This parameter cannot be changed after server start."))); + errmsg("parameter \"%s\" cannot be changed without restarting the server", + name))); return true; } if (context != PGC_POSTMASTER) { ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), - errmsg("attempted change of parameter \"%s\" ignored", - name), - errdetail("This parameter cannot be changed after server start."))); + errmsg("parameter \"%s\" cannot be changed without restarting the server", + name))); return false; } break; @@ -4661,6 +4726,48 @@ set_config_option(const char *name, const char *value, break; } + /* + * Disallow changing GUC_NOT_WHILE_SEC_REST values if we are inside a + * security restriction context. We can reject this regardless of + * the GUC context or source, mainly because sources that it might be + * reasonable to override for won't be seen while inside a function. + * + * Note: variables marked GUC_NOT_WHILE_SEC_REST should usually be marked + * GUC_NO_RESET_ALL as well, because ResetAllOptions() doesn't check this. + * An exception might be made if the reset value is assumed to be "safe". + * + * Note: this flag is currently used for "session_authorization" and + * "role". We need to prohibit changing these inside a local userid + * context because when we exit it, GUC won't be notified, leaving things + * out of sync. (This could be fixed by forcing a new GUC nesting level, + * but that would change behavior in possibly-undesirable ways.) Also, + * we prohibit changing these in a security-restricted operation because + * otherwise RESET could be used to regain the session user's privileges. + */ + if (record->flags & GUC_NOT_WHILE_SEC_REST) + { + if (InLocalUserIdChange()) + { + /* + * Phrasing of this error message is historical, but it's the + * most common case. + */ + ereport(elevel, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("cannot set parameter \"%s\" within security-definer function", + name))); + return false; + } + if (InSecurityRestrictedOperation()) + { + ereport(elevel, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("cannot set parameter \"%s\" within security-restricted operation", + name))); + return false; + } + } + /* * Should we set reset/stacked values? (If so, the behavior is not * transactional.) This is done either when we get a default value from @@ -5153,11 +5260,15 @@ SetConfigOption(const char *name, const char *value, * Fetch the current value of the option `name'. If the option doesn't exist, * throw an ereport and don't return. * + * If restrict_superuser is true, we also enforce that only superusers can + * see GUC_SUPERUSER_ONLY variables. This should only be passed as true + * in user-driven calls. + * * The string is *not* allocated for modification and is really only * valid until the next call to configuration related functions. */ const char * -GetConfigOption(const char *name) +GetConfigOption(const char *name, bool restrict_superuser) { struct config_generic *record; static char buffer[256]; @@ -5167,7 +5278,9 @@ GetConfigOption(const char *name) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("unrecognized configuration parameter \"%s\"", name))); - if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser()) + if (restrict_superuser && + (record->flags & GUC_SUPERUSER_ONLY) && + !superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to examine \"%s\"", name))); @@ -5712,6 +5825,7 @@ define_custom_variable(struct config_generic * variable) break; case PGC_S_DATABASE: case PGC_S_USER: + case PGC_S_DATABASE_USER: case PGC_S_CLIENT: case PGC_S_SESSION: default: @@ -6509,10 +6623,7 @@ _ShowOption(struct config_generic * record, bool use_units) { /* * Use int64 arithmetic to avoid overflows in units - * conversion. If INT64_IS_BUSTED we might overflow - * anyway and print bogus answers, but there are few - * enough such machines that it doesn't seem worth trying - * harder. + * conversion. */ int64 result = *conf->variable; const char *unit; @@ -7368,6 +7479,21 @@ assign_debug_assertions(bool newval, bool doit, GucSource source) return true; } +static bool +assign_bonjour(bool newval, bool doit, GucSource source) +{ +#ifndef USE_BONJOUR + if (newval) + { + ereport(GUC_complaint_elevel(source), + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Bonjour is not supported by this build"))); + return false; + } +#endif + return true; +} + static bool assign_ssl(bool newval, bool doit, GucSource source) { @@ -7429,6 +7555,18 @@ assign_transaction_read_only(bool newval, bool doit, GucSource source) if (source != PGC_S_OVERRIDE) return false; } + + /* Can't go to r/w mode while recovery is still active */ + if (newval == false && XactReadOnly && RecoveryInProgress()) + { + ereport(GUC_complaint_elevel(source), + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("cannot set transaction read-write mode during recovery"))); + /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */ + if (source != PGC_S_OVERRIDE) + return false; + } + return true; } @@ -7570,11 +7708,11 @@ show_tcp_keepalives_count(void) static bool assign_maxconnections(int newval, bool doit, GucSource source) { - if (newval + autovacuum_max_workers > INT_MAX / 4) + if (newval + autovacuum_max_workers + 1 > INT_MAX / 4) return false; if (doit) - MaxBackends = newval + autovacuum_max_workers; + MaxBackends = newval + autovacuum_max_workers + 1; return true; } @@ -7582,11 +7720,11 @@ assign_maxconnections(int newval, bool doit, GucSource source) static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source) { - if (newval + MaxConnections > INT_MAX / 4) + if (MaxConnections + newval + 1 > INT_MAX / 4) return false; if (doit) - MaxBackends = newval + MaxConnections; + MaxBackends = MaxConnections + newval + 1; return true; } @@ -7675,4 +7813,28 @@ assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source) return newval; } +static const char * +assign_application_name(const char *newval, bool doit, GucSource source) +{ + if (doit) + { + /* Only allow clean ASCII chars in the application name */ + char *repval = guc_strdup(ERROR, newval); + char *p; + + for (p = repval; *p; p++) + { + if (*p < 32 || *p > 126) + *p = '?'; + } + + /* Update the pg_stat_activity view */ + pgstat_report_appname(repval); + + return repval; + } + else + return newval; +} + #include "guc-file.c"