]> granicus.if.org Git - postgresql/commitdiff
Add ALTER ROLE ALL SET command
authorPeter Eisentraut <peter_e@gmx.net>
Mon, 18 Feb 2013 04:45:36 +0000 (23:45 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Mon, 18 Feb 2013 04:45:36 +0000 (23:45 -0500)
This generalizes the existing ALTER ROLE ... SET and ALTER DATABASE
... SET functionality to allow creating settings that apply to all users
in all databases.

reviewed by Pavel Stehule

doc/src/sgml/ref/alter_role.sgml
src/backend/commands/user.c
src/backend/parser/gram.y
src/backend/utils/init/postinit.c
src/backend/utils/misc/guc.c
src/include/utils/guc.h

index 2fbba53d25f5454d3c3494c362e2a4a2211359bc..b0981fdd5d5dfb073667d9d8bd391ea5c4fb73e5 100644 (file)
@@ -39,9 +39,9 @@ ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replace
 ALTER ROLE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 
 ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] SET <replaceable>configuration_parameter</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT }
-ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] SET <replaceable>configuration_parameter</replaceable> FROM CURRENT
-ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] RESET <replaceable>configuration_parameter</replaceable>
-ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] RESET ALL
+ALTER ROLE { <replaceable class="PARAMETER">name</replaceable> | ALL } [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] SET <replaceable>configuration_parameter</replaceable> FROM CURRENT
+ALTER ROLE { <replaceable class="PARAMETER">name</replaceable> | ALL } [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] RESET <replaceable>configuration_parameter</replaceable>
+ALTER ROLE { <replaceable class="PARAMETER">name</replaceable> | ALL } [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] RESET ALL
 </synopsis>
  </refsynopsisdiv>
 
@@ -83,8 +83,15 @@ ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ IN DATABASE <repl
   <para>
    The remaining variants change a role's session default for a configuration
    variable, either for all databases or, when the <literal>IN
-   DATABASE</literal> clause is specified, only for sessions in
-   the named database. Whenever the role subsequently
+   DATABASE</literal> clause is specified, only for sessions in the named
+   database.  If <literal>ALL</literal> is specified instead of a role name,
+   this changes the setting for all roles.  Using <literal>ALL</literal>
+   with <literal>IN DATABASE</literal> is effectively the same as using the
+   command <literal>ALTER DATABASE ... SET ...</literal>.
+  </para>
+
+  <para>
+   Whenever the role subsequently
    starts a new session, the specified value becomes the session
    default, overriding whatever setting is present in
    <filename>postgresql.conf</> or has been received from the <command>postgres</command>
@@ -93,12 +100,17 @@ ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ IN DATABASE <repl
    <xref linkend="sql-set-session-authorization"> does not cause new
    configuration values to be set.
    Settings set for all databases are overridden by database-specific settings
-   attached to a role.
+   attached to a role.  Settings for specific databases or specific roles override
+   settings for all roles.
+  </para>
+
+  <para>
    Superusers can change anyone's session defaults. Roles having
    <literal>CREATEROLE</> privilege can change defaults for non-superuser
    roles. Ordinary roles can only set defaults for themselves.
    Certain configuration variables cannot be set this way, or can only be
-   set if a superuser issues the command.
+   set if a superuser issues the command.  Only superusers can change a setting
+   for all roles in all databases.
   </para>
  </refsect1>
 
@@ -307,6 +319,7 @@ ALTER ROLE fred IN DATABASE devel SET client_min_messages = DEBUG;
   <simplelist type="inline">
    <member><xref linkend="sql-createrole"></member>
    <member><xref linkend="sql-droprole"></member>
+   <member><xref linkend="sql-alterdatabase"></member>
    <member><xref linkend="sql-set"></member>
   </simplelist>
  </refsect1>
index 3ba877d253a0dc14a40876f06d1ad59b5bffe4fe..5edb59af36b68950da7266cfa683152e106be429 100644 (file)
@@ -814,41 +814,46 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
 {
        HeapTuple       roletuple;
        Oid                     databaseid = InvalidOid;
-       Oid         roleid;
+       Oid         roleid = InvalidOid;
 
-       roletuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
+       if (stmt->role)
+       {
+               roletuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
 
-       if (!HeapTupleIsValid(roletuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("role \"%s\" does not exist", stmt->role)));
+               if (!HeapTupleIsValid(roletuple))
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                        errmsg("role \"%s\" does not exist", stmt->role)));
 
-       roleid = HeapTupleGetOid(roletuple);
+               roleid = HeapTupleGetOid(roletuple);
 
-       /*
-        * Obtain a lock on the role and make sure it didn't go away in the
-        * meantime.
-        */
-       shdepLockAndCheckObject(AuthIdRelationId, HeapTupleGetOid(roletuple));
+               /*
+                * Obtain a lock on the role and make sure it didn't go away in the
+                * meantime.
+                */
+               shdepLockAndCheckObject(AuthIdRelationId, HeapTupleGetOid(roletuple));
 
-       /*
-        * To mess with a superuser you gotta be superuser; else you need
-        * createrole, or just want to change your own settings
-        */
-       if (((Form_pg_authid) GETSTRUCT(roletuple))->rolsuper)
-       {
-               if (!superuser())
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                                        errmsg("must be superuser to alter superusers")));
-       }
-       else
-       {
-               if (!have_createrole_privilege() &&
-                       HeapTupleGetOid(roletuple) != GetUserId())
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                                        errmsg("permission denied")));
+               /*
+                * To mess with a superuser you gotta be superuser; else you need
+                * createrole, or just want to change your own settings
+                */
+               if (((Form_pg_authid) GETSTRUCT(roletuple))->rolsuper)
+               {
+                       if (!superuser())
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                                                errmsg("must be superuser to alter superusers")));
+               }
+               else
+               {
+                       if (!have_createrole_privilege() &&
+                               HeapTupleGetOid(roletuple) != GetUserId())
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                                                errmsg("permission denied")));
+               }
+
+               ReleaseSysCache(roletuple);
        }
 
        /* look up and lock the database, if specified */
@@ -856,10 +861,29 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
        {
                databaseid = get_database_oid(stmt->database, false);
                shdepLockAndCheckObject(DatabaseRelationId, databaseid);
+
+               if (!stmt->role)
+               {
+                       /*
+                        * If no role is specified, then this is effectively the same as
+                        * ALTER DATABASE ... SET, so use the same permission check.
+                        */
+                       if (!pg_database_ownercheck(databaseid, GetUserId()))
+                               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
+                                                          stmt->database);
+               }
+       }
+
+       if (!stmt->role && !stmt->database)
+       {
+               /* Must be superuser to alter settings globally. */
+               if (!superuser())
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                                        errmsg("must be superuser to alter settings globally")));
        }
 
-       AlterSetting(databaseid, HeapTupleGetOid(roletuple), stmt->setstmt);
-       ReleaseSysCache(roletuple);
+       AlterSetting(databaseid, roleid, stmt->setstmt);
 
        return roleid;
 }
index fee05311c5c5a8ecfaacc3f69799708dd5c5aa2e..b998431f5f36b3b62833db0e4d3c080810fd864f 100644 (file)
@@ -1020,6 +1020,14 @@ AlterRoleSetStmt:
                                        n->setstmt = $5;
                                        $$ = (Node *)n;
                                }
+                       | ALTER ROLE ALL opt_in_database SetResetClause
+                               {
+                                       AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
+                                       n->role = NULL;
+                                       n->database = $4;
+                                       n->setstmt = $5;
+                                       $$ = (Node *)n;
+                               }
                ;
 
 
index 7e21ceae8801f49b6a1cf10f0800362accb346b0..84270061d8a9c96963da03d83642ddd89f1bc862 100644 (file)
@@ -1010,6 +1010,7 @@ process_settings(Oid databaseid, Oid roleid)
        ApplySetting(databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
        ApplySetting(InvalidOid, roleid, relsetting, PGC_S_USER);
        ApplySetting(databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
+       ApplySetting(InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
 
        heap_close(relsetting, AccessShareLock);
 }
index 6128694200f0a9a69402493c0303ab9ea243e92b..5437e0744f3a12f60ab27c45839b1a44e89923a5 100644 (file)
@@ -500,6 +500,7 @@ const char *const GucSource_Names[] =
         /* PGC_S_ENV_VAR */ "environment variable",
         /* PGC_S_FILE */ "configuration file",
         /* PGC_S_ARGV */ "command line",
+        /* PGC_S_GLOBAL */ "global",
         /* PGC_S_DATABASE */ "database",
         /* PGC_S_USER */ "user",
         /* PGC_S_DATABASE_USER */ "database user",
@@ -5149,7 +5150,7 @@ 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_GLOBAL || source == PGC_S_DATABASE || source == PGC_S_USER ||
                                 source == PGC_S_DATABASE_USER)
                        elevel = WARNING;
                else
index 0023c007e0e98351bad1c8bea52c7e780b6bb4da..d497b1f6546d2dd0d41a34285c066e2a11b19748 100644 (file)
@@ -87,6 +87,7 @@ typedef enum
        PGC_S_ENV_VAR,                          /* postmaster environment variable */
        PGC_S_FILE,                                     /* postgresql.conf */
        PGC_S_ARGV,                                     /* postmaster command line */
+       PGC_S_GLOBAL,                           /* global in-database setting */
        PGC_S_DATABASE,                         /* per-database setting */
        PGC_S_USER,                                     /* per-user setting */
        PGC_S_DATABASE_USER,            /* per-user-and-database setting */