]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/misc/guc.c
Remove all the special-case code for INT64_IS_BUSTED, per decision that
[postgresql] / src / backend / utils / misc / guc.c
index 17bbbd7cb4aa9f4ed3579e4fe210bc8afbb5e6fa..38d577f87bb9a892a8908bc8f7d3dcc2eafe02bb 100644 (file)
@@ -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 <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.518 2009/09/17 21:15:18 petere 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;
@@ -170,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,
@@ -249,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},
@@ -385,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;
@@ -458,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",
@@ -1054,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."),
@@ -1216,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."),
@@ -1237,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
@@ -1347,6 +1362,8 @@ static struct config_int ConfigureNamesInt[] =
         * 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,
@@ -1357,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."),
@@ -1514,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."),
@@ -1572,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."),
@@ -2330,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_NOT_WHILE_SEC_DEF
+                       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
@@ -2341,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_NOT_WHILE_SEC_DEF
+                       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
@@ -2539,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
@@ -2655,15 +2715,6 @@ static struct config_enum ConfigureNamesEnum[] =
        },
 #endif
 
-       {
-               {"regex_flavor", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
-                       gettext_noop("Sets the regular expression \"flavor\"."),
-                       NULL
-               },
-               &regex_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."),
@@ -2674,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."),
@@ -4179,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)
                {
@@ -4545,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;
@@ -4669,29 +4727,45 @@ set_config_option(const char *name, const char *value,
        }
 
        /*
-        * Disallow changing GUC_NOT_WHILE_SEC_DEF values if we are inside a
-        * security-definer function.  We can reject this regardless of
-        * the context or source, mainly because sources that it might be
+        * 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_DEF should probably be marked
+        * 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 this because when we exit the sec-def
-        * context, GUC won't be notified, leaving things out of sync.
-        *
-        * XXX it would be nice to allow these cases in future, with the behavior
-        * being that the SET's effects end when the security definer context is
-        * exited.
+        * "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_DEF) && InSecurityDefinerContext())
+       if (record->flags & GUC_NOT_WHILE_SEC_REST)
        {
-               ereport(elevel,
-                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                                errmsg("cannot set parameter \"%s\" within security-definer function",
-                                               name)));
-               return false;
+               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;
+               }
        }
 
        /*
@@ -5186,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];
@@ -5200,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)));
@@ -5745,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:
@@ -6542,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;
@@ -7477,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;
 }
 
@@ -7723,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"