]> granicus.if.org Git - postgresql/commitdiff
Allow CURRENT/SESSION_USER to be used in certain commands
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 9 Mar 2015 18:41:54 +0000 (15:41 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 9 Mar 2015 18:41:54 +0000 (15:41 -0300)
Commands such as ALTER USER, ALTER GROUP, ALTER ROLE, GRANT, and the
various ALTER OBJECT / OWNER TO, as well as ad-hoc clauses related to
roles such as the AUTHORIZATION clause of CREATE SCHEMA, the FOR clause
of CREATE USER MAPPING, and the FOR ROLE clause of ALTER DEFAULT
PRIVILEGES can now take the keywords CURRENT_USER and SESSION_USER as
user specifiers in place of an explicit user name.

This commit also fixes some quite ugly handling of special standards-
mandated syntax in CREATE USER MAPPING, which in particular would fail
to work in presence of a role named "current_user".

The special role specifiers PUBLIC and NONE also have more consistent
handling now.

Also take the opportunity to add location tracking to user specifiers.

Authors: Kyotaro Horiguchi.  Heavily reworked by Álvaro Herrera.
Reviewed by: Rushabh Lathia, Adam Brightwell, Marti Raudsepp.

52 files changed:
doc/src/sgml/ref/alter_aggregate.sgml
doc/src/sgml/ref/alter_collation.sgml
doc/src/sgml/ref/alter_conversion.sgml
doc/src/sgml/ref/alter_database.sgml
doc/src/sgml/ref/alter_domain.sgml
doc/src/sgml/ref/alter_event_trigger.sgml
doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
doc/src/sgml/ref/alter_foreign_table.sgml
doc/src/sgml/ref/alter_function.sgml
doc/src/sgml/ref/alter_group.sgml
doc/src/sgml/ref/alter_language.sgml
doc/src/sgml/ref/alter_large_object.sgml
doc/src/sgml/ref/alter_materialized_view.sgml
doc/src/sgml/ref/alter_opclass.sgml
doc/src/sgml/ref/alter_operator.sgml
doc/src/sgml/ref/alter_opfamily.sgml
doc/src/sgml/ref/alter_role.sgml
doc/src/sgml/ref/alter_schema.sgml
doc/src/sgml/ref/alter_sequence.sgml
doc/src/sgml/ref/alter_server.sgml
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/alter_tablespace.sgml
doc/src/sgml/ref/alter_tsconfig.sgml
doc/src/sgml/ref/alter_tsdictionary.sgml
doc/src/sgml/ref/alter_type.sgml
doc/src/sgml/ref/alter_user.sgml
doc/src/sgml/ref/alter_user_mapping.sgml
doc/src/sgml/ref/alter_view.sgml
doc/src/sgml/ref/create_schema.sgml
doc/src/sgml/ref/grant.sgml
src/backend/catalog/aclchk.c
src/backend/commands/alter.c
src/backend/commands/extension.c
src/backend/commands/foreigncmds.c
src/backend/commands/policy.c
src/backend/commands/schemacmds.c
src/backend/commands/tablecmds.c
src/backend/commands/tablespace.c
src/backend/commands/user.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/parser/parse_utilcmd.c
src/backend/utils/adt/acl.c
src/include/commands/user.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/include/utils/acl.h
src/test/regress/expected/rolenames.out [new file with mode: 0644]
src/test/regress/parallel_schedule
src/test/regress/serial_schedule
src/test/regress/sql/rolenames.sql [new file with mode: 0644]

index f92b8e5da379e348b21e9d78e66fa6f9b3c27155..3aa7c259da187b2b481f560892116376f8596b34 100644 (file)
@@ -22,7 +22,8 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>aggregate_signature</replaceable> ) RENAME TO <replaceable>new_name</replaceable>
-ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>aggregate_signature</replaceable> ) OWNER TO <replaceable>new_owner</replaceable>
+ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>aggregate_signature</replaceable> )
+                OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>aggregate_signature</replaceable> ) SET SCHEMA <replaceable>new_schema</replaceable>
 
 <phrase>where <replaceable>aggregate_signature</replaceable> is:</phrase>
index 11ecd93c205f145a6bd62ef01fec071788eb38cc..6708c7e10e896964ecba85c5cb7a8a41bcef4d12 100644 (file)
@@ -22,7 +22,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER COLLATION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER COLLATION <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER COLLATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER COLLATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
index a3f68975bfeffbd73745a76a81fe86a9e0d0bda9..3514720d03ebbf31e8f03dae49705661c0088a66 100644 (file)
@@ -22,7 +22,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER CONVERSION <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER CONVERSION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER CONVERSION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
index 95c7ac91584267d32d6108b857cf4b3a046a03b8..8b6fa5816f45b2589e039a5d9ed215b1426daf87 100644 (file)
@@ -31,7 +31,7 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <rep
 
 ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 
-ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 
 ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> SET TABLESPACE <replaceable class="PARAMETER">new_tablespace</replaceable>
 
index d65d517bb5f9981021cad19be944f333e720d880..f738b2948b3581045af8a5ca0f8e6dc45a1b380d 100644 (file)
@@ -36,7 +36,7 @@ ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
 ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
     VALIDATE CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable>
 ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
-    OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
+    OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
     RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
 ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
index 1bf9d8abb609d99e835e6d92c94d6d91bbd20b03..9d6c64ad5299fe73eb1535732cf9ed83467550da 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 ALTER EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable> DISABLE
 ALTER EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable> ENABLE [ REPLICA | ALWAYS ]
-ALTER EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
+ALTER EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable> OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
index 1c82db9e0385f7efb751dedd8b00d890dac4b353..3f5fb0f77ea925dafc29fdd2e4de99f940f218fe 100644 (file)
@@ -25,7 +25,7 @@ ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
     [ HANDLER <replaceable class="parameter">handler_function</replaceable> | NO HANDLER ]
     [ VALIDATOR <replaceable class="parameter">validator_function</replaceable> | NO VALIDATOR ]
     [ OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ]) ]
-ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
index ff48ab888299ff258e49d0323a54f561993e2c9e..93f8743071bf30d2bdd1e586b495d995821e08e2 100644 (file)
@@ -48,7 +48,7 @@ ALTER FOREIGN TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceab
     ENABLE TRIGGER [ <replaceable class="PARAMETER">trigger_name</replaceable> | ALL | USER ]
     ENABLE REPLICA TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable>
     ENABLE ALWAYS TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable>
-    OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
+    OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
     OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ])
 </synopsis>
  </refsynopsisdiv>
index ba879eb1ea33448ae34f3d2483162daf17782f3f..4e77962c88d6593da38eb92d70ecfb68f3eb6143 100644 (file)
@@ -26,7 +26,7 @@ ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="paramet
 ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] )
     RENAME TO <replaceable>new_name</replaceable>
 ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] )
-    OWNER TO <replaceable>new_owner</replaceable>
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] )
     SET SCHEMA <replaceable>new_schema</replaceable>
 
index 143224286ab5c14c88011d9437c4800ddee0f33c..adf6f7e932325c3eaa3ffd7ab8fa6a03bea8cd48 100644 (file)
@@ -21,8 +21,14 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER GROUP <replaceable class="PARAMETER">group_name</replaceable> ADD USER <replaceable class="PARAMETER">user_name</replaceable> [, ... ]
-ALTER GROUP <replaceable class="PARAMETER">group_name</replaceable> DROP USER <replaceable class="PARAMETER">user_name</replaceable> [, ... ]
+ALTER GROUP <replaceable class="PARAMETER">role_specification</replaceable> ADD USER <replaceable class="PARAMETER">user_name</replaceable> [, ... ]
+ALTER GROUP <replaceable class="PARAMETER">role_specification</replaceable> DROP USER <replaceable class="PARAMETER">user_name</replaceable> [, ... ]
+
+<phrase>where <replaceable class="PARAMETER">role_specification</replaceable> can be:</phrase>
+
+    <replaceable class="PARAMETER">role_name</replaceable>
+  | CURRENT_USER
+  | SESSION_USER
 
 ALTER GROUP <replaceable class="PARAMETER">group_name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
index 5c9ded6837fef608d02a8e4f9cb0ea0a7052077b..63d9ecd924dca136b1b925c52ae3dd7b1bba6355 100644 (file)
@@ -22,7 +22,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER [ PROCEDURAL ] LANGUAGE <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER [ PROCEDURAL ] LANGUAGE <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER [ PROCEDURAL ] LANGUAGE <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
index a6dabca1b2fd29ca3231a617eec597ac3343b897..a0ed6c22f3449d8f72bf28606e2e320877640a2d 100644 (file)
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER LARGE OBJECT <replaceable class="PARAMETER">large_object_oid</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER LARGE OBJECT <replaceable class="PARAMETER">large_object_oid</replaceable> { OWNER TO <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
index b0759fc5dca5af497e837f203d9edc7082820f4a..8807e01c365900623f8e45211238150dc80023d7 100644 (file)
@@ -42,7 +42,7 @@ ALTER MATERIALIZED VIEW ALL IN TABLESPACE <replaceable class="parameter">name</r
     SET WITHOUT CLUSTER
     SET ( <replaceable class="PARAMETER">storage_parameter</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )
     RESET ( <replaceable class="PARAMETER">storage_parameter</replaceable> [, ... ] )
-    OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
+    OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
     SET TABLESPACE <replaceable class="PARAMETER">new_tablespace</replaceable>
 </synopsis>
  </refsynopsisdiv>
index fc41d866611f24b9c68fc7b8878edacfffe02cab..2e561be8d78f4f25ef8c7925e06882f1a060594b 100644 (file)
@@ -21,9 +21,14 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> OWNER TO <replaceable>new_owner</replaceable>
-ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
+ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
+           RENAME TO <replaceable>new_name</replaceable>
+
+ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
+          { OWNER TO <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+
+ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
+          SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
index 60754163204d3484488fee71c4230e5e19613d05..bdb2d029b171a297307b1c52a2fcbbc5cd2ffa92 100644 (file)
@@ -21,8 +21,11 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>left_type</replaceable> | NONE } , { <replaceable>right_type</replaceable> | NONE } ) OWNER TO <replaceable>new_owner</replaceable>
-ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>left_type</replaceable> | NONE } , { <replaceable>right_type</replaceable> | NONE } ) SET SCHEMA <replaceable>new_schema</replaceable>
+ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>left_type</replaceable> | NONE } , { <replaceable>right_type</replaceable> | NONE } )
+             { OWNER TO <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+
+ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>left_type</replaceable> | NONE } , { <replaceable>right_type</replaceable> | NONE } )
+               SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
index 55b912611d94eada68880ed8fc4d2a0a783fdf6c..b0942b6ea7de2c71053357cca076fdf168507ccf 100644 (file)
@@ -22,16 +22,25 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> ADD
-  {  OPERATOR <replaceable class="parameter">strategy_number</replaceable> <replaceable class="parameter">operator_name</replaceable> ( <replaceable class="parameter">op_type</replaceable>, <replaceable class="parameter">op_type</replaceable> ) [ FOR SEARCH | FOR ORDER BY <replaceable class="parameter">sort_family_name</replaceable> ]
-   | FUNCTION <replaceable class="parameter">support_number</replaceable> [ ( <replaceable class="parameter">op_type</replaceable> [ , <replaceable class="parameter">op_type</replaceable> ] ) ] <replaceable class="parameter">function_name</replaceable> ( <replaceable class="parameter">argument_type</replaceable> [, ...] )
+  {  OPERATOR <replaceable class="parameter">strategy_number</replaceable> <replaceable class="parameter">operator_name</replaceable> ( <replaceable class="parameter">op_type</replaceable>, <replaceable class="parameter">op_type</replaceable> )
+              [ FOR SEARCH | FOR ORDER BY <replaceable class="parameter">sort_family_name</replaceable> ]
+   | FUNCTION <replaceable class="parameter">support_number</replaceable> [ ( <replaceable class="parameter">op_type</replaceable> [ , <replaceable class="parameter">op_type</replaceable> ] ) ]
+              <replaceable class="parameter">function_name</replaceable> ( <replaceable class="parameter">argument_type</replaceable> [, ...] )
   } [, ... ]
+
 ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> DROP
   {  OPERATOR <replaceable class="parameter">strategy_number</replaceable> ( <replaceable class="parameter">op_type</replaceable> [ , <replaceable class="parameter">op_type</replaceable> ] )
    | FUNCTION <replaceable class="parameter">support_number</replaceable> ( <replaceable class="parameter">op_type</replaceable> [ , <replaceable class="parameter">op_type</replaceable> ] )
   } [, ... ]
-ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> OWNER TO <replaceable>new_owner</replaceable>
-ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
+
+ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
+            RENAME TO <replaceable>new_name</replaceable>
+
+ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
+             OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+
+ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
+           SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
index 0471daa1cce7329d4bce0b3efbe80a0f4cf24790..e97bf4c9d282e27da928068289230b6eac0c0453 100644 (file)
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
+ALTER ROLE <replaceable class="PARAMETER">role_specification</replaceable> [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ]
 
 <phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
 
@@ -39,10 +39,16 @@ 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> | 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
+ALTER ROLE { <replaceable class="PARAMETER">role_specification</replaceable> | ALL } [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] SET <replaceable>configuration_parameter</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT }
+ALTER ROLE { <replaceable class="PARAMETER">role_specification</replaceable> | ALL } [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] SET <replaceable>configuration_parameter</replaceable> FROM CURRENT
+ALTER ROLE { <replaceable class="PARAMETER">role_specification</replaceable> | ALL } [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] RESET <replaceable>configuration_parameter</replaceable>
+ALTER ROLE { <replaceable class="PARAMETER">role_specification</replaceable> | ALL } [ IN DATABASE <replaceable class="PARAMETER">database_name</replaceable> ] RESET ALL
+
+<phrase>where <replaceable class="PARAMETER">role_specification</replaceable> can be:</phrase>
+
+    [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable>
+  | CURRENT_USER
+  | SESSION_USER
 </synopsis>
  </refsynopsisdiv>
 
@@ -128,6 +134,25 @@ ALTER ROLE { <replaceable class="PARAMETER">name</replaceable> | ALL } [ IN DATA
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term>CURRENT_USER</term>
+      <listitem>
+       <para>
+        Alter the current user instead of an explicitely identified role.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term>SESSION_USER</term>
+      <listitem>
+       <para>
+        Alter the current session user instead of an explicitely identified
+        role.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><literal>SUPERUSER</literal></term>
       <term><literal>NOSUPERUSER</literal></term>
index 00395c02f85867c75ae6e86bd383e303e590195e..dbc5c2d45f54166392afb7372a9e2095038e1153 100644 (file)
@@ -22,7 +22,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER SCHEMA <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER SCHEMA <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
index 9ba9bc46229152b2e670377d57daf51635497adf..47d3c8291fa5bfc7153255b583f6ee9316a2a5be 100644 (file)
@@ -29,7 +29,7 @@ ALTER SEQUENCE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> [
     [ RESTART [ [ WITH ] <replaceable class="parameter">restart</replaceable> ] ]
     [ CACHE <replaceable class="parameter">cache</replaceable> ] [ [ NO ] CYCLE ]
     [ OWNED BY { <replaceable class="parameter">table_name</replaceable>.<replaceable class="parameter">column_name</replaceable> | NONE } ]
-ALTER SEQUENCE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
+ALTER SEQUENCE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER SEQUENCE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 ALTER SEQUENCE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
 </synopsis>
index 68253b916680ae085d90d153da2783ebdb7f6b2d..e6cf511853f669ca7aba2e2b9c92b913d7819b07 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 ALTER SERVER <replaceable class="parameter">name</replaceable> [ VERSION '<replaceable class="parameter">new_version</replaceable>' ]
     [ OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] ) ]
-ALTER SERVER <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER SERVER <replaceable class="PARAMETER">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER SERVER <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
index b3a497071357a737c479a660b0d7e994f42a7e15..19baf2961a4826c49e59c7314c7fc6538192839f 100644 (file)
@@ -73,7 +73,7 @@ ALTER TABLE ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable>
     NO INHERIT <replaceable class="PARAMETER">parent_table</replaceable>
     OF <replaceable class="PARAMETER">type_name</replaceable>
     NOT OF
-    OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
+    OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
     REPLICA IDENTITY {DEFAULT | USING INDEX <replaceable class="PARAMETER">index_name</replaceable> | FULL | NOTHING}
 
 <phrase>and <replaceable class="PARAMETER">table_constraint_using_index</replaceable> is:</phrase>
index 9d27173d71e9aececfc0d106e9a7d287194a38de..d9b2a133b10632945ab9a86016e0eb0d27929748 100644 (file)
@@ -22,7 +22,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER TABLESPACE <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER TABLESPACE <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER TABLESPACE <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER TABLESPACE <replaceable>name</replaceable> SET ( <replaceable class="PARAMETER">tablespace_option</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )
 ALTER TABLESPACE <replaceable>name</replaceable> RESET ( <replaceable class="PARAMETER">tablespace_option</replaceable> [, ... ] )
 </synopsis>
index 1a40d88f6a0cb5fa9ff9d355fc0d7bc1adbf60f7..72a719b8629b75a603355398d67e2c230202a56a 100644 (file)
@@ -32,7 +32,7 @@ ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable>
 ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable>
     DROP MAPPING [ IF EXISTS ] FOR <replaceable class="parameter">token_type</replaceable> [, ... ]
 ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
index 368f8ee1352b27eb6e56cc991c3f2f4d05a382dc..7cecabea83bd8da82af906eed7a56bca82cb8c52 100644 (file)
@@ -25,7 +25,7 @@ ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> (
     <replaceable class="parameter">option</replaceable> [ = <replaceable class="parameter">value</replaceable> ] [, ... ]
 )
 ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
index 7724c11c78e7c9a0cdd5546ea38bcfdc6e7b0b17..9789881a5cabef66277da8a623fdfb3873816a12 100644 (file)
@@ -24,7 +24,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> <replaceable class="PARAMETER">action</replaceable> [, ... ]
-ALTER TYPE <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
+ALTER TYPE <replaceable class="PARAMETER">name</replaceable> OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> TO <replaceable class="PARAMETER">new_attribute_name</replaceable> [ CASCADE | RESTRICT ]
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
index 58ae1da127f68eab9df07b105783a515f5346888..0ffaa16da2fc75fcd1121dcde627837d6a8e9166 100644 (file)
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER USER <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
+ALTER USER <replaceable class="PARAMETER">role_specification</replaceable> [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ]
 
 <phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
 
@@ -38,10 +38,16 @@ ALTER USER <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replace
 
 ALTER USER <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 
-ALTER USER <replaceable class="PARAMETER">name</replaceable> SET <replaceable>configuration_parameter</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT }
-ALTER USER <replaceable class="PARAMETER">name</replaceable> SET <replaceable>configuration_parameter</replaceable> FROM CURRENT
-ALTER USER <replaceable class="PARAMETER">name</replaceable> RESET <replaceable>configuration_parameter</replaceable>
-ALTER USER <replaceable class="PARAMETER">name</replaceable> RESET ALL
+ALTER USER <replaceable class="PARAMETER">role_specification</replaceable> SET <replaceable>configuration_parameter</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT }
+ALTER USER <replaceable class="PARAMETER">role_specification</replaceable> SET <replaceable>configuration_parameter</replaceable> FROM CURRENT
+ALTER USER <replaceable class="PARAMETER">role_specification</replaceable> RESET <replaceable>configuration_parameter</replaceable>
+ALTER USER <replaceable class="PARAMETER">role_specification</replaceable> RESET ALL
+
+<phrase>where <replaceable class="PARAMETER">role_specification</replaceable> can be:</phrase>
+
+    [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable>
+  | CURRENT_USER
+  | SESSION_USER
 </synopsis>
  </refsynopsisdiv>
 
index d0ddd1370b9b32b2c00f5a896739cdffb9b65487..3cd51b14139454c9f318acee8362b7d5af47826a 100644 (file)
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_USER | PUBLIC }
+ALTER USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_USER | SESSION_USER | PUBLIC }
     SERVER <replaceable class="parameter">server_name</replaceable>
     OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )
 </synopsis>
index 3aef61b67e6d5664b08636da2ec5f7b3b29f2f06..00f4ecb9b1a89650372fba4afaebd1a7aa4562de 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ALTER [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> SET DEFAULT <replaceable class="PARAMETER">expression</replaceable>
 ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ALTER [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> DROP DEFAULT
-ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
+ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
 ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
 ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">view_option_name</replaceable> [= <replaceable class="parameter">view_option_value</replaceable>] [, ... ] )
index 45e4637ab5b21f6b6e05294aaa71081cdf9f17c4..79305f15dd03f052745acbf008e8fc31f87bc63e 100644 (file)
@@ -21,10 +21,16 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-CREATE SCHEMA <replaceable class="parameter">schema_name</replaceable> [ AUTHORIZATION <replaceable class="parameter">user_name</replaceable> ] [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ]
-CREATE SCHEMA AUTHORIZATION <replaceable class="parameter">user_name</replaceable> [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ]
-CREATE SCHEMA IF NOT EXISTS <replaceable class="parameter">schema_name</replaceable> [ AUTHORIZATION <replaceable class="parameter">user_name</replaceable> ]
-CREATE SCHEMA IF NOT EXISTS AUTHORIZATION <replaceable class="parameter">user_name</replaceable>
+CREATE SCHEMA <replaceable class="parameter">schema_name</replaceable> [ AUTHORIZATION <replaceable class="PARAMETER">role_specification</replaceable> ] [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ]
+CREATE SCHEMA AUTHORIZATION <replaceable class="PARAMETER">role_specification</replaceable> [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ]
+CREATE SCHEMA IF NOT EXISTS <replaceable class="parameter">schema_name</replaceable> [ AUTHORIZATION <replaceable class="PARAMETER">role_specification</replaceable> ]
+CREATE SCHEMA IF NOT EXISTS AUTHORIZATION <replaceable class="PARAMETER">role_specification</replaceable>
+
+<phrase>where <replaceable class="PARAMETER">role_specification</replaceable> can be:</phrase>
+
+    [ GROUP ] <replaceable class="PARAMETER">user_name</replaceable>
+  | CURRENT_USER
+  | SESSION_USER
 </synopsis>
  </refsynopsisdiv>
 
index f2b25e546c3bc5b3d50fdd18b9973cad74784926..d9ac8d20f2dae758b6a0d7177a9caf2991f7335a 100644 (file)
@@ -25,59 +25,66 @@ GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
     [, ...] | ALL [ PRIVILEGES ] }
     ON { [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
          | ALL TABLES IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] }
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] )
     [, ...] | ALL [ PRIVILEGES ] ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] ) }
     ON [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { { USAGE | SELECT | UPDATE }
     [, ...] | ALL [ PRIVILEGES ] }
     ON { SEQUENCE <replaceable class="PARAMETER">sequence_name</replaceable> [, ...]
          | ALL SEQUENCES IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] }
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
     ON DATABASE <replaceable>database_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON DOMAIN <replaceable>domain_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON FOREIGN DATA WRAPPER <replaceable>fdw_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON FOREIGN SERVER <replaceable>server_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { EXECUTE | ALL [ PRIVILEGES ] }
     ON { FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...]
          | ALL FUNCTIONS IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] }
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON LANGUAGE <replaceable>lang_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
     ON LARGE OBJECT <replaceable class="PARAMETER">loid</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
     ON SCHEMA <replaceable>schema_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { CREATE | ALL [ PRIVILEGES ] }
     ON TABLESPACE <replaceable>tablespace_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON TYPE <replaceable>type_name</replaceable> [, ...]
-    TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+    TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+
+<phrase>where <replaceable class="PARAMETER">role_specification</replaceable> can be:</phrase>
+
+    [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable>
+  | PUBLIC
+  | CURRENT_USER
+  | SESSION_USER
 
 GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replaceable class="PARAMETER">role_name</replaceable> [, ...] [ WITH ADMIN OPTION ]
 </synopsis>
index 3b456f97efa4ddb95ad783603840bcb3e0a182da..6c8780f794dbfd0764126cf2564c86058ff0dd88 100644 (file)
@@ -421,22 +421,25 @@ ExecuteGrantStmt(GrantStmt *stmt)
        istmt.behavior = stmt->behavior;
 
        /*
-        * Convert the PrivGrantee list into an Oid list.  Note that at this point
-        * we insert an ACL_ID_PUBLIC into the list if an empty role name is
-        * detected (which is what the grammar uses if PUBLIC is found), so
-        * downstream there shouldn't be any additional work needed to support
-        * this case.
+        * Convert the RoleSpec list into an Oid list.  Note that at this point
+        * we insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
+        * there shouldn't be any additional work needed to support this case.
         */
        foreach(cell, stmt->grantees)
        {
-               PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
+               RoleSpec *grantee = (RoleSpec *) lfirst(cell);
+               Oid grantee_uid;
 
-               if (grantee->rolname == NULL)
-                       istmt.grantees = lappend_oid(istmt.grantees, ACL_ID_PUBLIC);
-               else
-                       istmt.grantees =
-                               lappend_oid(istmt.grantees,
-                                                       get_role_oid(grantee->rolname, false));
+               switch (grantee->roletype)
+               {
+                       case ROLESPEC_PUBLIC:
+                               grantee_uid = ACL_ID_PUBLIC;
+                               break;
+                       default:
+                               grantee_uid = get_rolespec_oid((Node *) grantee, false);
+                               break;
+               }
+               istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
        }
 
        /*
@@ -904,22 +907,25 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
        iacls.behavior = action->behavior;
 
        /*
-        * Convert the PrivGrantee list into an Oid list.  Note that at this point
-        * we insert an ACL_ID_PUBLIC into the list if an empty role name is
-        * detected (which is what the grammar uses if PUBLIC is found), so
-        * downstream there shouldn't be any additional work needed to support
-        * this case.
+        * Convert the RoleSpec list into an Oid list.  Note that at this point
+        * we insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
+        * there shouldn't be any additional work needed to support this case.
         */
        foreach(cell, action->grantees)
        {
-               PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
+               RoleSpec *grantee = (RoleSpec *) lfirst(cell);
+               Oid grantee_uid;
 
-               if (grantee->rolname == NULL)
-                       iacls.grantees = lappend_oid(iacls.grantees, ACL_ID_PUBLIC);
-               else
-                       iacls.grantees =
-                               lappend_oid(iacls.grantees,
-                                                       get_role_oid(grantee->rolname, false));
+               switch (grantee->roletype)
+               {
+                       case ROLESPEC_PUBLIC:
+                               grantee_uid = ACL_ID_PUBLIC;
+                               break;
+                       default:
+                               grantee_uid = get_rolespec_oid((Node *) grantee, false);
+                               break;
+               }
+               iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
        }
 
        /*
index 59aacef7ea947efeb7f78a0368463d777195f0ac..3ddd7ec4343219de616e17bab26324bce391b17d 100644 (file)
@@ -699,7 +699,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
 ObjectAddress
 ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
 {
-       Oid                     newowner = get_role_oid(stmt->newowner, false);
+       Oid                     newowner = get_rolespec_oid(stmt->newowner, false);
 
        switch (stmt->objectType)
        {
index aa733575e46796bd60f1df2342a37f21d8bd4681..5cc74d03c11a3aac696eb98393b0d7e0707133e5 100644 (file)
@@ -1371,7 +1371,7 @@ CreateExtension(CreateExtensionStmt *stmt)
                        CreateSchemaStmt *csstmt = makeNode(CreateSchemaStmt);
 
                        csstmt->schemaname = schemaName;
-                       csstmt->authid = NULL;          /* will be created by current user */
+                       csstmt->authrole = NULL;        /* will be created by current user */
                        csstmt->schemaElts = NIL;
                        csstmt->if_not_exists = false;
                        CreateSchemaCommand(csstmt, NULL);
index bd4839189e6efb2a16ddee0b38c7b7633ae0406e..3b85c2c017eec93d1ecba3385173611bd3c8e420 100644 (file)
@@ -197,24 +197,6 @@ transformGenericOptions(Oid catalogId,
 }
 
 
-/*
- * Convert the user mapping user name to OID
- */
-static Oid
-GetUserOidFromMapping(const char *username, bool missing_ok)
-{
-       if (!username)
-               /* PUBLIC user mapping */
-               return InvalidOid;
-
-       if (strcmp(username, "current_user") == 0)
-               /* map to the owner */
-               return GetUserId();
-
-       /* map to provided user */
-       return get_role_oid(username, missing_ok);
-}
-
 /*
  * Internal workhorse for changing a data wrapper's owner.
  *
@@ -1156,10 +1138,14 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
        ObjectAddress referenced;
        ForeignServer *srv;
        ForeignDataWrapper *fdw;
+       RoleSpec   *role = (RoleSpec *) stmt->user;
 
        rel = heap_open(UserMappingRelationId, RowExclusiveLock);
 
-       useId = GetUserOidFromMapping(stmt->username, false);
+       if (role->roletype == ROLESPEC_PUBLIC)
+               useId = ACL_ID_PUBLIC;
+       else
+               useId = get_rolespec_oid(stmt->user, false);
 
        /* Check that the server exists. */
        srv = GetForeignServerByName(stmt->servername, false);
@@ -1252,10 +1238,15 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
        Oid                     umId;
        ForeignServer *srv;
        ObjectAddress address;
+       RoleSpec   *role = (RoleSpec *) stmt->user;
 
        rel = heap_open(UserMappingRelationId, RowExclusiveLock);
 
-       useId = GetUserOidFromMapping(stmt->username, false);
+       if (role->roletype == ROLESPEC_PUBLIC)
+               useId = ACL_ID_PUBLIC;
+       else
+               useId = get_rolespec_oid(stmt->user, false);
+
        srv = GetForeignServerByName(stmt->servername, false);
 
        umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
@@ -1338,20 +1329,27 @@ RemoveUserMapping(DropUserMappingStmt *stmt)
        Oid                     useId;
        Oid                     umId;
        ForeignServer *srv;
+       RoleSpec   *role = (RoleSpec *) stmt->user;
 
-       useId = GetUserOidFromMapping(stmt->username, stmt->missing_ok);
-       srv = GetForeignServerByName(stmt->servername, true);
-
-       if (stmt->username && !OidIsValid(useId))
+       if (role->roletype == ROLESPEC_PUBLIC)
+               useId = ACL_ID_PUBLIC;
+       else
        {
-               /*
-                * IF EXISTS specified, role not found and not public. Notice this and
-                * leave.
-                */
-               elog(NOTICE, "role \"%s\" does not exist, skipping", stmt->username);
-               return InvalidOid;
+               useId = get_rolespec_oid(stmt->user, stmt->missing_ok);
+               if (!OidIsValid(useId))
+               {
+                       /*
+                        * IF EXISTS specified, role not found and not public. Notice this
+                        * and leave.
+                        */
+                       elog(NOTICE, "role \"%s\" does not exist, skipping",
+                                role->rolename);
+                       return InvalidOid;
+               }
        }
 
+       srv = GetForeignServerByName(stmt->servername, true);
+
        if (!srv)
        {
                if (!stmt->missing_ok)
index e86299781f960b93c0ee27e6e4fec2047aa873e6..a3d840da5cf7f319f498a6602966022f7ad6cc7b 100644 (file)
@@ -129,13 +129,7 @@ parse_policy_command(const char *cmd_name)
 
 /*
  * policy_role_list_to_array
- *   helper function to convert a list of role names in to an array of
- *   role ids.
- *
- * Note: If PUBLIC is provided as a role name, then ACL_ID_PUBLIC is
- *       used as the role id.
- *
- * roles - the list of role names to convert.
+ *   helper function to convert a list of RoleSpecs to an array of role ids.
  */
 static ArrayType *
 policy_role_list_to_array(List *roles)
@@ -162,25 +156,25 @@ policy_role_list_to_array(List *roles)
 
        foreach(cell, roles)
        {
-               Oid             roleid = get_role_oid_or_public(strVal(lfirst(cell)));
+               RoleSpec *spec = lfirst(cell);
 
                /*
                 * PUBLIC covers all roles, so it only makes sense alone.
                 */
-               if (roleid == ACL_ID_PUBLIC)
+               if (spec->roletype == ROLESPEC_PUBLIC)
                {
                        if (num_roles != 1)
                                ereport(WARNING,
                                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                                 errmsg("ignoring roles specified other than public"),
                                                 errhint("All roles are members of the public role.")));
-
-                       temp_array[0] = ObjectIdGetDatum(roleid);
+                       temp_array[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
                        num_roles = 1;
                        break;
                }
                else
-                       temp_array[i++] = ObjectIdGetDatum(roleid);
+                       temp_array[i++] =
+                               ObjectIdGetDatum(get_rolespec_oid((Node *) spec, false));
        }
 
        role_ids = construct_array(temp_array, num_roles, OIDOID, sizeof(Oid), true,
index 722142e16eaae72b13fb410ff1b63046b75b5911..c090ed220f8ee3d7fc46feec62de249d07e66eef 100644 (file)
@@ -21,6 +21,7 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/pg_authid.h"
 #include "catalog/objectaccess.h"
 #include "catalog/pg_namespace.h"
 #include "commands/dbcommands.h"
@@ -42,8 +43,7 @@ static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerI
 Oid
 CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
 {
-       const char *schemaName = stmt->schemaname;
-       const char *authId = stmt->authid;
+       const char      *schemaName = stmt->schemaname;
        Oid                     namespaceId;
        OverrideSearchPath *overridePath;
        List       *parsetree_list;
@@ -58,11 +58,24 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
        /*
         * Who is supposed to own the new schema?
         */
-       if (authId)
-               owner_uid = get_role_oid(authId, false);
+       if (stmt->authrole)
+               owner_uid = get_rolespec_oid(stmt->authrole, false);
        else
                owner_uid = saved_uid;
 
+       /* fill schema name with the user name if not specified */
+       if (!schemaName)
+       {
+               HeapTuple tuple;
+
+               tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(owner_uid));
+               if (!HeapTupleIsValid(tuple))
+                       elog(ERROR, "cache lookup failed for role %u", owner_uid);
+               schemaName =
+                       pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
+               ReleaseSysCache(tuple);
+       }
+
        /*
         * To create a schema, must have schema-create privilege on the current
         * database and must be able to become the target role (this does not
index 653677892dee133e60cc1ced15cfc6d0be8a5721..623e6bfba81c6ad02284d9984705a4157a550e4b 100644 (file)
@@ -3507,7 +3507,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
                        break;
                case AT_ChangeOwner:    /* ALTER OWNER */
                        ATExecChangeOwner(RelationGetRelid(rel),
-                                                         get_role_oid(cmd->name, false),
+                                                         get_rolespec_oid(cmd->newowner, false),
                                                          false, lockmode);
                        break;
                case AT_ClusterOn:              /* CLUSTER ON */
@@ -9388,7 +9388,7 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
        HeapTuple       tuple;
        Oid                     orig_tablespaceoid;
        Oid                     new_tablespaceoid;
-       List       *role_oids = roleNamesToIds(stmt->roles);
+       List       *role_oids = roleSpecsToIds(stmt->roles);
 
        /* Ensure we were not asked to move something we can't */
        if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
index 68b6917df5dc513b567535d029e79db6a86bbf97..fd226125a93838a74dad709565e6e7ce6bce6bf1 100644 (file)
@@ -252,7 +252,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
 
        /* However, the eventual owner of the tablespace need not be */
        if (stmt->owner)
-               ownerId = get_role_oid(stmt->owner, false);
+               ownerId = get_rolespec_oid(stmt->owner, false);
        else
                ownerId = GetUserId();
 
index 0ba7ba0c20f88928d9f42531aa6631bde08e38e9..c14465eb87b6dfc9a73a6abed848a29bc8eac280 100644 (file)
@@ -49,10 +49,10 @@ extern bool Password_encryption;
 check_password_hook_type check_password_hook = NULL;
 
 static void AddRoleMems(const char *rolename, Oid roleid,
-                       List *memberNames, List *memberIds,
+                       List *memberSpecs, List *memberIds,
                        Oid grantorId, bool admin_opt);
 static void DelRoleMems(const char *rolename, Oid roleid,
-                       List *memberNames, List *memberIds,
+                       List *memberSpecs, List *memberIds,
                        bool admin_opt);
 
 
@@ -443,10 +443,10 @@ CreateRole(CreateRoleStmt *stmt)
         * option, rolemembers don't.
         */
        AddRoleMems(stmt->role, roleid,
-                               adminmembers, roleNamesToIds(adminmembers),
+                               adminmembers, roleSpecsToIds(adminmembers),
                                GetUserId(), true);
        AddRoleMems(stmt->role, roleid,
-                               rolemembers, roleNamesToIds(rolemembers),
+                               rolemembers, roleSpecsToIds(rolemembers),
                                GetUserId(), false);
 
        /* Post creation hook for new role */
@@ -478,7 +478,9 @@ AlterRole(AlterRoleStmt *stmt)
        TupleDesc       pg_authid_dsc;
        HeapTuple       tuple,
                                new_tuple;
+       Form_pg_authid authform;
        ListCell   *option;
+       char       *rolename = NULL;
        char       *password = NULL;    /* user password */
        bool            encrypt_password = Password_encryption; /* encrypt password? */
        char            encrypted_password[MD5_PASSWD_LEN + 1];
@@ -647,33 +649,30 @@ AlterRole(AlterRoleStmt *stmt)
        pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);
        pg_authid_dsc = RelationGetDescr(pg_authid_rel);
 
-       tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("role \"%s\" does not exist", stmt->role)));
-
+       tuple = get_rolespec_tuple(stmt->role);
+       authform = (Form_pg_authid) GETSTRUCT(tuple);
+       rolename = pstrdup(NameStr(authform->rolname));
        roleid = HeapTupleGetOid(tuple);
 
        /*
         * To mess with a superuser you gotta be superuser; else you need
         * createrole, or just want to change your own password
         */
-       if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper || issuper >= 0)
+       if (authform->rolsuper || issuper >= 0)
        {
                if (!superuser())
                        ereport(ERROR,
                                        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                         errmsg("must be superuser to alter superusers")));
        }
-       else if (((Form_pg_authid) GETSTRUCT(tuple))->rolreplication || isreplication >= 0)
+       else if (authform->rolreplication || isreplication >= 0)
        {
                if (!superuser())
                        ereport(ERROR,
                                        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                         errmsg("must be superuser to alter replication users")));
        }
-       else if (((Form_pg_authid) GETSTRUCT(tuple))->rolbypassrls || bypassrls >= 0)
+       else if (authform->rolbypassrls || bypassrls >= 0)
        {
                if (!superuser())
                        ereport(ERROR,
@@ -718,11 +717,11 @@ AlterRole(AlterRoleStmt *stmt)
         * Call the password checking hook if there is one defined
         */
        if (check_password_hook && password)
-               (*check_password_hook) (stmt->role,
-                                                               password,
-                          isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
-                                                               validUntil_datum,
-                                                               validUntil_null);
+               (*check_password_hook)(rolename ,
+                                                          password,
+                        isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
+                                                          validUntil_datum,
+                                                          validUntil_null);
 
        /*
         * Build an updated tuple, perusing the information just obtained
@@ -784,7 +783,7 @@ AlterRole(AlterRoleStmt *stmt)
                                CStringGetTextDatum(password);
                else
                {
-                       if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role),
+                       if (!pg_md5_encrypt(password, rolename, strlen(rolename),
                                                                encrypted_password))
                                elog(ERROR, "password encryption failed");
                        new_record[Anum_pg_authid_rolpassword - 1] =
@@ -831,12 +830,12 @@ AlterRole(AlterRoleStmt *stmt)
                CommandCounterIncrement();
 
        if (stmt->action == +1)         /* add members to role */
-               AddRoleMems(stmt->role, roleid,
-                                       rolemembers, roleNamesToIds(rolemembers),
+               AddRoleMems(rolename, roleid,
+                                       rolemembers, roleSpecsToIds(rolemembers),
                                        GetUserId(), false);
        else if (stmt->action == -1)    /* drop members from role */
-               DelRoleMems(stmt->role, roleid,
-                                       rolemembers, roleNamesToIds(rolemembers),
+               DelRoleMems(rolename, roleid,
+                                       rolemembers, roleSpecsToIds(rolemembers),
                                        false);
 
        /*
@@ -860,13 +859,7 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
 
        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)));
-
+               roletuple = get_rolespec_tuple(stmt->role);
                roleid = HeapTupleGetOid(roletuple);
 
                /*
@@ -955,7 +948,8 @@ DropRole(DropRoleStmt *stmt)
 
        foreach(item, stmt->roles)
        {
-               const char *role = strVal(lfirst(item));
+               RoleSpec   *rolspec = lfirst(item);
+               char       *role;
                HeapTuple       tuple,
                                        tmp_tuple;
                ScanKeyData scankey;
@@ -964,6 +958,12 @@ DropRole(DropRoleStmt *stmt)
                SysScanDesc sscan;
                Oid                     roleid;
 
+               if (rolspec->roletype != ROLESPEC_CSTRING)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("cannot use special role specifier in \"%s\"", "DROP ROLE")));
+               role = rolspec->rolename;
+
                tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
                if (!HeapTupleIsValid(tuple))
                {
@@ -1233,11 +1233,11 @@ GrantRole(GrantRoleStmt *stmt)
        ListCell   *item;
 
        if (stmt->grantor)
-               grantor = get_role_oid(stmt->grantor, false);
+               grantor = get_rolespec_oid(stmt->grantor, false);
        else
                grantor = GetUserId();
 
-       grantee_ids = roleNamesToIds(stmt->grantee_roles);
+       grantee_ids = roleSpecsToIds(stmt->grantee_roles);
 
        /* AccessShareLock is enough since we aren't modifying pg_authid */
        pg_authid_rel = heap_open(AuthIdRelationId, AccessShareLock);
@@ -1286,7 +1286,7 @@ GrantRole(GrantRoleStmt *stmt)
 void
 DropOwnedObjects(DropOwnedStmt *stmt)
 {
-       List       *role_ids = roleNamesToIds(stmt->roles);
+       List       *role_ids = roleSpecsToIds(stmt->roles);
        ListCell   *cell;
 
        /* Check privileges */
@@ -1312,7 +1312,7 @@ DropOwnedObjects(DropOwnedStmt *stmt)
 void
 ReassignOwnedObjects(ReassignOwnedStmt *stmt)
 {
-       List       *role_ids = roleNamesToIds(stmt->roles);
+       List       *role_ids = roleSpecsToIds(stmt->roles);
        ListCell   *cell;
        Oid                     newrole;
 
@@ -1328,7 +1328,7 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
        }
 
        /* Must have privileges on the receiving side too */
-       newrole = get_role_oid(stmt->newrole, false);
+       newrole = get_rolespec_oid(stmt->newrole, false);
 
        if (!has_privs_of_role(GetUserId(), newrole))
                ereport(ERROR,
@@ -1340,22 +1340,24 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
 }
 
 /*
- * roleNamesToIds
+ * roleSpecsToIds
+ *
+ * Given a list of RoleSpecs, generate a list of role OIDs in the same order.
  *
- * Given a list of role names (as String nodes), generate a list of role OIDs
- * in the same order.
+ * ROLESPEC_PUBLIC is not allowed.
  */
 List *
-roleNamesToIds(List *memberNames)
+roleSpecsToIds(List *memberNames)
 {
        List       *result = NIL;
        ListCell   *l;
 
        foreach(l, memberNames)
        {
-               char       *rolename = strVal(lfirst(l));
-               Oid                     roleid = get_role_oid(rolename, false);
+               Node   *rolespec = (Node *) lfirst(l);
+               Oid             roleid;
 
+               roleid = get_rolespec_oid(rolespec, false);
                result = lappend_oid(result, roleid);
        }
        return result;
@@ -1366,7 +1368,7 @@ roleNamesToIds(List *memberNames)
  *
  * rolename: name of role to add to (used only for error messages)
  * roleid: OID of role to add to
- * memberNames: list of names of roles to add (used only for error messages)
+ * memberSpecs: list of RoleSpec of roles to add (used only for error messages)
  * memberIds: OIDs of roles to add
  * grantorId: who is granting the membership
  * admin_opt: granting admin option?
@@ -1375,15 +1377,15 @@ roleNamesToIds(List *memberNames)
  */
 static void
 AddRoleMems(const char *rolename, Oid roleid,
-                       List *memberNames, List *memberIds,
+                       List *memberSpecs, List *memberIds,
                        Oid grantorId, bool admin_opt)
 {
        Relation        pg_authmem_rel;
        TupleDesc       pg_authmem_dsc;
-       ListCell   *nameitem;
+       ListCell   *specitem;
        ListCell   *iditem;
 
-       Assert(list_length(memberNames) == list_length(memberIds));
+       Assert(list_length(memberSpecs) == list_length(memberIds));
 
        /* Skip permission check if nothing to do */
        if (!memberIds)
@@ -1428,9 +1430,9 @@ AddRoleMems(const char *rolename, Oid roleid,
        pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
        pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
 
-       forboth(nameitem, memberNames, iditem, memberIds)
+       forboth(specitem, memberSpecs, iditem, memberIds)
        {
-               const char *membername = strVal(lfirst(nameitem));
+               RoleSpec   *memberRole = lfirst(specitem);
                Oid                     memberid = lfirst_oid(iditem);
                HeapTuple       authmem_tuple;
                HeapTuple       tuple;
@@ -1449,7 +1451,7 @@ AddRoleMems(const char *rolename, Oid roleid,
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                                         (errmsg("role \"%s\" is a member of role \"%s\"",
-                                                        rolename, membername))));
+                                                        rolename, get_rolespec_name((Node *) memberRole)))));
 
                /*
                 * Check if entry for this role/member already exists; if so, give
@@ -1464,7 +1466,7 @@ AddRoleMems(const char *rolename, Oid roleid,
                {
                        ereport(NOTICE,
                                        (errmsg("role \"%s\" is already a member of role \"%s\"",
-                                                       membername, rolename)));
+                                                       get_rolespec_name((Node *) memberRole), rolename)));
                        ReleaseSysCache(authmem_tuple);
                        continue;
                }
@@ -1513,7 +1515,7 @@ AddRoleMems(const char *rolename, Oid roleid,
  *
  * rolename: name of role to del from (used only for error messages)
  * roleid: OID of role to del from
- * memberNames: list of names of roles to del (used only for error messages)
+ * memberSpecs: list of RoleSpec of roles to del (used only for error messages)
  * memberIds: OIDs of roles to del
  * admin_opt: remove admin option only?
  *
@@ -1521,15 +1523,15 @@ AddRoleMems(const char *rolename, Oid roleid,
  */
 static void
 DelRoleMems(const char *rolename, Oid roleid,
-                       List *memberNames, List *memberIds,
+                       List *memberSpecs, List *memberIds,
                        bool admin_opt)
 {
        Relation        pg_authmem_rel;
        TupleDesc       pg_authmem_dsc;
-       ListCell   *nameitem;
+       ListCell   *specitem;
        ListCell   *iditem;
 
-       Assert(list_length(memberNames) == list_length(memberIds));
+       Assert(list_length(memberSpecs) == list_length(memberIds));
 
        /* Skip permission check if nothing to do */
        if (!memberIds)
@@ -1559,9 +1561,9 @@ DelRoleMems(const char *rolename, Oid roleid,
        pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
        pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
 
-       forboth(nameitem, memberNames, iditem, memberIds)
+       forboth(specitem, memberSpecs, iditem, memberIds)
        {
-               const char *membername = strVal(lfirst(nameitem));
+               RoleSpec   *memberRole = lfirst(specitem);
                Oid                     memberid = lfirst_oid(iditem);
                HeapTuple       authmem_tuple;
 
@@ -1575,7 +1577,7 @@ DelRoleMems(const char *rolename, Oid roleid,
                {
                        ereport(WARNING,
                                        (errmsg("role \"%s\" is not a member of role \"%s\"",
-                                                       membername, rolename)));
+                                                       get_rolespec_name((Node *) memberRole), rolename)));
                        continue;
                }
 
index 9fe80080f31884b5153658f988e3a3d80351e134..ebb6f3a49b74d68b82f0bf592f1af2cb69ef7ac7 100644 (file)
@@ -2504,6 +2504,18 @@ _copyXmlSerialize(const XmlSerialize *from)
        return newnode;
 }
 
+static RoleSpec *
+_copyRoleSpec(const RoleSpec *from)
+{
+       RoleSpec *newnode = makeNode(RoleSpec);
+
+       COPY_SCALAR_FIELD(roletype);
+       COPY_STRING_FIELD(rolename);
+       COPY_LOCATION_FIELD(location);
+
+       return newnode;
+}
+
 static Query *
 _copyQuery(const Query *from)
 {
@@ -2650,6 +2662,7 @@ _copyAlterTableCmd(const AlterTableCmd *from)
 
        COPY_SCALAR_FIELD(subtype);
        COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(newowner);
        COPY_NODE_FIELD(def);
        COPY_SCALAR_FIELD(behavior);
        COPY_SCALAR_FIELD(missing_ok);
@@ -2689,16 +2702,6 @@ _copyGrantStmt(const GrantStmt *from)
        return newnode;
 }
 
-static PrivGrantee *
-_copyPrivGrantee(const PrivGrantee *from)
-{
-       PrivGrantee *newnode = makeNode(PrivGrantee);
-
-       COPY_STRING_FIELD(rolname);
-
-       return newnode;
-}
-
 static FuncWithArgs *
 _copyFuncWithArgs(const FuncWithArgs *from)
 {
@@ -2730,7 +2733,7 @@ _copyGrantRoleStmt(const GrantRoleStmt *from)
        COPY_NODE_FIELD(grantee_roles);
        COPY_SCALAR_FIELD(is_grant);
        COPY_SCALAR_FIELD(admin_opt);
-       COPY_STRING_FIELD(grantor);
+       COPY_NODE_FIELD(grantor);
        COPY_SCALAR_FIELD(behavior);
 
        return newnode;
@@ -3038,7 +3041,7 @@ _copyAlterOwnerStmt(const AlterOwnerStmt *from)
        COPY_NODE_FIELD(relation);
        COPY_NODE_FIELD(object);
        COPY_NODE_FIELD(objarg);
-       COPY_STRING_FIELD(newowner);
+       COPY_NODE_FIELD(newowner);
 
        return newnode;
 }
@@ -3424,7 +3427,7 @@ _copyCreateTableSpaceStmt(const CreateTableSpaceStmt *from)
        CreateTableSpaceStmt *newnode = makeNode(CreateTableSpaceStmt);
 
        COPY_STRING_FIELD(tablespacename);
-       COPY_STRING_FIELD(owner);
+       COPY_NODE_FIELD(owner);
        COPY_STRING_FIELD(location);
        COPY_NODE_FIELD(options);
 
@@ -3561,7 +3564,7 @@ _copyCreateUserMappingStmt(const CreateUserMappingStmt *from)
 {
        CreateUserMappingStmt *newnode = makeNode(CreateUserMappingStmt);
 
-       COPY_STRING_FIELD(username);
+       COPY_NODE_FIELD(user);
        COPY_STRING_FIELD(servername);
        COPY_NODE_FIELD(options);
 
@@ -3573,7 +3576,7 @@ _copyAlterUserMappingStmt(const AlterUserMappingStmt *from)
 {
        AlterUserMappingStmt *newnode = makeNode(AlterUserMappingStmt);
 
-       COPY_STRING_FIELD(username);
+       COPY_NODE_FIELD(user);
        COPY_STRING_FIELD(servername);
        COPY_NODE_FIELD(options);
 
@@ -3585,7 +3588,7 @@ _copyDropUserMappingStmt(const DropUserMappingStmt *from)
 {
        DropUserMappingStmt *newnode = makeNode(DropUserMappingStmt);
 
-       COPY_STRING_FIELD(username);
+       COPY_NODE_FIELD(user);
        COPY_STRING_FIELD(servername);
        COPY_SCALAR_FIELD(missing_ok);
 
@@ -3698,7 +3701,7 @@ _copyAlterRoleStmt(const AlterRoleStmt *from)
 {
        AlterRoleStmt *newnode = makeNode(AlterRoleStmt);
 
-       COPY_STRING_FIELD(role);
+       COPY_NODE_FIELD(role);
        COPY_NODE_FIELD(options);
        COPY_SCALAR_FIELD(action);
 
@@ -3710,7 +3713,7 @@ _copyAlterRoleSetStmt(const AlterRoleSetStmt *from)
 {
        AlterRoleSetStmt *newnode = makeNode(AlterRoleSetStmt);
 
-       COPY_STRING_FIELD(role);
+       COPY_NODE_FIELD(role);
        COPY_STRING_FIELD(database);
        COPY_NODE_FIELD(setstmt);
 
@@ -3769,7 +3772,7 @@ _copyCreateSchemaStmt(const CreateSchemaStmt *from)
        CreateSchemaStmt *newnode = makeNode(CreateSchemaStmt);
 
        COPY_STRING_FIELD(schemaname);
-       COPY_STRING_FIELD(authid);
+       COPY_NODE_FIELD(authrole);
        COPY_NODE_FIELD(schemaElts);
        COPY_SCALAR_FIELD(if_not_exists);
 
@@ -3854,7 +3857,7 @@ _copyReassignOwnedStmt(const ReassignOwnedStmt *from)
        ReassignOwnedStmt *newnode = makeNode(ReassignOwnedStmt);
 
        COPY_NODE_FIELD(roles);
-       COPY_STRING_FIELD(newrole);
+       COPY_NODE_FIELD(newrole);
 
        return newnode;
 }
@@ -4728,9 +4731,6 @@ copyObject(const void *from)
                case T_CommonTableExpr:
                        retval = _copyCommonTableExpr(from);
                        break;
-               case T_PrivGrantee:
-                       retval = _copyPrivGrantee(from);
-                       break;
                case T_FuncWithArgs:
                        retval = _copyFuncWithArgs(from);
                        break;
@@ -4740,6 +4740,9 @@ copyObject(const void *from)
                case T_XmlSerialize:
                        retval = _copyXmlSerialize(from);
                        break;
+               case T_RoleSpec:
+                       retval = _copyRoleSpec(from);
+                       break;
 
                default:
                        elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from));
index fe509b0ad1cb3d43a57e73f5c2803d1077d0919c..8186e84d3395ee6e3f1cd0d40f092402bef99e31 100644 (file)
@@ -973,6 +973,7 @@ _equalAlterTableCmd(const AlterTableCmd *a, const AlterTableCmd *b)
 {
        COMPARE_SCALAR_FIELD(subtype);
        COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(newowner);
        COMPARE_NODE_FIELD(def);
        COMPARE_SCALAR_FIELD(behavior);
        COMPARE_SCALAR_FIELD(missing_ok);
@@ -1008,14 +1009,6 @@ _equalGrantStmt(const GrantStmt *a, const GrantStmt *b)
        return true;
 }
 
-static bool
-_equalPrivGrantee(const PrivGrantee *a, const PrivGrantee *b)
-{
-       COMPARE_STRING_FIELD(rolname);
-
-       return true;
-}
-
 static bool
 _equalFuncWithArgs(const FuncWithArgs *a, const FuncWithArgs *b)
 {
@@ -1041,7 +1034,7 @@ _equalGrantRoleStmt(const GrantRoleStmt *a, const GrantRoleStmt *b)
        COMPARE_NODE_FIELD(grantee_roles);
        COMPARE_SCALAR_FIELD(is_grant);
        COMPARE_SCALAR_FIELD(admin_opt);
-       COMPARE_STRING_FIELD(grantor);
+       COMPARE_NODE_FIELD(grantor);
        COMPARE_SCALAR_FIELD(behavior);
 
        return true;
@@ -1295,7 +1288,7 @@ _equalAlterOwnerStmt(const AlterOwnerStmt *a, const AlterOwnerStmt *b)
        COMPARE_NODE_FIELD(relation);
        COMPARE_NODE_FIELD(object);
        COMPARE_NODE_FIELD(objarg);
-       COMPARE_STRING_FIELD(newowner);
+       COMPARE_NODE_FIELD(newowner);
 
        return true;
 }
@@ -1618,7 +1611,7 @@ static bool
 _equalCreateTableSpaceStmt(const CreateTableSpaceStmt *a, const CreateTableSpaceStmt *b)
 {
        COMPARE_STRING_FIELD(tablespacename);
-       COMPARE_STRING_FIELD(owner);
+       COMPARE_NODE_FIELD(owner);
        COMPARE_STRING_FIELD(location);
        COMPARE_NODE_FIELD(options);
 
@@ -1735,7 +1728,7 @@ _equalAlterForeignServerStmt(const AlterForeignServerStmt *a, const AlterForeign
 static bool
 _equalCreateUserMappingStmt(const CreateUserMappingStmt *a, const CreateUserMappingStmt *b)
 {
-       COMPARE_STRING_FIELD(username);
+       COMPARE_NODE_FIELD(user);
        COMPARE_STRING_FIELD(servername);
        COMPARE_NODE_FIELD(options);
 
@@ -1745,7 +1738,7 @@ _equalCreateUserMappingStmt(const CreateUserMappingStmt *a, const CreateUserMapp
 static bool
 _equalAlterUserMappingStmt(const AlterUserMappingStmt *a, const AlterUserMappingStmt *b)
 {
-       COMPARE_STRING_FIELD(username);
+       COMPARE_NODE_FIELD(user);
        COMPARE_STRING_FIELD(servername);
        COMPARE_NODE_FIELD(options);
 
@@ -1755,7 +1748,7 @@ _equalAlterUserMappingStmt(const AlterUserMappingStmt *a, const AlterUserMapping
 static bool
 _equalDropUserMappingStmt(const DropUserMappingStmt *a, const DropUserMappingStmt *b)
 {
-       COMPARE_STRING_FIELD(username);
+       COMPARE_NODE_FIELD(user);
        COMPARE_STRING_FIELD(servername);
        COMPARE_SCALAR_FIELD(missing_ok);
 
@@ -1853,7 +1846,7 @@ _equalCreateRoleStmt(const CreateRoleStmt *a, const CreateRoleStmt *b)
 static bool
 _equalAlterRoleStmt(const AlterRoleStmt *a, const AlterRoleStmt *b)
 {
-       COMPARE_STRING_FIELD(role);
+       COMPARE_NODE_FIELD(role);
        COMPARE_NODE_FIELD(options);
        COMPARE_SCALAR_FIELD(action);
 
@@ -1863,7 +1856,7 @@ _equalAlterRoleStmt(const AlterRoleStmt *a, const AlterRoleStmt *b)
 static bool
 _equalAlterRoleSetStmt(const AlterRoleSetStmt *a, const AlterRoleSetStmt *b)
 {
-       COMPARE_STRING_FIELD(role);
+       COMPARE_NODE_FIELD(role);
        COMPARE_STRING_FIELD(database);
        COMPARE_NODE_FIELD(setstmt);
 
@@ -1912,7 +1905,7 @@ static bool
 _equalCreateSchemaStmt(const CreateSchemaStmt *a, const CreateSchemaStmt *b)
 {
        COMPARE_STRING_FIELD(schemaname);
-       COMPARE_STRING_FIELD(authid);
+       COMPARE_NODE_FIELD(authrole);
        COMPARE_NODE_FIELD(schemaElts);
        COMPARE_SCALAR_FIELD(if_not_exists);
 
@@ -1983,7 +1976,7 @@ static bool
 _equalReassignOwnedStmt(const ReassignOwnedStmt *a, const ReassignOwnedStmt *b)
 {
        COMPARE_NODE_FIELD(roles);
-       COMPARE_STRING_FIELD(newrole);
+       COMPARE_NODE_FIELD(newrole);
 
        return true;
 }
@@ -2455,6 +2448,16 @@ _equalXmlSerialize(const XmlSerialize *a, const XmlSerialize *b)
        return true;
 }
 
+static bool
+_equalRoleSpec(const RoleSpec *a, const RoleSpec *b)
+{
+       COMPARE_SCALAR_FIELD(roletype);
+       COMPARE_STRING_FIELD(rolename);
+       COMPARE_LOCATION_FIELD(location);
+
+       return true;
+}
+
 /*
  * Stuff from pg_list.h
  */
@@ -3153,9 +3156,6 @@ equal(const void *a, const void *b)
                case T_CommonTableExpr:
                        retval = _equalCommonTableExpr(a, b);
                        break;
-               case T_PrivGrantee:
-                       retval = _equalPrivGrantee(a, b);
-                       break;
                case T_FuncWithArgs:
                        retval = _equalFuncWithArgs(a, b);
                        break;
@@ -3165,6 +3165,9 @@ equal(const void *a, const void *b)
                case T_XmlSerialize:
                        retval = _equalXmlSerialize(a, b);
                        break;
+               case T_RoleSpec:
+                       retval = _equalRoleSpec(a, b);
+                       break;
 
                default:
                        elog(ERROR, "unrecognized node type: %d",
index 581f7a1c1c64fa20687a372740770345fef35992..435c0451cae194bb784fb76ac148f9f30957ee56 100644 (file)
@@ -143,6 +143,7 @@ static Node *makeBitStringConst(char *str, int location);
 static Node *makeNullAConst(int location);
 static Node *makeAConst(Value *v, int location);
 static Node *makeBoolAConst(bool state, int location);
+static Node *makeRoleSpec(RoleSpecType type, int location);
 static void check_qualified_name(List *names, core_yyscan_t yyscanner);
 static List *check_func_name(List *names, core_yyscan_t yyscanner);
 static List *check_indirection(List *indirection, core_yyscan_t yyscanner);
@@ -291,7 +292,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 %type <str>            opt_type
 %type <str>            foreign_server_version opt_foreign_server_version
-%type <str>            auth_ident
 %type <str>            opt_in_database
 
 %type <str>            OptSchemaName
@@ -474,12 +474,13 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 %type <ival>   Iconst SignedIconst
 %type <str>            Sconst comment_text notify_payload
-%type <str>            RoleId opt_granted_by opt_boolean_or_string
+%type <str>            RoleId opt_boolean_or_string
 %type <list>   var_list
 %type <str>            ColId ColLabel var_name type_function_name param_name
 %type <str>            NonReservedWord NonReservedWord_or_Sconst
 %type <str>            createdb_opt_name
 %type <node>   var_value zone_value
+%type <node>   auth_ident RoleSpec opt_granted_by
 
 %type <keyword> unreserved_keyword type_func_name_keyword
 %type <keyword> col_name_keyword reserved_keyword
@@ -494,7 +495,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 %type <list>   constraints_set_list
 %type <boolean> constraints_set_mode
-%type <str>            OptTableSpace OptConsTableSpace OptTableSpaceOwner
+%type <str>            OptTableSpace OptConsTableSpace
+%type <node>   OptTableSpaceOwner
 %type <ival>   opt_check_option
 
 %type <str>            opt_provider security_label
@@ -1037,7 +1039,7 @@ CreateUserStmt:
  *****************************************************************************/
 
 AlterRoleStmt:
-                       ALTER ROLE RoleId opt_with AlterOptRoleList
+                       ALTER ROLE RoleSpec opt_with AlterOptRoleList
                                 {
                                        AlterRoleStmt *n = makeNode(AlterRoleStmt);
                                        n->role = $3;
@@ -1053,7 +1055,7 @@ opt_in_database:
                ;
 
 AlterRoleSetStmt:
-                       ALTER ROLE RoleId opt_in_database SetResetClause
+                       ALTER ROLE RoleSpec opt_in_database SetResetClause
                                {
                                        AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
                                        n->role = $3;
@@ -1079,7 +1081,7 @@ AlterRoleSetStmt:
  *****************************************************************************/
 
 AlterUserStmt:
-                       ALTER USER RoleId opt_with AlterOptRoleList
+                       ALTER USER RoleSpec opt_with AlterOptRoleList
                                 {
                                        AlterRoleStmt *n = makeNode(AlterRoleStmt);
                                        n->role = $3;
@@ -1091,7 +1093,7 @@ AlterUserStmt:
 
 
 AlterUserSetStmt:
-                       ALTER USER RoleId SetResetClause
+                       ALTER USER RoleSpec SetResetClause
                                {
                                        AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
                                        n->role = $3;
@@ -1180,7 +1182,7 @@ CreateGroupStmt:
  *****************************************************************************/
 
 AlterGroupStmt:
-                       ALTER GROUP_P RoleId add_drop USER role_list
+                       ALTER GROUP_P RoleSpec add_drop USER role_list
                                {
                                        AlterRoleStmt *n = makeNode(AlterRoleStmt);
                                        n->role = $3;
@@ -1228,15 +1230,12 @@ DropGroupStmt:
  *****************************************************************************/
 
 CreateSchemaStmt:
-                       CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList
+                       CREATE SCHEMA OptSchemaName AUTHORIZATION RoleSpec OptSchemaEltList
                                {
                                        CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
                                        /* One can omit the schema name or the authorization id. */
-                                       if ($3 != NULL)
-                                               n->schemaname = $3;
-                                       else
-                                               n->schemaname = $5;
-                                       n->authid = $5;
+                                       n->schemaname = $3;
+                                       n->authrole = $5;
                                        n->schemaElts = $6;
                                        n->if_not_exists = false;
                                        $$ = (Node *)n;
@@ -1246,20 +1245,17 @@ CreateSchemaStmt:
                                        CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
                                        /* ...but not both */
                                        n->schemaname = $3;
-                                       n->authid = NULL;
+                                       n->authrole = NULL;
                                        n->schemaElts = $4;
                                        n->if_not_exists = false;
                                        $$ = (Node *)n;
                                }
-                       | CREATE SCHEMA IF_P NOT EXISTS OptSchemaName AUTHORIZATION RoleId OptSchemaEltList
+                       | CREATE SCHEMA IF_P NOT EXISTS OptSchemaName AUTHORIZATION RoleSpec OptSchemaEltList
                                {
                                        CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
-                                       /* One can omit the schema name or the authorization id. */
-                                       if ($6 != NULL)
-                                               n->schemaname = $6;
-                                       else
-                                               n->schemaname = $8;
-                                       n->authid = $8;
+                                       /* schema name can be omitted here, too */
+                                       n->schemaname = $6;
+                                       n->authrole = $8;
                                        if ($9 != NIL)
                                                ereport(ERROR,
                                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1272,9 +1268,9 @@ CreateSchemaStmt:
                        | CREATE SCHEMA IF_P NOT EXISTS ColId OptSchemaEltList
                                {
                                        CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
-                                       /* ...but not both */
+                                       /* ...but not here */
                                        n->schemaname = $6;
-                                       n->authid = NULL;
+                                       n->authrole = NULL;
                                        if ($7 != NIL)
                                                ereport(ERROR,
                                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -2259,12 +2255,12 @@ alter_table_cmd:
                                        n->subtype = AT_DropOf;
                                        $$ = (Node *)n;
                                }
-                       /* ALTER TABLE <name> OWNER TO RoleId */
-                       | OWNER TO RoleId
+                       /* ALTER TABLE <name> OWNER TO RoleSpec */
+                       | OWNER TO RoleSpec
                                {
                                        AlterTableCmd *n = makeNode(AlterTableCmd);
                                        n->subtype = AT_ChangeOwner;
-                                       n->name = $3;
+                                       n->newowner = $3;
                                        $$ = (Node *)n;
                                }
                        /* ALTER TABLE <name> SET TABLESPACE <tablespacename> */
@@ -3756,7 +3752,7 @@ CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst
                                }
                ;
 
-OptTableSpaceOwner: OWNER name                 { $$ = $2; }
+OptTableSpaceOwner: OWNER RoleSpec             { $$ = $2; }
                        | /*EMPTY */                            { $$ = NULL; }
                ;
 
@@ -4478,7 +4474,7 @@ import_qualification:
 CreateUserMappingStmt: CREATE USER MAPPING FOR auth_ident SERVER name create_generic_options
                                {
                                        CreateUserMappingStmt *n = makeNode(CreateUserMappingStmt);
-                                       n->username = $5;
+                                       n->user = $5;
                                        n->servername = $7;
                                        n->options = $8;
                                        $$ = (Node *) n;
@@ -4486,10 +4482,8 @@ CreateUserMappingStmt: CREATE USER MAPPING FOR auth_ident SERVER name create_gen
                ;
 
 /* User mapping authorization identifier */
-auth_ident:
-                       CURRENT_USER    { $$ = "current_user"; }
-               |       USER                    { $$ = "current_user"; }
-               |       RoleId                  { $$ = (strcmp($1, "public") == 0) ? NULL : $1; }
+auth_ident: RoleSpec                   { $$ = $1; }
+                       | USER                          { $$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1); }
                ;
 
 /*****************************************************************************
@@ -4502,7 +4496,7 @@ auth_ident:
 DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name
                                {
                                        DropUserMappingStmt *n = makeNode(DropUserMappingStmt);
-                                       n->username = $5;
+                                       n->user = $5;
                                        n->servername = $7;
                                        n->missing_ok = false;
                                        $$ = (Node *) n;
@@ -4510,7 +4504,7 @@ DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name
                                |  DROP USER MAPPING IF_P EXISTS FOR auth_ident SERVER name
                                {
                                        DropUserMappingStmt *n = makeNode(DropUserMappingStmt);
-                                       n->username = $7;
+                                       n->user = $7;
                                        n->servername = $9;
                                        n->missing_ok = true;
                                        $$ = (Node *) n;
@@ -4527,7 +4521,7 @@ DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name
 AlterUserMappingStmt: ALTER USER MAPPING FOR auth_ident SERVER name alter_generic_options
                                {
                                        AlterUserMappingStmt *n = makeNode(AlterUserMappingStmt);
-                                       n->username = $5;
+                                       n->user = $5;
                                        n->servername = $7;
                                        n->options = $8;
                                        $$ = (Node *) n;
@@ -4612,7 +4606,7 @@ RowSecurityOptionalWithCheck:
 
 RowSecurityDefaultToRole:
                        TO role_list                    { $$ = $2; }
-                       | /* EMPTY */                   { $$ = list_make1(makeString("public")); }
+                       | /* EMPTY */                   { $$ = list_make1(makeRoleSpec(ROLESPEC_PUBLIC, -1)); }
                ;
 
 RowSecurityOptionalToRole:
@@ -5432,7 +5426,7 @@ DropOwnedStmt:
                ;
 
 ReassignOwnedStmt:
-                       REASSIGN OWNED BY role_list TO name
+                       REASSIGN OWNED BY role_list TO RoleSpec
                                {
                                        ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt);
                                        n->roles = $4;
@@ -6348,26 +6342,9 @@ grantee_list:
                        | grantee_list ',' grantee                              { $$ = lappend($1, $3); }
                ;
 
-grantee:       RoleId
-                               {
-                                       PrivGrantee *n = makeNode(PrivGrantee);
-                                       /* This hack lets us avoid reserving PUBLIC as a keyword*/
-                                       if (strcmp($1, "public") == 0)
-                                               n->rolname = NULL;
-                                       else
-                                               n->rolname = $1;
-                                       $$ = (Node *)n;
-                               }
-                       | GROUP_P RoleId
-                               {
-                                       PrivGrantee *n = makeNode(PrivGrantee);
-                                       /* Treat GROUP PUBLIC as a synonym for PUBLIC */
-                                       if (strcmp($2, "public") == 0)
-                                               n->rolname = NULL;
-                                       else
-                                               n->rolname = $2;
-                                       $$ = (Node *)n;
-                               }
+grantee:
+                       RoleSpec                                                                { $$ = $1; }
+                       | GROUP_P RoleSpec                                              { $$ = $2; }
                ;
 
 
@@ -6438,7 +6415,7 @@ opt_grant_admin_option: WITH ADMIN OPTION                         { $$ = TRUE; }
                        | /*EMPTY*/                                                                     { $$ = FALSE; }
                ;
 
-opt_granted_by: GRANTED BY RoleId                                              { $$ = $3; }
+opt_granted_by: GRANTED BY RoleSpec                                            { $$ = $3; }
                        | /*EMPTY*/                                                                     { $$ = NULL; }
                ;
 
@@ -8104,7 +8081,7 @@ AlterObjectSchemaStmt:
  *
  *****************************************************************************/
 
-AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
+AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_AGGREGATE;
@@ -8113,7 +8090,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $7;
                                        $$ = (Node *)n;
                                }
-                       | ALTER COLLATION any_name OWNER TO RoleId
+                       | ALTER COLLATION any_name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_COLLATION;
@@ -8121,7 +8098,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER CONVERSION_P any_name OWNER TO RoleId
+                       | ALTER CONVERSION_P any_name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_CONVERSION;
@@ -8129,7 +8106,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER DATABASE database_name OWNER TO RoleId
+                       | ALTER DATABASE database_name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_DATABASE;
@@ -8137,7 +8114,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER DOMAIN_P any_name OWNER TO RoleId
+                       | ALTER DOMAIN_P any_name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_DOMAIN;
@@ -8145,7 +8122,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER FUNCTION function_with_argtypes OWNER TO RoleId
+                       | ALTER FUNCTION function_with_argtypes OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_FUNCTION;
@@ -8154,7 +8131,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER opt_procedural LANGUAGE name OWNER TO RoleId
+                       | ALTER opt_procedural LANGUAGE name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_LANGUAGE;
@@ -8162,7 +8139,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $7;
                                        $$ = (Node *)n;
                                }
-                       | ALTER LARGE_P OBJECT_P NumericOnly OWNER TO RoleId
+                       | ALTER LARGE_P OBJECT_P NumericOnly OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_LARGEOBJECT;
@@ -8170,7 +8147,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $7;
                                        $$ = (Node *)n;
                                }
-                       | ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleId
+                       | ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_OPERATOR;
@@ -8179,7 +8156,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $7;
                                        $$ = (Node *)n;
                                }
-                       | ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleId
+                       | ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_OPCLASS;
@@ -8188,7 +8165,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $9;
                                        $$ = (Node *)n;
                                }
-                       | ALTER OPERATOR FAMILY any_name USING access_method OWNER TO RoleId
+                       | ALTER OPERATOR FAMILY any_name USING access_method OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_OPFAMILY;
@@ -8197,7 +8174,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $9;
                                        $$ = (Node *)n;
                                }
-                       | ALTER SCHEMA name OWNER TO RoleId
+                       | ALTER SCHEMA name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_SCHEMA;
@@ -8205,7 +8182,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER TYPE_P any_name OWNER TO RoleId
+                       | ALTER TYPE_P any_name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_TYPE;
@@ -8213,7 +8190,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER TABLESPACE name OWNER TO RoleId
+                       | ALTER TABLESPACE name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_TABLESPACE;
@@ -8221,7 +8198,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO RoleId
+                       | ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_TSDICTIONARY;
@@ -8229,7 +8206,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $8;
                                        $$ = (Node *)n;
                                }
-                       | ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO RoleId
+                       | ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_TSCONFIGURATION;
@@ -8237,7 +8214,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $8;
                                        $$ = (Node *)n;
                                }
-                       | ALTER FOREIGN DATA_P WRAPPER name OWNER TO RoleId
+                       | ALTER FOREIGN DATA_P WRAPPER name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_FDW;
@@ -8245,7 +8222,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $8;
                                        $$ = (Node *)n;
                                }
-                       | ALTER SERVER name OWNER TO RoleId
+                       | ALTER SERVER name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_FOREIGN_SERVER;
@@ -8253,7 +8230,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                        n->newowner = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER EVENT TRIGGER name OWNER TO RoleId
+                       | ALTER EVENT TRIGGER name OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_EVENT_TRIGGER;
@@ -13113,19 +13090,86 @@ AexprConst: Iconst
 
 Iconst:                ICONST                                                                  { $$ = $1; };
 Sconst:                SCONST                                                                  { $$ = $1; };
-RoleId:                NonReservedWord                                                 { $$ = $1; };
-
-role_list:     RoleId
-                                       { $$ = list_make1(makeString($1)); }
-                       | role_list ',' RoleId
-                                       { $$ = lappend($1, makeString($3)); }
-               ;
 
 SignedIconst: Iconst                                                           { $$ = $1; }
                        | '+' Iconst                                                    { $$ = + $2; }
                        | '-' Iconst                                                    { $$ = - $2; }
                ;
 
+/* Role specifications */
+RoleId:                RoleSpec
+                               {
+                                       RoleSpec *spc = (RoleSpec *) $1;
+                                       switch (spc->roletype)
+                                       {
+                                               case ROLESPEC_CSTRING:
+                                                       $$ = spc->rolename;
+                                                       break;
+                                               case ROLESPEC_PUBLIC:
+                                                       ereport(ERROR,
+                                                                       (errcode(ERRCODE_RESERVED_NAME),
+                                                                        errmsg("role name \"%s\" is reserved",
+                                                                                       "public"),
+                                                                        parser_errposition(@1)));
+                                               case ROLESPEC_SESSION_USER:
+                                                       ereport(ERROR,
+                                                                       (errcode(ERRCODE_RESERVED_NAME),
+                                                                        errmsg("%s cannot be used as a role name",
+                                                                                       "SESSION_USER"),
+                                                                        parser_errposition(@1)));
+                                               case ROLESPEC_CURRENT_USER:
+                                                       ereport(ERROR,
+                                                                       (errcode(ERRCODE_RESERVED_NAME),
+                                                                        errmsg("%s cannot be used as a role name",
+                                                                                       "CURRENT_USER"),
+                                                                        parser_errposition(@1)));
+                                       }
+                               }
+                       ;
+
+RoleSpec:      NonReservedWord
+                                       {
+                                               /*
+                                                * "public" and "none" are not keywords, but they must
+                                                * be treated specially here.
+                                                */
+                                               RoleSpec *n;
+                                               if (strcmp($1, "public") == 0)
+                                               {
+                                                       n = (RoleSpec *) makeRoleSpec(ROLESPEC_PUBLIC, @1);
+                                                       n->roletype = ROLESPEC_PUBLIC;
+                                               }
+                                               else if (strcmp($1, "none") == 0)
+                                               {
+                                                       ereport(ERROR,
+                                                                       (errcode(ERRCODE_RESERVED_NAME),
+                                                                        errmsg("role name \"%s\" is reserved",
+                                                                                       "none"),
+                                                                        parser_errposition(@1)));
+                                               }
+                                               else
+                                               {
+                                                       n = (RoleSpec *) makeRoleSpec(ROLESPEC_CSTRING, @1);
+                                                       n->rolename = pstrdup($1);
+                                               }
+                                               $$ = (Node *) n;
+                                       }
+                       | CURRENT_USER
+                                       {
+                                               $$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1);
+                                       }
+                       | SESSION_USER
+                                       {
+                                               $$ = makeRoleSpec(ROLESPEC_SESSION_USER, @1);
+                                       }
+               ;
+
+role_list:     RoleSpec
+                                       { $$ = list_make1($1); }
+                       | role_list ',' RoleSpec
+                                       { $$ = lappend($1, $3); }
+               ;
+
 /*
  * Name classification hierarchy.
  *
@@ -13812,6 +13856,20 @@ makeBoolAConst(bool state, int location)
        return makeTypeCast((Node *)n, SystemTypeName("bool"), -1);
 }
 
+/* makeRoleSpec
+ * Create a RoleSpec with the given type
+ */
+static Node *
+makeRoleSpec(RoleSpecType type, int location)
+{
+       RoleSpec *spec = makeNode(RoleSpec);
+
+       spec->roletype = type;
+       spec->location = location;
+
+       return (Node *) spec;
+}
+
 /* check_qualified_name --- check the result of qualified_name production
  *
  * It's easiest to let the grammar production for qualified_name allow
index c29f1065294a42c4b3d38fcc4c0bce6d3baa4681..1e6da9cc40e397bed92a888a91c32b99b2fed003 100644 (file)
@@ -90,7 +90,7 @@ typedef struct
 {
        const char *stmtType;           /* "CREATE SCHEMA" or "ALTER SCHEMA" */
        char       *schemaname;         /* name of schema */
-       char       *authid;                     /* owner of schema */
+       RoleSpec   *authrole;           /* owner of schema */
        List       *sequences;          /* CREATE SEQUENCE items */
        List       *tables;                     /* CREATE TABLE items */
        List       *views;                      /* CREATE VIEW items */
@@ -2723,7 +2723,7 @@ transformCreateSchemaStmt(CreateSchemaStmt *stmt)
 
        cxt.stmtType = "CREATE SCHEMA";
        cxt.schemaname = stmt->schemaname;
-       cxt.authid = stmt->authid;
+       cxt.authrole = (RoleSpec *) stmt->authrole;
        cxt.sequences = NIL;
        cxt.tables = NIL;
        cxt.views = NIL;
index 411d779be6bee24c6358d98675787f037800f6ac..7701fc5ac07f4357ada4858be06e6d6b1eafc225 100644 (file)
@@ -5105,7 +5105,7 @@ select_best_grantor(Oid roleId, AclMode privileges,
 /*
  * get_role_oid - Given a role name, look up the role's OID.
  *
- * If missing_ok is false, throw an error if tablespace name not found.  If
+ * If missing_ok is false, throw an error if role name not found.  If
  * true, just return InvalidOid.
  */
 Oid
@@ -5133,3 +5133,117 @@ get_role_oid_or_public(const char *rolname)
 
        return get_role_oid(rolname, false);
 }
+
+/*
+ * Given a RoleSpec node, return the OID it corresponds to.  If missing_ok is
+ * true, return InvalidOid if the role does not exist.
+ *
+ * PUBLIC is always disallowed here.  Routines wanting to handle the PUBLIC
+ * case must check the case separately.
+ */
+Oid
+get_rolespec_oid(const Node *node, bool missing_ok)
+{
+       RoleSpec   *role;
+       Oid                     oid;
+
+       if (!IsA(node, RoleSpec))
+               elog(ERROR, "invalid node type %d", node->type);
+
+       role = (RoleSpec *) node;
+       switch (role->roletype)
+       {
+               case ROLESPEC_CSTRING:
+                       Assert(role->rolename);
+                       oid = get_role_oid(role->rolename, missing_ok);
+                       break;
+
+               case ROLESPEC_CURRENT_USER:
+                       oid = GetUserId();
+                       break;
+
+               case ROLESPEC_SESSION_USER:
+                       oid = GetSessionUserId();
+                       break;
+
+               case ROLESPEC_PUBLIC:
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                        errmsg("role \"%s\" does not exist", "public")));
+                       oid = InvalidOid;       /* make compiler happy */
+                       break;
+
+               default:
+                       elog(ERROR, "unexpected role type %d", role->roletype);
+       }
+
+       return oid;
+}
+
+/*
+ * Given a RoleSpec node, return the pg_authid HeapTuple it corresponds to.
+ * Caller must ReleaseSysCache when done with the result tuple.
+ */
+HeapTuple
+get_rolespec_tuple(const Node *node)
+{
+       RoleSpec   *role;
+       HeapTuple       tuple;
+
+       role = (RoleSpec *) node;
+       if (!IsA(node, RoleSpec))
+               elog(ERROR, "invalid node type %d", node->type);
+
+       switch (role->roletype)
+       {
+               case ROLESPEC_CSTRING:
+                       Assert(role->rolename);
+                       tuple = SearchSysCache1(AUTHNAME, CStringGetDatum(role->rolename));
+                       if (!HeapTupleIsValid(tuple))
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                                errmsg("role \"%s\" does not exist", role->rolename)));
+                       break;
+
+               case ROLESPEC_CURRENT_USER:
+                       tuple = SearchSysCache1(AUTHOID, GetUserId());
+                       if (!HeapTupleIsValid(tuple))
+                               elog(ERROR, "cache lookup failed for role %u", GetUserId());
+                       break;
+
+               case ROLESPEC_SESSION_USER:
+                       tuple = SearchSysCache1(AUTHOID, GetSessionUserId());
+                       if (!HeapTupleIsValid(tuple))
+                               elog(ERROR, "cache lookup failed for role %u", GetSessionUserId());
+                       break;
+
+               case ROLESPEC_PUBLIC:
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                        errmsg("role \"%s\" does not exist", "public")));
+                       tuple = NULL;   /* make compiler happy */
+
+               default:
+                       elog(ERROR, "unexpected role type %d", role->roletype);
+       }
+
+       return tuple;
+}
+
+/*
+ * Given a RoleSpec, returns a palloc'ed copy of the corresponding role's name.
+ */
+char *
+get_rolespec_name(const Node *node)
+{
+       HeapTuple       tp;
+       Form_pg_authid authForm;
+       char       *rolename;
+
+       tp = get_rolespec_tuple(node);
+       authForm = (Form_pg_authid) GETSTRUCT(tp);
+       rolename = pstrdup(NameStr(authForm->rolname));
+       ReleaseSysCache(tp);
+
+       return rolename;
+}
index ccadb04b8c7688f944706babf2b62991678e4cfc..d35cb0c90deff570fc15da57c1ed6f43728deb2b 100644 (file)
@@ -31,6 +31,6 @@ extern void GrantRole(GrantRoleStmt *stmt);
 extern ObjectAddress RenameRole(const char *oldname, const char *newname);
 extern void DropOwnedObjects(DropOwnedStmt *stmt);
 extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt);
-extern List *roleNamesToIds(List *memberNames);
+extern List *roleSpecsToIds(List *memberNames);
 
 #endif   /* USER_H */
index 97ef0fcf7d177cb53738505947a2b3d6ee5cd296..38469ef4d1af4abba24935d91e76f1eb30ed25cf 100644 (file)
@@ -413,6 +413,7 @@ typedef enum NodeTag
        T_XmlSerialize,
        T_WithClause,
        T_CommonTableExpr,
+       T_RoleSpec,
 
        /*
         * TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)
index ac133023b4f6b750ad43b444bbd9536058f1ed9d..497559df5887982b12386d37881ed3b6045e0bff 100644 (file)
@@ -284,6 +284,25 @@ typedef struct CollateClause
        int                     location;               /* token location, or -1 if unknown */
 } CollateClause;
 
+/*
+ * RoleSpec - a role name or one of a few special values.
+ */
+typedef enum RoleSpecType
+{
+       ROLESPEC_CSTRING,               /* role name is stored as a C string */
+       ROLESPEC_CURRENT_USER,  /* role spec is CURRENT_USER */
+       ROLESPEC_SESSION_USER,  /* role spec is SESSION_USER */
+       ROLESPEC_PUBLIC                 /* role name is "public" */
+} RoleSpecType;
+
+typedef struct RoleSpec
+{
+       NodeTag         type;
+       RoleSpecType roletype;  /* Type of this rolespec */
+       char       *rolename;   /* filled only for ROLESPEC_CSTRING */
+       int                     location;       /* token location, or -1 if unknown */
+} RoleSpec;
+
 /*
  * FuncCall - a function or aggregate invocation
  *
@@ -1263,7 +1282,7 @@ typedef struct CreateSchemaStmt
 {
        NodeTag         type;
        char       *schemaname;         /* the name of the schema to create */
-       char       *authid;                     /* the owner of the created schema */
+       Node       *authrole;           /* the owner of the created schema */
        List       *schemaElts;         /* schema components (list of parsenodes) */
        bool            if_not_exists;  /* just do nothing if schema already exists? */
 } CreateSchemaStmt;
@@ -1362,7 +1381,8 @@ typedef struct AlterTableCmd      /* one subcommand of an ALTER TABLE */
        NodeTag         type;
        AlterTableType subtype;         /* Type of table alteration to apply */
        char       *name;                       /* column, constraint, or trigger to act on,
-                                                                * or new owner or tablespace */
+                                                                * or tablespace */
+       Node       *newowner;           /* RoleSpec */
        Node       *def;                        /* definition of new column, index,
                                                                 * constraint, or parent table */
        DropBehavior behavior;          /* RESTRICT or CASCADE for DROP cases */
@@ -1434,17 +1454,11 @@ typedef struct GrantStmt
                                                                 * or plain names (as Value strings) */
        List       *privileges;         /* list of AccessPriv nodes */
        /* privileges == NIL denotes ALL PRIVILEGES */
-       List       *grantees;           /* list of PrivGrantee nodes */
+       List       *grantees;           /* list of RoleSpec nodes */
        bool            grant_option;   /* grant or revoke grant option */
        DropBehavior behavior;          /* drop behavior (for REVOKE) */
 } GrantStmt;
 
-typedef struct PrivGrantee
-{
-       NodeTag         type;
-       char       *rolname;            /* if NULL then PUBLIC */
-} PrivGrantee;
-
 /*
  * Note: FuncWithArgs carries only the types of the input parameters of the
  * function.  So it is sufficient to identify an existing function, but it
@@ -1487,7 +1501,7 @@ typedef struct GrantRoleStmt
        List       *grantee_roles;      /* list of member roles to add/delete */
        bool            is_grant;               /* true = GRANT, false = REVOKE */
        bool            admin_opt;              /* with admin option */
-       char       *grantor;            /* set grantor to other than current role */
+       Node       *grantor;            /* set grantor to other than current role */
        DropBehavior behavior;          /* drop behavior (for REVOKE) */
 } GrantRoleStmt;
 
@@ -1699,7 +1713,7 @@ typedef struct CreateTableSpaceStmt
 {
        NodeTag         type;
        char       *tablespacename;
-       char       *owner;
+       Node       *owner;
        char       *location;
        List       *options;
 } CreateTableSpaceStmt;
@@ -1825,7 +1839,7 @@ typedef struct CreateForeignTableStmt
 typedef struct CreateUserMappingStmt
 {
        NodeTag         type;
-       char       *username;           /* username or PUBLIC/CURRENT_USER */
+       Node       *user;                       /* user role */
        char       *servername;         /* server name */
        List       *options;            /* generic options to server */
 } CreateUserMappingStmt;
@@ -1833,7 +1847,7 @@ typedef struct CreateUserMappingStmt
 typedef struct AlterUserMappingStmt
 {
        NodeTag         type;
-       char       *username;           /* username or PUBLIC/CURRENT_USER */
+       Node       *user;                       /* user role */
        char       *servername;         /* server name */
        List       *options;            /* generic options to server */
 } AlterUserMappingStmt;
@@ -1841,7 +1855,7 @@ typedef struct AlterUserMappingStmt
 typedef struct DropUserMappingStmt
 {
        NodeTag         type;
-       char       *username;           /* username or PUBLIC/CURRENT_USER */
+       Node       *user;                       /* user role */
        char       *servername;         /* server name */
        bool            missing_ok;             /* ignore missing mappings */
 } DropUserMappingStmt;
@@ -1991,7 +2005,7 @@ typedef struct CreateRoleStmt
 typedef struct AlterRoleStmt
 {
        NodeTag         type;
-       char       *role;                       /* role name */
+       Node       *role;                       /* role */
        List       *options;            /* List of DefElem nodes */
        int                     action;                 /* +1 = add members, -1 = drop members */
 } AlterRoleStmt;
@@ -1999,7 +2013,7 @@ typedef struct AlterRoleStmt
 typedef struct AlterRoleSetStmt
 {
        NodeTag         type;
-       char       *role;                       /* role name */
+       Node       *role;                       /* role */
        char       *database;           /* database name, or NULL */
        VariableSetStmt *setstmt;       /* SET or RESET subcommand */
 } AlterRoleSetStmt;
@@ -2375,7 +2389,7 @@ typedef struct AlterOwnerStmt
        RangeVar   *relation;           /* in case it's a table */
        List       *object;                     /* in case it's some other object */
        List       *objarg;                     /* argument types, if applicable */
-       char       *newowner;           /* the new owner */
+       Node       *newowner;           /* the new owner */
 } AlterOwnerStmt;
 
 
@@ -2831,7 +2845,7 @@ typedef struct ReassignOwnedStmt
 {
        NodeTag         type;
        List       *roles;
-       char       *newrole;
+       Node       *newrole;
 } ReassignOwnedStmt;
 
 /*
index ab0df6c7d8a741d0fca8d516d20ad058c1c0183f..d747579e7a00f227a86a5d68a3d631ff1c39556d 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef ACL_H
 #define ACL_H
 
+#include "access/htup.h"
 #include "nodes/parsenodes.h"
 #include "utils/array.h"
 #include "utils/snapshot.h"
@@ -227,8 +228,11 @@ extern bool is_member_of_role(Oid member, Oid role);
 extern bool is_member_of_role_nosuper(Oid member, Oid role);
 extern bool is_admin_of_role(Oid member, Oid role);
 extern void check_is_member_of_role(Oid member, Oid role);
-extern Oid     get_role_oid(const char *rolname, bool missing_ok);
-extern Oid     get_role_oid_or_public(const char *rolname);
+extern Oid     get_role_oid(const char *rolename, bool missing_ok);
+extern Oid     get_role_oid_or_public(const char *rolename);
+extern Oid  get_rolespec_oid(const Node *node, bool missing_ok);
+extern HeapTuple get_rolespec_tuple(const Node *node);
+extern char *get_rolespec_name(const Node *node);
 
 extern void select_best_grantor(Oid roleId, AclMode privileges,
                                        const Acl *acl, Oid ownerId,
diff --git a/src/test/regress/expected/rolenames.out b/src/test/regress/expected/rolenames.out
new file mode 100644 (file)
index 0000000..1879337
--- /dev/null
@@ -0,0 +1,940 @@
+CREATE OR REPLACE FUNCTION chkrolattr()
+ RETURNS TABLE ("role" name, rolekeyword text, canlogin bool, replication bool)
+ AS $$
+SELECT r.rolname, v.keyword, r.rolcanlogin, r.rolreplication
+ FROM pg_roles r
+ JOIN (VALUES(CURRENT_USER, 'current_user'),
+             (SESSION_USER, 'session_user'),
+             ('current_user', '-'),
+             ('session_user', '-'),
+             ('Public', '-'),
+             ('None', '-'))
+      AS v(uname, keyword)
+      ON (r.rolname = v.uname)
+ ORDER BY 1;
+$$ LANGUAGE SQL;
+CREATE OR REPLACE FUNCTION chksetconfig()
+ RETURNS TABLE (db name, "role" name, rolkeyword text, setconfig text[])
+ AS $$
+SELECT COALESCE(d.datname, 'ALL'), COALESCE(r.rolname, 'ALL'),
+          COALESCE(v.keyword, '-'), s.setconfig
+ FROM pg_db_role_setting s
+ LEFT JOIN pg_roles r ON (r.oid = s.setrole)
+ LEFT JOIN pg_database d ON (d.oid = s.setdatabase)
+ LEFT JOIN (VALUES(CURRENT_USER, 'current_user'),
+             (SESSION_USER, 'session_user'))
+      AS v(uname, keyword)
+      ON (r.rolname = v.uname)
+   WHERE (r.rolname) IN ('Public', 'current_user', 'testrol1', 'testrol2')
+ORDER BY 1, 2;
+$$ LANGUAGE SQL;
+CREATE OR REPLACE FUNCTION chkumapping()
+ RETURNS TABLE (umname name, umserver name, umoptions text[])
+ AS $$
+SELECT r.rolname, s.srvname, m.umoptions
+ FROM pg_user_mapping m
+ LEFT JOIN pg_roles r ON (r.oid = m.umuser)
+ JOIN pg_foreign_server s ON (s.oid = m.umserver)
+ ORDER BY 2;
+$$ LANGUAGE SQL;
+CREATE ROLE "Public";
+CREATE ROLE "None";
+CREATE ROLE "current_user";
+CREATE ROLE "session_user";
+CREATE ROLE "user";
+CREATE ROLE current_user; -- error
+ERROR:  CURRENT_USER cannot be used as a role name
+LINE 1: CREATE ROLE current_user;
+                    ^
+CREATE ROLE current_role; -- error
+ERROR:  syntax error at or near "current_role"
+LINE 1: CREATE ROLE current_role;
+                    ^
+CREATE ROLE session_user; -- error
+ERROR:  SESSION_USER cannot be used as a role name
+LINE 1: CREATE ROLE session_user;
+                    ^
+CREATE ROLE user; -- error
+ERROR:  syntax error at or near "user"
+LINE 1: CREATE ROLE user;
+                    ^
+CREATE ROLE all; -- error
+ERROR:  syntax error at or near "all"
+LINE 1: CREATE ROLE all;
+                    ^
+CREATE ROLE public; -- error
+ERROR:  role name "public" is reserved
+LINE 1: CREATE ROLE public;
+                    ^
+CREATE ROLE "public"; -- error
+ERROR:  role name "public" is reserved
+LINE 1: CREATE ROLE "public";
+                    ^
+CREATE ROLE none; -- error
+ERROR:  role name "none" is reserved
+LINE 1: CREATE ROLE none;
+                    ^
+CREATE ROLE "none"; -- error
+ERROR:  role name "none" is reserved
+LINE 1: CREATE ROLE "none";
+                    ^
+CREATE ROLE testrol0 SUPERUSER LOGIN;
+CREATE ROLE testrolx SUPERUSER LOGIN;
+CREATE ROLE testrol2 SUPERUSER;
+CREATE ROLE testrol1 SUPERUSER LOGIN IN ROLE testrol2;
+\c -
+SET SESSION AUTHORIZATION testrol1;
+SET ROLE testrol2;
+--  ALTER ROLE
+BEGIN;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | f
+ session_user | -            | f        | f
+ testrol1     | session_user | t        | f
+ testrol2     | current_user | f        | f
+(6 rows)
+
+ALTER ROLE CURRENT_USER WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | f
+ session_user | -            | f        | f
+ testrol1     | session_user | t        | f
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER ROLE "current_user" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | t
+ session_user | -            | f        | f
+ testrol1     | session_user | t        | f
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER ROLE SESSION_USER WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | t
+ session_user | -            | f        | f
+ testrol1     | session_user | t        | t
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER ROLE "session_user" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | t
+ session_user | -            | f        | t
+ testrol1     | session_user | t        | t
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER USER "Public" WITH REPLICATION;
+ALTER USER "None" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | t
+ Public       | -            | f        | t
+ current_user | -            | f        | t
+ session_user | -            | f        | t
+ testrol1     | session_user | t        | t
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER USER testrol1 WITH NOREPLICATION;
+ALTER USER testrol2 WITH NOREPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | t
+ Public       | -            | f        | t
+ current_user | -            | f        | t
+ session_user | -            | f        | t
+ testrol1     | session_user | t        | f
+ testrol2     | current_user | f        | f
+(6 rows)
+
+ROLLBACK;
+ALTER ROLE USER WITH LOGIN; -- error
+ERROR:  syntax error at or near "USER"
+LINE 1: ALTER ROLE USER WITH LOGIN;
+                   ^
+ALTER ROLE CURRENT_ROLE WITH LOGIN; --error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ALTER ROLE CURRENT_ROLE WITH LOGIN;
+                   ^
+ALTER ROLE ALL WITH REPLICATION; -- error
+ERROR:  syntax error at or near "WITH"
+LINE 1: ALTER ROLE ALL WITH REPLICATION;
+                       ^
+ALTER ROLE SESSION_ROLE WITH NOREPLICATION; -- error
+ERROR:  role "session_role" does not exist
+ALTER ROLE PUBLIC WITH NOREPLICATION; -- error
+ERROR:  role "public" does not exist
+ALTER ROLE "public" WITH NOREPLICATION; -- error
+ERROR:  role "public" does not exist
+ALTER ROLE NONE WITH NOREPLICATION; -- error
+ERROR:  role name "none" is reserved
+LINE 1: ALTER ROLE NONE WITH NOREPLICATION;
+                   ^
+ALTER ROLE "none" WITH NOREPLICATION; -- error
+ERROR:  role name "none" is reserved
+LINE 1: ALTER ROLE "none" WITH NOREPLICATION;
+                   ^
+ALTER ROLE nonexistent WITH NOREPLICATION; -- error
+ERROR:  role "nonexistent" does not exist
+--  ALTER USER
+BEGIN;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | f
+ session_user | -            | f        | f
+ testrol1     | session_user | t        | f
+ testrol2     | current_user | f        | f
+(6 rows)
+
+ALTER USER CURRENT_USER WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | f
+ session_user | -            | f        | f
+ testrol1     | session_user | t        | f
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER USER "current_user" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | t
+ session_user | -            | f        | f
+ testrol1     | session_user | t        | f
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER USER SESSION_USER WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | t
+ session_user | -            | f        | f
+ testrol1     | session_user | t        | t
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER USER "session_user" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | f
+ Public       | -            | f        | f
+ current_user | -            | f        | t
+ session_user | -            | f        | t
+ testrol1     | session_user | t        | t
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER USER "Public" WITH REPLICATION;
+ALTER USER "None" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | t
+ Public       | -            | f        | t
+ current_user | -            | f        | t
+ session_user | -            | f        | t
+ testrol1     | session_user | t        | t
+ testrol2     | current_user | f        | t
+(6 rows)
+
+ALTER USER testrol1 WITH NOREPLICATION;
+ALTER USER testrol2 WITH NOREPLICATION;
+SELECT * FROM chkrolattr();
+     role     | rolekeyword  | canlogin | replication 
+--------------+--------------+----------+-------------
+ None         | -            | f        | t
+ Public       | -            | f        | t
+ current_user | -            | f        | t
+ session_user | -            | f        | t
+ testrol1     | session_user | t        | f
+ testrol2     | current_user | f        | f
+(6 rows)
+
+ROLLBACK;
+ALTER USER USER WITH LOGIN; -- error
+ERROR:  syntax error at or near "USER"
+LINE 1: ALTER USER USER WITH LOGIN;
+                   ^
+ALTER USER CURRENT_ROLE WITH LOGIN; -- error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ALTER USER CURRENT_ROLE WITH LOGIN;
+                   ^
+ALTER USER ALL WITH REPLICATION; -- error
+ERROR:  syntax error at or near "ALL"
+LINE 1: ALTER USER ALL WITH REPLICATION;
+                   ^
+ALTER USER SESSION_ROLE WITH NOREPLICATION; -- error
+ERROR:  role "session_role" does not exist
+ALTER USER PUBLIC WITH NOREPLICATION; -- error
+ERROR:  role "public" does not exist
+ALTER USER "public" WITH NOREPLICATION; -- error
+ERROR:  role "public" does not exist
+ALTER USER NONE WITH NOREPLICATION; -- error
+ERROR:  role name "none" is reserved
+LINE 1: ALTER USER NONE WITH NOREPLICATION;
+                   ^
+ALTER USER "none" WITH NOREPLICATION; -- error
+ERROR:  role name "none" is reserved
+LINE 1: ALTER USER "none" WITH NOREPLICATION;
+                   ^
+ALTER USER nonexistent WITH NOREPLICATION; -- error
+ERROR:  role "nonexistent" does not exist
+--  ALTER ROLE SET/RESET
+SELECT * FROM chksetconfig();
+ db | role | rolkeyword | setconfig 
+----+------+------------+-----------
+(0 rows)
+
+ALTER ROLE CURRENT_USER SET application_name to 'FOO';
+ALTER ROLE SESSION_USER SET application_name to 'BAR';
+ALTER ROLE "current_user" SET application_name to 'FOOFOO';
+ALTER ROLE "Public" SET application_name to 'BARBAR';
+ALTER ROLE ALL SET application_name to 'SLAP';
+SELECT * FROM chksetconfig();
+ db  |     role     |  rolkeyword  |         setconfig         
+-----+--------------+--------------+---------------------------
+ ALL | Public       | -            | {application_name=BARBAR}
+ ALL | current_user | -            | {application_name=FOOFOO}
+ ALL | testrol1     | session_user | {application_name=BAR}
+ ALL | testrol2     | current_user | {application_name=FOO}
+(4 rows)
+
+ALTER ROLE testrol1 SET application_name to 'SLAM';
+SELECT * FROM chksetconfig();
+ db  |     role     |  rolkeyword  |         setconfig         
+-----+--------------+--------------+---------------------------
+ ALL | Public       | -            | {application_name=BARBAR}
+ ALL | current_user | -            | {application_name=FOOFOO}
+ ALL | testrol1     | session_user | {application_name=SLAM}
+ ALL | testrol2     | current_user | {application_name=FOO}
+(4 rows)
+
+ALTER ROLE CURRENT_USER RESET application_name;
+ALTER ROLE SESSION_USER RESET application_name;
+ALTER ROLE "current_user" RESET application_name;
+ALTER ROLE "Public" RESET application_name;
+ALTER ROLE ALL RESET application_name;
+SELECT * FROM chksetconfig();
+ db | role | rolkeyword | setconfig 
+----+------+------------+-----------
+(0 rows)
+
+ALTER ROLE CURRENT_ROLE SET application_name to 'BAZ'; -- error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ALTER ROLE CURRENT_ROLE SET application_name to 'BAZ';
+                   ^
+ALTER ROLE USER SET application_name to 'BOOM'; -- error
+ERROR:  syntax error at or near "USER"
+LINE 1: ALTER ROLE USER SET application_name to 'BOOM';
+                   ^
+ALTER ROLE PUBLIC SET application_name to 'BOMB'; -- error
+ERROR:  role "public" does not exist
+ALTER ROLE nonexistent SET application_name to 'BOMB'; -- error
+ERROR:  role "nonexistent" does not exist
+--  ALTER USER SET/RESET
+SELECT * FROM chksetconfig();
+ db | role | rolkeyword | setconfig 
+----+------+------------+-----------
+(0 rows)
+
+ALTER USER CURRENT_USER SET application_name to 'FOO';
+ALTER USER SESSION_USER SET application_name to 'BAR';
+ALTER USER "current_user" SET application_name to 'FOOFOO';
+ALTER USER "Public" SET application_name to 'BARBAR';
+ALTER USER ALL SET application_name to 'SLAP';
+ERROR:  syntax error at or near "ALL"
+LINE 1: ALTER USER ALL SET application_name to 'SLAP';
+                   ^
+SELECT * FROM chksetconfig();
+ db  |     role     |  rolkeyword  |         setconfig         
+-----+--------------+--------------+---------------------------
+ ALL | Public       | -            | {application_name=BARBAR}
+ ALL | current_user | -            | {application_name=FOOFOO}
+ ALL | testrol1     | session_user | {application_name=BAR}
+ ALL | testrol2     | current_user | {application_name=FOO}
+(4 rows)
+
+ALTER USER testrol1 SET application_name to 'SLAM';
+SELECT * FROM chksetconfig();
+ db  |     role     |  rolkeyword  |         setconfig         
+-----+--------------+--------------+---------------------------
+ ALL | Public       | -            | {application_name=BARBAR}
+ ALL | current_user | -            | {application_name=FOOFOO}
+ ALL | testrol1     | session_user | {application_name=SLAM}
+ ALL | testrol2     | current_user | {application_name=FOO}
+(4 rows)
+
+ALTER USER CURRENT_USER RESET application_name;
+ALTER USER SESSION_USER RESET application_name;
+ALTER USER "current_user" RESET application_name;
+ALTER USER "Public" RESET application_name;
+ALTER USER ALL RESET application_name;
+ERROR:  syntax error at or near "ALL"
+LINE 1: ALTER USER ALL RESET application_name;
+                   ^
+SELECT * FROM chksetconfig();
+ db | role | rolkeyword | setconfig 
+----+------+------------+-----------
+(0 rows)
+
+ALTER USER CURRENT_USER SET application_name to 'BAZ'; -- error
+ALTER USER USER SET application_name to 'BOOM'; -- error
+ERROR:  syntax error at or near "USER"
+LINE 1: ALTER USER USER SET application_name to 'BOOM';
+                   ^
+ALTER USER PUBLIC SET application_name to 'BOMB'; -- error
+ERROR:  role "public" does not exist
+ALTER USER NONE SET application_name to 'BOMB'; -- error
+ERROR:  role name "none" is reserved
+LINE 1: ALTER USER NONE SET application_name to 'BOMB';
+                   ^
+ALTER USER nonexistent SET application_name to 'BOMB'; -- error
+ERROR:  role "nonexistent" does not exist
+-- CREAETE SCHEMA
+set client_min_messages to error;
+CREATE SCHEMA newschema1 AUTHORIZATION CURRENT_USER;
+CREATE SCHEMA newschema2 AUTHORIZATION "current_user";
+CREATE SCHEMA newschema3 AUTHORIZATION SESSION_USER;
+CREATE SCHEMA newschema4 AUTHORIZATION testrolx;
+CREATE SCHEMA newschema5 AUTHORIZATION "Public";
+CREATE SCHEMA newschema6 AUTHORIZATION USER; -- error
+ERROR:  syntax error at or near "USER"
+LINE 1: CREATE SCHEMA newschema6 AUTHORIZATION USER;
+                                               ^
+CREATE SCHEMA newschema6 AUTHORIZATION CURRENT_ROLE; -- error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: CREATE SCHEMA newschema6 AUTHORIZATION CURRENT_ROLE;
+                                               ^
+CREATE SCHEMA newschema6 AUTHORIZATION PUBLIC; -- error
+ERROR:  role "public" does not exist
+CREATE SCHEMA newschema6 AUTHORIZATION "public"; -- error
+ERROR:  role "public" does not exist
+CREATE SCHEMA newschema6 AUTHORIZATION NONE; -- error
+ERROR:  role name "none" is reserved
+LINE 1: CREATE SCHEMA newschema6 AUTHORIZATION NONE;
+                                               ^
+CREATE SCHEMA newschema6 AUTHORIZATION nonexistent; -- error
+ERROR:  role "nonexistent" does not exist
+SELECT n.nspname, r.rolname FROM pg_namespace n
+ JOIN pg_roles r ON (r.oid = n.nspowner)
+ WHERE n.nspname LIKE 'newschema_' ORDER BY 1;
+  nspname   |   rolname    
+------------+--------------
+ newschema1 | testrol2
+ newschema2 | current_user
+ newschema3 | testrol1
+ newschema4 | testrolx
+ newschema5 | Public
+(5 rows)
+
+CREATE SCHEMA IF NOT EXISTS newschema1 AUTHORIZATION CURRENT_USER;
+CREATE SCHEMA IF NOT EXISTS newschema2 AUTHORIZATION "current_user";
+CREATE SCHEMA IF NOT EXISTS newschema3 AUTHORIZATION SESSION_USER;
+CREATE SCHEMA IF NOT EXISTS newschema4 AUTHORIZATION testrolx;
+CREATE SCHEMA IF NOT EXISTS newschema5 AUTHORIZATION "Public";
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION USER; -- error
+ERROR:  syntax error at or near "USER"
+LINE 1: CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION USER;
+                                                             ^
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION CURRENT_ROLE; -- error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ...ATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION CURRENT_RO...
+                                                             ^
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION PUBLIC; -- error
+ERROR:  role "public" does not exist
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION "public"; -- error
+ERROR:  role "public" does not exist
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION NONE; -- error
+ERROR:  role name "none" is reserved
+LINE 1: CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION NONE;
+                                                             ^
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION nonexistent; -- error
+ERROR:  role "nonexistent" does not exist
+SELECT n.nspname, r.rolname FROM pg_namespace n
+ JOIN pg_roles r ON (r.oid = n.nspowner)
+ WHERE n.nspname LIKE 'newschema_' ORDER BY 1;
+  nspname   |   rolname    
+------------+--------------
+ newschema1 | testrol2
+ newschema2 | current_user
+ newschema3 | testrol1
+ newschema4 | testrolx
+ newschema5 | Public
+(5 rows)
+
+-- ALTER TABLE OWNER TO
+\c -
+SET SESSION AUTHORIZATION testrol0;
+set client_min_messages to error;
+CREATE TABLE testtab1 (a int);
+CREATE TABLE testtab2 (a int);
+CREATE TABLE testtab3 (a int);
+CREATE TABLE testtab4 (a int);
+CREATE TABLE testtab5 (a int);
+CREATE TABLE testtab6 (a int);
+\c -
+SET SESSION AUTHORIZATION testrol1;
+SET ROLE testrol2;
+ALTER TABLE testtab1 OWNER TO CURRENT_USER;
+ALTER TABLE testtab2 OWNER TO "current_user";
+ALTER TABLE testtab3 OWNER TO SESSION_USER;
+ALTER TABLE testtab4 OWNER TO testrolx;
+ALTER TABLE testtab5 OWNER TO "Public";
+ALTER TABLE testtab6 OWNER TO CURRENT_ROLE; -- error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ALTER TABLE testtab6 OWNER TO CURRENT_ROLE;
+                                      ^
+ALTER TABLE testtab6 OWNER TO USER; --error
+ERROR:  syntax error at or near "USER"
+LINE 1: ALTER TABLE testtab6 OWNER TO USER;
+                                      ^
+ALTER TABLE testtab6 OWNER TO PUBLIC; -- error
+ERROR:  role "public" does not exist
+ALTER TABLE testtab6 OWNER TO "public"; -- error
+ERROR:  role "public" does not exist
+ALTER TABLE testtab6 OWNER TO nonexistent; -- error
+ERROR:  role "nonexistent" does not exist
+SELECT c.relname, r.rolname
+ FROM pg_class c JOIN pg_roles r ON (r.oid = c.relowner)
+ WHERE relname LIKE 'testtab_'
+ ORDER BY 1;
+ relname  |   rolname    
+----------+--------------
+ testtab1 | testrol2
+ testtab2 | current_user
+ testtab3 | testrol1
+ testtab4 | testrolx
+ testtab5 | Public
+ testtab6 | testrol0
+(6 rows)
+
+-- ALTER TABLE, VIEW, MATERIALIZED VIEW, FOREIGN TABLE, SEQUENCE are
+-- changed their owner in the same way.
+-- ALTER AGGREGATE
+\c -
+SET SESSION AUTHORIZATION testrol0;
+CREATE AGGREGATE testagg1(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg2(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg3(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg4(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg5(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg5(int2) (SFUNC = int2_sum, STYPE = int8);
+ERROR:  function "testagg5" already exists with same argument types
+CREATE AGGREGATE testagg6(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg7(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg8(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg9(int2) (SFUNC = int2_sum, STYPE = int8);
+\c -
+SET SESSION AUTHORIZATION testrol1;
+SET ROLE testrol2;
+ALTER AGGREGATE testagg1(int2) OWNER TO CURRENT_USER;
+ALTER AGGREGATE testagg2(int2) OWNER TO "current_user";
+ALTER AGGREGATE testagg3(int2) OWNER TO SESSION_USER;
+ALTER AGGREGATE testagg4(int2) OWNER TO testrolx;
+ALTER AGGREGATE testagg5(int2) OWNER TO "Public";
+ALTER AGGREGATE testagg5(int2) OWNER TO CURRENT_ROLE; -- error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ALTER AGGREGATE testagg5(int2) OWNER TO CURRENT_ROLE;
+                                                ^
+ALTER AGGREGATE testagg5(int2) OWNER TO USER; -- error
+ERROR:  syntax error at or near "USER"
+LINE 1: ALTER AGGREGATE testagg5(int2) OWNER TO USER;
+                                                ^
+ALTER AGGREGATE testagg5(int2) OWNER TO PUBLIC; -- error
+ERROR:  role "public" does not exist
+ALTER AGGREGATE testagg5(int2) OWNER TO "public"; -- error
+ERROR:  role "public" does not exist
+ALTER AGGREGATE testagg5(int2) OWNER TO nonexistent; -- error
+ERROR:  role "nonexistent" does not exist
+SELECT p.proname, r.rolname
+ FROM pg_proc p JOIN pg_roles r ON (r.oid = p.proowner)
+ WHERE proname LIKE 'testagg_'
+ ORDER BY 1;
+ proname  |   rolname    
+----------+--------------
+ testagg1 | testrol2
+ testagg2 | current_user
+ testagg3 | testrol1
+ testagg4 | testrolx
+ testagg5 | Public
+ testagg6 | testrol0
+ testagg7 | testrol0
+ testagg8 | testrol0
+ testagg9 | testrol0
+(9 rows)
+
+-- CREATE USER MAPPING
+CREATE FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv1 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv2 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv3 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv4 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv5 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv6 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv7 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv8 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv9 FOREIGN DATA WRAPPER test_wrapper;
+CREATE USER MAPPING FOR CURRENT_USER SERVER sv1 OPTIONS (user 'CURRENT_USER');
+CREATE USER MAPPING FOR "current_user" SERVER sv2 OPTIONS (user '"current_user"');
+CREATE USER MAPPING FOR USER SERVER sv3 OPTIONS (user 'USER');
+CREATE USER MAPPING FOR "user" SERVER sv4 OPTIONS (user '"USER"');
+CREATE USER MAPPING FOR SESSION_USER SERVER sv5 OPTIONS (user 'SESSION_USER');
+CREATE USER MAPPING FOR PUBLIC SERVER sv6 OPTIONS (user 'PUBLIC');
+CREATE USER MAPPING FOR "Public" SERVER sv7 OPTIONS (user '"Public"');
+CREATE USER MAPPING FOR testrolx SERVER sv8 OPTIONS (user 'testrolx');
+CREATE USER MAPPING FOR CURRENT_ROLE SERVER sv9
+           OPTIONS (user 'CURRENT_ROLE'); -- error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: CREATE USER MAPPING FOR CURRENT_ROLE SERVER sv9
+                                ^
+CREATE USER MAPPING FOR nonexistent SERVER sv9
+           OPTIONS (user 'nonexistent'); -- error;
+ERROR:  role "nonexistent" does not exist
+SELECT * FROM chkumapping();
+    umname    | umserver |         umoptions         
+--------------+----------+---------------------------
+ testrol2     | sv1      | {user=CURRENT_USER}
+ current_user | sv2      | {"user=\"current_user\""}
+ testrol2     | sv3      | {user=USER}
+ user         | sv4      | {"user=\"USER\""}
+ testrol1     | sv5      | {user=SESSION_USER}
+              | sv6      | {user=PUBLIC}
+ Public       | sv7      | {"user=\"Public\""}
+ testrolx     | sv8      | {user=testrolx}
+(8 rows)
+
+-- ALTER USER MAPPING
+ALTER USER MAPPING FOR CURRENT_USER SERVER sv1
+ OPTIONS (SET user 'CURRENT_USER_alt');
+ALTER USER MAPPING FOR "current_user" SERVER sv2
+ OPTIONS (SET user '"current_user"_alt');
+ALTER USER MAPPING FOR USER SERVER sv3
+ OPTIONS (SET user 'USER_alt');
+ALTER USER MAPPING FOR "user" SERVER sv4
+ OPTIONS (SET user '"user"_alt');
+ALTER USER MAPPING FOR SESSION_USER SERVER sv5
+ OPTIONS (SET user 'SESSION_USER_alt');
+ALTER USER MAPPING FOR PUBLIC SERVER sv6
+ OPTIONS (SET user 'public_alt');
+ALTER USER MAPPING FOR "Public" SERVER sv7
+ OPTIONS (SET user '"Public"_alt');
+ALTER USER MAPPING FOR testrolx SERVER sv8
+ OPTIONS (SET user 'testrolx_alt');
+ALTER USER MAPPING FOR CURRENT_ROLE SERVER sv9
+ OPTIONS (SET user 'CURRENT_ROLE_alt');
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ALTER USER MAPPING FOR CURRENT_ROLE SERVER sv9
+                               ^
+ALTER USER MAPPING FOR nonexistent SERVER sv9
+ OPTIONS (SET user 'nonexistent_alt'); -- error
+ERROR:  role "nonexistent" does not exist
+SELECT * FROM chkumapping();
+    umname    | umserver |           umoptions           
+--------------+----------+-------------------------------
+ testrol2     | sv1      | {user=CURRENT_USER_alt}
+ current_user | sv2      | {"user=\"current_user\"_alt"}
+ testrol2     | sv3      | {user=USER_alt}
+ user         | sv4      | {"user=\"user\"_alt"}
+ testrol1     | sv5      | {user=SESSION_USER_alt}
+              | sv6      | {user=public_alt}
+ Public       | sv7      | {"user=\"Public\"_alt"}
+ testrolx     | sv8      | {user=testrolx_alt}
+(8 rows)
+
+-- DROP USER MAPPING
+DROP USER MAPPING FOR CURRENT_USER SERVER sv1;
+DROP USER MAPPING FOR "current_user" SERVER sv2;
+DROP USER MAPPING FOR USER SERVER sv3;
+DROP USER MAPPING FOR "user" SERVER sv4;
+DROP USER MAPPING FOR SESSION_USER SERVER sv5;
+DROP USER MAPPING FOR PUBLIC SERVER sv6;
+DROP USER MAPPING FOR "Public" SERVER sv7;
+DROP USER MAPPING FOR testrolx SERVER sv8;
+DROP USER MAPPING FOR CURRENT_ROLE SERVER sv9; -- error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: DROP USER MAPPING FOR CURRENT_ROLE SERVER sv9;
+                              ^
+DROP USER MAPPING FOR nonexistent SERVER sv;  -- error
+ERROR:  role "nonexistent" does not exist
+SELECT * FROM chkumapping();
+ umname | umserver | umoptions 
+--------+----------+-----------
+(0 rows)
+
+CREATE USER MAPPING FOR CURRENT_USER SERVER sv1 OPTIONS (user 'CURRENT_USER');
+CREATE USER MAPPING FOR "current_user" SERVER sv2 OPTIONS (user '"current_user"');
+CREATE USER MAPPING FOR USER SERVER sv3 OPTIONS (user 'USER');
+CREATE USER MAPPING FOR "user" SERVER sv4 OPTIONS (user '"USER"');
+CREATE USER MAPPING FOR SESSION_USER SERVER sv5 OPTIONS (user 'SESSION_USER');
+CREATE USER MAPPING FOR PUBLIC SERVER sv6 OPTIONS (user 'PUBLIC');
+CREATE USER MAPPING FOR "Public" SERVER sv7 OPTIONS (user '"Public"');
+CREATE USER MAPPING FOR testrolx SERVER sv8 OPTIONS (user 'testrolx');
+SELECT * FROM chkumapping();
+    umname    | umserver |         umoptions         
+--------------+----------+---------------------------
+ testrol2     | sv1      | {user=CURRENT_USER}
+ current_user | sv2      | {"user=\"current_user\""}
+ testrol2     | sv3      | {user=USER}
+ user         | sv4      | {"user=\"USER\""}
+ testrol1     | sv5      | {user=SESSION_USER}
+              | sv6      | {user=PUBLIC}
+ Public       | sv7      | {"user=\"Public\""}
+ testrolx     | sv8      | {user=testrolx}
+(8 rows)
+
+-- DROP USER MAPPING IF EXISTS
+DROP USER MAPPING IF EXISTS FOR CURRENT_USER SERVER sv1;
+SELECT * FROM chkumapping();
+    umname    | umserver |         umoptions         
+--------------+----------+---------------------------
+ current_user | sv2      | {"user=\"current_user\""}
+ testrol2     | sv3      | {user=USER}
+ user         | sv4      | {"user=\"USER\""}
+ testrol1     | sv5      | {user=SESSION_USER}
+              | sv6      | {user=PUBLIC}
+ Public       | sv7      | {"user=\"Public\""}
+ testrolx     | sv8      | {user=testrolx}
+(7 rows)
+
+DROP USER MAPPING IF EXISTS FOR "current_user" SERVER sv2;
+SELECT * FROM chkumapping();
+  umname  | umserver |      umoptions      
+----------+----------+---------------------
+ testrol2 | sv3      | {user=USER}
+ user     | sv4      | {"user=\"USER\""}
+ testrol1 | sv5      | {user=SESSION_USER}
+          | sv6      | {user=PUBLIC}
+ Public   | sv7      | {"user=\"Public\""}
+ testrolx | sv8      | {user=testrolx}
+(6 rows)
+
+DROP USER MAPPING IF EXISTS FOR USER SERVER sv3;
+SELECT * FROM chkumapping();
+  umname  | umserver |      umoptions      
+----------+----------+---------------------
+ user     | sv4      | {"user=\"USER\""}
+ testrol1 | sv5      | {user=SESSION_USER}
+          | sv6      | {user=PUBLIC}
+ Public   | sv7      | {"user=\"Public\""}
+ testrolx | sv8      | {user=testrolx}
+(5 rows)
+
+DROP USER MAPPING IF EXISTS FOR "user" SERVER sv4;
+SELECT * FROM chkumapping();
+  umname  | umserver |      umoptions      
+----------+----------+---------------------
+ testrol1 | sv5      | {user=SESSION_USER}
+          | sv6      | {user=PUBLIC}
+ Public   | sv7      | {"user=\"Public\""}
+ testrolx | sv8      | {user=testrolx}
+(4 rows)
+
+DROP USER MAPPING IF EXISTS FOR SESSION_USER SERVER sv5;
+SELECT * FROM chkumapping();
+  umname  | umserver |      umoptions      
+----------+----------+---------------------
+          | sv6      | {user=PUBLIC}
+ Public   | sv7      | {"user=\"Public\""}
+ testrolx | sv8      | {user=testrolx}
+(3 rows)
+
+DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER sv6;
+SELECT * FROM chkumapping();
+  umname  | umserver |      umoptions      
+----------+----------+---------------------
+ Public   | sv7      | {"user=\"Public\""}
+ testrolx | sv8      | {user=testrolx}
+(2 rows)
+
+DROP USER MAPPING IF EXISTS FOR "Public" SERVER sv7;
+SELECT * FROM chkumapping();
+  umname  | umserver |    umoptions    
+----------+----------+-----------------
+ testrolx | sv8      | {user=testrolx}
+(1 row)
+
+DROP USER MAPPING IF EXISTS FOR testrolx SERVER sv8;
+SELECT * FROM chkumapping();
+ umname | umserver | umoptions 
+--------+----------+-----------
+(0 rows)
+
+DROP USER MAPPING IF EXISTS FOR CURRENT_ROLE SERVER sv9; --error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: DROP USER MAPPING IF EXISTS FOR CURRENT_ROLE SERVER sv9;
+                                        ^
+DROP USER MAPPING IF EXISTS FOR nonexistent SERVER sv9;  -- error
+NOTICE:  role "nonexistent" does not exist, skipping
+-- GRANT/REVOKE
+UPDATE pg_proc SET proacl = null WHERE proname LIKE 'testagg_';
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+ proname  | proacl 
+----------+--------
+ testagg1 | 
+ testagg2 | 
+ testagg3 | 
+ testagg4 | 
+ testagg5 | 
+ testagg6 | 
+ testagg7 | 
+ testagg8 | 
+ testagg9 | 
+(9 rows)
+
+REVOKE ALL PRIVILEGES ON FUNCTION testagg1(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg2(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg3(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg4(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg5(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg6(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg7(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg8(int2) FROM PUBLIC;
+GRANT ALL PRIVILEGES ON FUNCTION testagg1(int2) TO PUBLIC;
+GRANT ALL PRIVILEGES ON FUNCTION testagg2(int2) TO CURRENT_USER;
+GRANT ALL PRIVILEGES ON FUNCTION testagg3(int2) TO "current_user";
+GRANT ALL PRIVILEGES ON FUNCTION testagg4(int2) TO SESSION_USER;
+GRANT ALL PRIVILEGES ON FUNCTION testagg5(int2) TO "Public";
+GRANT ALL PRIVILEGES ON FUNCTION testagg6(int2) TO testrolx;
+GRANT ALL PRIVILEGES ON FUNCTION testagg7(int2) TO "public";
+GRANT ALL PRIVILEGES ON FUNCTION testagg8(int2)
+          TO current_user, public, testrolx;
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+ proname  |                                  proacl                                   
+----------+---------------------------------------------------------------------------
+ testagg1 | {testrol2=X/testrol2,=X/testrol2}
+ testagg2 | {current_user=X/current_user,testrol2=X/current_user}
+ testagg3 | {testrol1=X/testrol1,current_user=X/testrol1}
+ testagg4 | {testrolx=X/testrolx,testrol1=X/testrolx}
+ testagg5 | {Public=X/Public}
+ testagg6 | {testrol0=X/testrol0,testrolx=X/testrol0}
+ testagg7 | {testrol0=X/testrol0,=X/testrol0}
+ testagg8 | {testrol0=X/testrol0,testrol2=X/testrol0,=X/testrol0,testrolx=X/testrol0}
+ testagg9 | 
+(9 rows)
+
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO CURRENT_ROLE; --error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ...RANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO CURRENT_RO...
+                                                             ^
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO USER; --error
+ERROR:  syntax error at or near "USER"
+LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO USER;
+                                                           ^
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO NONE; --error
+ERROR:  role name "none" is reserved
+LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO NONE;
+                                                           ^
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO "none"; --error
+ERROR:  role name "none" is reserved
+LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO "none";
+                                                           ^
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+ proname  |                                  proacl                                   
+----------+---------------------------------------------------------------------------
+ testagg1 | {testrol2=X/testrol2,=X/testrol2}
+ testagg2 | {current_user=X/current_user,testrol2=X/current_user}
+ testagg3 | {testrol1=X/testrol1,current_user=X/testrol1}
+ testagg4 | {testrolx=X/testrolx,testrol1=X/testrolx}
+ testagg5 | {Public=X/Public}
+ testagg6 | {testrol0=X/testrol0,testrolx=X/testrol0}
+ testagg7 | {testrol0=X/testrol0,=X/testrol0}
+ testagg8 | {testrol0=X/testrol0,testrol2=X/testrol0,=X/testrol0,testrolx=X/testrol0}
+ testagg9 | 
+(9 rows)
+
+REVOKE ALL PRIVILEGES ON FUNCTION testagg1(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg2(int2) FROM CURRENT_USER;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg3(int2) FROM "current_user";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg4(int2) FROM SESSION_USER;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg5(int2) FROM "Public";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg6(int2) FROM testrolx;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg7(int2) FROM "public";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg8(int2)
+          FROM current_user, public, testrolx;
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+ proname  |            proacl             
+----------+-------------------------------
+ testagg1 | {testrol2=X/testrol2}
+ testagg2 | {current_user=X/current_user}
+ testagg3 | {testrol1=X/testrol1}
+ testagg4 | {testrolx=X/testrolx}
+ testagg5 | {}
+ testagg6 | {testrol0=X/testrol0}
+ testagg7 | {testrol0=X/testrol0}
+ testagg8 | {testrol0=X/testrol0}
+ testagg9 | 
+(9 rows)
+
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM CURRENT_ROLE; --error
+ERROR:  syntax error at or near "CURRENT_ROLE"
+LINE 1: ...KE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM CURRENT_RO...
+                                                             ^
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM USER; --error
+ERROR:  syntax error at or near "USER"
+LINE 1: REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM USER;
+                                                              ^
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM NONE; --error
+ERROR:  role name "none" is reserved
+LINE 1: REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM NONE;
+                                                              ^
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM "none"; --error
+ERROR:  role name "none" is reserved
+LINE 1: ...EVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM "none";
+                                                                ^
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+ proname  |            proacl             
+----------+-------------------------------
+ testagg1 | {testrol2=X/testrol2}
+ testagg2 | {current_user=X/current_user}
+ testagg3 | {testrol1=X/testrol1}
+ testagg4 | {testrolx=X/testrolx}
+ testagg5 | {}
+ testagg6 | {testrol0=X/testrol0}
+ testagg7 | {testrol0=X/testrol0}
+ testagg8 | {testrol0=X/testrol0}
+ testagg9 | 
+(9 rows)
+
+-- clean up
+\c
+DROP OWNED BY testrol0, "Public", "current_user", testrol1, testrol2, testrolx CASCADE;
+DROP ROLE testrol0, testrol1, testrol2, testrolx;
+DROP ROLE "Public", "None", "current_user", "session_user", "user";
index e0ae2f2b01da8ac4cb2b822d030d7533e94914be..6d3b865351d370f0ed52ca42f8f11a3445bf7b9b 100644 (file)
@@ -59,7 +59,7 @@ test: create_index create_view
 # ----------
 # Another group of parallel tests
 # ----------
-test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views
+test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views rolenames
 
 # ----------
 # sanity_check does a vacuum, affecting the sort order of SELECT *
index 7f762bd08fdd92a318b53215d8691153dd5e44ad..8326894ed9d9cece29fc4eda4ede34f731383050 100644 (file)
@@ -71,6 +71,7 @@ test: typed_table
 test: vacuum
 test: drop_if_exists
 test: updatable_views
+test: rolenames
 test: sanity_check
 test: errors
 test: select
diff --git a/src/test/regress/sql/rolenames.sql b/src/test/regress/sql/rolenames.sql
new file mode 100644 (file)
index 0000000..e8c6b33
--- /dev/null
@@ -0,0 +1,434 @@
+CREATE OR REPLACE FUNCTION chkrolattr()
+ RETURNS TABLE ("role" name, rolekeyword text, canlogin bool, replication bool)
+ AS $$
+SELECT r.rolname, v.keyword, r.rolcanlogin, r.rolreplication
+ FROM pg_roles r
+ JOIN (VALUES(CURRENT_USER, 'current_user'),
+             (SESSION_USER, 'session_user'),
+             ('current_user', '-'),
+             ('session_user', '-'),
+             ('Public', '-'),
+             ('None', '-'))
+      AS v(uname, keyword)
+      ON (r.rolname = v.uname)
+ ORDER BY 1;
+$$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION chksetconfig()
+ RETURNS TABLE (db name, "role" name, rolkeyword text, setconfig text[])
+ AS $$
+SELECT COALESCE(d.datname, 'ALL'), COALESCE(r.rolname, 'ALL'),
+          COALESCE(v.keyword, '-'), s.setconfig
+ FROM pg_db_role_setting s
+ LEFT JOIN pg_roles r ON (r.oid = s.setrole)
+ LEFT JOIN pg_database d ON (d.oid = s.setdatabase)
+ LEFT JOIN (VALUES(CURRENT_USER, 'current_user'),
+             (SESSION_USER, 'session_user'))
+      AS v(uname, keyword)
+      ON (r.rolname = v.uname)
+   WHERE (r.rolname) IN ('Public', 'current_user', 'testrol1', 'testrol2')
+ORDER BY 1, 2;
+$$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION chkumapping()
+ RETURNS TABLE (umname name, umserver name, umoptions text[])
+ AS $$
+SELECT r.rolname, s.srvname, m.umoptions
+ FROM pg_user_mapping m
+ LEFT JOIN pg_roles r ON (r.oid = m.umuser)
+ JOIN pg_foreign_server s ON (s.oid = m.umserver)
+ ORDER BY 2;
+$$ LANGUAGE SQL;
+
+CREATE ROLE "Public";
+CREATE ROLE "None";
+CREATE ROLE "current_user";
+CREATE ROLE "session_user";
+CREATE ROLE "user";
+
+CREATE ROLE current_user; -- error
+CREATE ROLE current_role; -- error
+CREATE ROLE session_user; -- error
+CREATE ROLE user; -- error
+CREATE ROLE all; -- error
+
+CREATE ROLE public; -- error
+CREATE ROLE "public"; -- error
+CREATE ROLE none; -- error
+CREATE ROLE "none"; -- error
+
+CREATE ROLE testrol0 SUPERUSER LOGIN;
+CREATE ROLE testrolx SUPERUSER LOGIN;
+CREATE ROLE testrol2 SUPERUSER;
+CREATE ROLE testrol1 SUPERUSER LOGIN IN ROLE testrol2;
+
+\c -
+SET SESSION AUTHORIZATION testrol1;
+SET ROLE testrol2;
+
+--  ALTER ROLE
+BEGIN;
+SELECT * FROM chkrolattr();
+ALTER ROLE CURRENT_USER WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER ROLE "current_user" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER ROLE SESSION_USER WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER ROLE "session_user" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER "Public" WITH REPLICATION;
+ALTER USER "None" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER testrol1 WITH NOREPLICATION;
+ALTER USER testrol2 WITH NOREPLICATION;
+SELECT * FROM chkrolattr();
+ROLLBACK;
+
+ALTER ROLE USER WITH LOGIN; -- error
+ALTER ROLE CURRENT_ROLE WITH LOGIN; --error
+ALTER ROLE ALL WITH REPLICATION; -- error
+ALTER ROLE SESSION_ROLE WITH NOREPLICATION; -- error
+ALTER ROLE PUBLIC WITH NOREPLICATION; -- error
+ALTER ROLE "public" WITH NOREPLICATION; -- error
+ALTER ROLE NONE WITH NOREPLICATION; -- error
+ALTER ROLE "none" WITH NOREPLICATION; -- error
+ALTER ROLE nonexistent WITH NOREPLICATION; -- error
+
+--  ALTER USER
+BEGIN;
+SELECT * FROM chkrolattr();
+ALTER USER CURRENT_USER WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER "current_user" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER SESSION_USER WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER "session_user" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER "Public" WITH REPLICATION;
+ALTER USER "None" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER testrol1 WITH NOREPLICATION;
+ALTER USER testrol2 WITH NOREPLICATION;
+SELECT * FROM chkrolattr();
+ROLLBACK;
+
+ALTER USER USER WITH LOGIN; -- error
+ALTER USER CURRENT_ROLE WITH LOGIN; -- error
+ALTER USER ALL WITH REPLICATION; -- error
+ALTER USER SESSION_ROLE WITH NOREPLICATION; -- error
+ALTER USER PUBLIC WITH NOREPLICATION; -- error
+ALTER USER "public" WITH NOREPLICATION; -- error
+ALTER USER NONE WITH NOREPLICATION; -- error
+ALTER USER "none" WITH NOREPLICATION; -- error
+ALTER USER nonexistent WITH NOREPLICATION; -- error
+
+--  ALTER ROLE SET/RESET
+SELECT * FROM chksetconfig();
+ALTER ROLE CURRENT_USER SET application_name to 'FOO';
+ALTER ROLE SESSION_USER SET application_name to 'BAR';
+ALTER ROLE "current_user" SET application_name to 'FOOFOO';
+ALTER ROLE "Public" SET application_name to 'BARBAR';
+ALTER ROLE ALL SET application_name to 'SLAP';
+SELECT * FROM chksetconfig();
+ALTER ROLE testrol1 SET application_name to 'SLAM';
+SELECT * FROM chksetconfig();
+ALTER ROLE CURRENT_USER RESET application_name;
+ALTER ROLE SESSION_USER RESET application_name;
+ALTER ROLE "current_user" RESET application_name;
+ALTER ROLE "Public" RESET application_name;
+ALTER ROLE ALL RESET application_name;
+SELECT * FROM chksetconfig();
+
+
+ALTER ROLE CURRENT_ROLE SET application_name to 'BAZ'; -- error
+ALTER ROLE USER SET application_name to 'BOOM'; -- error
+ALTER ROLE PUBLIC SET application_name to 'BOMB'; -- error
+ALTER ROLE nonexistent SET application_name to 'BOMB'; -- error
+
+--  ALTER USER SET/RESET
+SELECT * FROM chksetconfig();
+ALTER USER CURRENT_USER SET application_name to 'FOO';
+ALTER USER SESSION_USER SET application_name to 'BAR';
+ALTER USER "current_user" SET application_name to 'FOOFOO';
+ALTER USER "Public" SET application_name to 'BARBAR';
+ALTER USER ALL SET application_name to 'SLAP';
+SELECT * FROM chksetconfig();
+ALTER USER testrol1 SET application_name to 'SLAM';
+SELECT * FROM chksetconfig();
+ALTER USER CURRENT_USER RESET application_name;
+ALTER USER SESSION_USER RESET application_name;
+ALTER USER "current_user" RESET application_name;
+ALTER USER "Public" RESET application_name;
+ALTER USER ALL RESET application_name;
+SELECT * FROM chksetconfig();
+
+
+ALTER USER CURRENT_USER SET application_name to 'BAZ'; -- error
+ALTER USER USER SET application_name to 'BOOM'; -- error
+ALTER USER PUBLIC SET application_name to 'BOMB'; -- error
+ALTER USER NONE SET application_name to 'BOMB'; -- error
+ALTER USER nonexistent SET application_name to 'BOMB'; -- error
+
+-- CREAETE SCHEMA
+set client_min_messages to error;
+CREATE SCHEMA newschema1 AUTHORIZATION CURRENT_USER;
+CREATE SCHEMA newschema2 AUTHORIZATION "current_user";
+CREATE SCHEMA newschema3 AUTHORIZATION SESSION_USER;
+CREATE SCHEMA newschema4 AUTHORIZATION testrolx;
+CREATE SCHEMA newschema5 AUTHORIZATION "Public";
+
+CREATE SCHEMA newschema6 AUTHORIZATION USER; -- error
+CREATE SCHEMA newschema6 AUTHORIZATION CURRENT_ROLE; -- error
+CREATE SCHEMA newschema6 AUTHORIZATION PUBLIC; -- error
+CREATE SCHEMA newschema6 AUTHORIZATION "public"; -- error
+CREATE SCHEMA newschema6 AUTHORIZATION NONE; -- error
+CREATE SCHEMA newschema6 AUTHORIZATION nonexistent; -- error
+
+SELECT n.nspname, r.rolname FROM pg_namespace n
+ JOIN pg_roles r ON (r.oid = n.nspowner)
+ WHERE n.nspname LIKE 'newschema_' ORDER BY 1;
+
+CREATE SCHEMA IF NOT EXISTS newschema1 AUTHORIZATION CURRENT_USER;
+CREATE SCHEMA IF NOT EXISTS newschema2 AUTHORIZATION "current_user";
+CREATE SCHEMA IF NOT EXISTS newschema3 AUTHORIZATION SESSION_USER;
+CREATE SCHEMA IF NOT EXISTS newschema4 AUTHORIZATION testrolx;
+CREATE SCHEMA IF NOT EXISTS newschema5 AUTHORIZATION "Public";
+
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION USER; -- error
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION CURRENT_ROLE; -- error
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION PUBLIC; -- error
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION "public"; -- error
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION NONE; -- error
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION nonexistent; -- error
+
+SELECT n.nspname, r.rolname FROM pg_namespace n
+ JOIN pg_roles r ON (r.oid = n.nspowner)
+ WHERE n.nspname LIKE 'newschema_' ORDER BY 1;
+
+-- ALTER TABLE OWNER TO
+\c -
+SET SESSION AUTHORIZATION testrol0;
+set client_min_messages to error;
+CREATE TABLE testtab1 (a int);
+CREATE TABLE testtab2 (a int);
+CREATE TABLE testtab3 (a int);
+CREATE TABLE testtab4 (a int);
+CREATE TABLE testtab5 (a int);
+CREATE TABLE testtab6 (a int);
+
+\c -
+SET SESSION AUTHORIZATION testrol1;
+SET ROLE testrol2;
+
+ALTER TABLE testtab1 OWNER TO CURRENT_USER;
+ALTER TABLE testtab2 OWNER TO "current_user";
+ALTER TABLE testtab3 OWNER TO SESSION_USER;
+ALTER TABLE testtab4 OWNER TO testrolx;
+ALTER TABLE testtab5 OWNER TO "Public";
+
+ALTER TABLE testtab6 OWNER TO CURRENT_ROLE; -- error
+ALTER TABLE testtab6 OWNER TO USER; --error
+ALTER TABLE testtab6 OWNER TO PUBLIC; -- error
+ALTER TABLE testtab6 OWNER TO "public"; -- error
+ALTER TABLE testtab6 OWNER TO nonexistent; -- error
+
+SELECT c.relname, r.rolname
+ FROM pg_class c JOIN pg_roles r ON (r.oid = c.relowner)
+ WHERE relname LIKE 'testtab_'
+ ORDER BY 1;
+
+-- ALTER TABLE, VIEW, MATERIALIZED VIEW, FOREIGN TABLE, SEQUENCE are
+-- changed their owner in the same way.
+
+-- ALTER AGGREGATE
+\c -
+SET SESSION AUTHORIZATION testrol0;
+CREATE AGGREGATE testagg1(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg2(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg3(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg4(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg5(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg5(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg6(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg7(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg8(int2) (SFUNC = int2_sum, STYPE = int8);
+CREATE AGGREGATE testagg9(int2) (SFUNC = int2_sum, STYPE = int8);
+
+\c -
+SET SESSION AUTHORIZATION testrol1;
+SET ROLE testrol2;
+
+ALTER AGGREGATE testagg1(int2) OWNER TO CURRENT_USER;
+ALTER AGGREGATE testagg2(int2) OWNER TO "current_user";
+ALTER AGGREGATE testagg3(int2) OWNER TO SESSION_USER;
+ALTER AGGREGATE testagg4(int2) OWNER TO testrolx;
+ALTER AGGREGATE testagg5(int2) OWNER TO "Public";
+
+ALTER AGGREGATE testagg5(int2) OWNER TO CURRENT_ROLE; -- error
+ALTER AGGREGATE testagg5(int2) OWNER TO USER; -- error
+ALTER AGGREGATE testagg5(int2) OWNER TO PUBLIC; -- error
+ALTER AGGREGATE testagg5(int2) OWNER TO "public"; -- error
+ALTER AGGREGATE testagg5(int2) OWNER TO nonexistent; -- error
+
+SELECT p.proname, r.rolname
+ FROM pg_proc p JOIN pg_roles r ON (r.oid = p.proowner)
+ WHERE proname LIKE 'testagg_'
+ ORDER BY 1;
+
+-- CREATE USER MAPPING
+CREATE FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv1 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv2 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv3 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv4 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv5 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv6 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv7 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv8 FOREIGN DATA WRAPPER test_wrapper;
+CREATE SERVER sv9 FOREIGN DATA WRAPPER test_wrapper;
+
+CREATE USER MAPPING FOR CURRENT_USER SERVER sv1 OPTIONS (user 'CURRENT_USER');
+CREATE USER MAPPING FOR "current_user" SERVER sv2 OPTIONS (user '"current_user"');
+CREATE USER MAPPING FOR USER SERVER sv3 OPTIONS (user 'USER');
+CREATE USER MAPPING FOR "user" SERVER sv4 OPTIONS (user '"USER"');
+CREATE USER MAPPING FOR SESSION_USER SERVER sv5 OPTIONS (user 'SESSION_USER');
+CREATE USER MAPPING FOR PUBLIC SERVER sv6 OPTIONS (user 'PUBLIC');
+CREATE USER MAPPING FOR "Public" SERVER sv7 OPTIONS (user '"Public"');
+CREATE USER MAPPING FOR testrolx SERVER sv8 OPTIONS (user 'testrolx');
+
+CREATE USER MAPPING FOR CURRENT_ROLE SERVER sv9
+           OPTIONS (user 'CURRENT_ROLE'); -- error
+CREATE USER MAPPING FOR nonexistent SERVER sv9
+           OPTIONS (user 'nonexistent'); -- error;
+
+SELECT * FROM chkumapping();
+
+-- ALTER USER MAPPING
+ALTER USER MAPPING FOR CURRENT_USER SERVER sv1
+ OPTIONS (SET user 'CURRENT_USER_alt');
+ALTER USER MAPPING FOR "current_user" SERVER sv2
+ OPTIONS (SET user '"current_user"_alt');
+ALTER USER MAPPING FOR USER SERVER sv3
+ OPTIONS (SET user 'USER_alt');
+ALTER USER MAPPING FOR "user" SERVER sv4
+ OPTIONS (SET user '"user"_alt');
+ALTER USER MAPPING FOR SESSION_USER SERVER sv5
+ OPTIONS (SET user 'SESSION_USER_alt');
+ALTER USER MAPPING FOR PUBLIC SERVER sv6
+ OPTIONS (SET user 'public_alt');
+ALTER USER MAPPING FOR "Public" SERVER sv7
+ OPTIONS (SET user '"Public"_alt');
+ALTER USER MAPPING FOR testrolx SERVER sv8
+ OPTIONS (SET user 'testrolx_alt');
+
+ALTER USER MAPPING FOR CURRENT_ROLE SERVER sv9
+ OPTIONS (SET user 'CURRENT_ROLE_alt');
+ALTER USER MAPPING FOR nonexistent SERVER sv9
+ OPTIONS (SET user 'nonexistent_alt'); -- error
+
+SELECT * FROM chkumapping();
+
+-- DROP USER MAPPING
+DROP USER MAPPING FOR CURRENT_USER SERVER sv1;
+DROP USER MAPPING FOR "current_user" SERVER sv2;
+DROP USER MAPPING FOR USER SERVER sv3;
+DROP USER MAPPING FOR "user" SERVER sv4;
+DROP USER MAPPING FOR SESSION_USER SERVER sv5;
+DROP USER MAPPING FOR PUBLIC SERVER sv6;
+DROP USER MAPPING FOR "Public" SERVER sv7;
+DROP USER MAPPING FOR testrolx SERVER sv8;
+
+DROP USER MAPPING FOR CURRENT_ROLE SERVER sv9; -- error
+DROP USER MAPPING FOR nonexistent SERVER sv;  -- error
+SELECT * FROM chkumapping();
+
+CREATE USER MAPPING FOR CURRENT_USER SERVER sv1 OPTIONS (user 'CURRENT_USER');
+CREATE USER MAPPING FOR "current_user" SERVER sv2 OPTIONS (user '"current_user"');
+CREATE USER MAPPING FOR USER SERVER sv3 OPTIONS (user 'USER');
+CREATE USER MAPPING FOR "user" SERVER sv4 OPTIONS (user '"USER"');
+CREATE USER MAPPING FOR SESSION_USER SERVER sv5 OPTIONS (user 'SESSION_USER');
+CREATE USER MAPPING FOR PUBLIC SERVER sv6 OPTIONS (user 'PUBLIC');
+CREATE USER MAPPING FOR "Public" SERVER sv7 OPTIONS (user '"Public"');
+CREATE USER MAPPING FOR testrolx SERVER sv8 OPTIONS (user 'testrolx');
+SELECT * FROM chkumapping();
+
+-- DROP USER MAPPING IF EXISTS
+DROP USER MAPPING IF EXISTS FOR CURRENT_USER SERVER sv1;
+SELECT * FROM chkumapping();
+DROP USER MAPPING IF EXISTS FOR "current_user" SERVER sv2;
+SELECT * FROM chkumapping();
+DROP USER MAPPING IF EXISTS FOR USER SERVER sv3;
+SELECT * FROM chkumapping();
+DROP USER MAPPING IF EXISTS FOR "user" SERVER sv4;
+SELECT * FROM chkumapping();
+DROP USER MAPPING IF EXISTS FOR SESSION_USER SERVER sv5;
+SELECT * FROM chkumapping();
+DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER sv6;
+SELECT * FROM chkumapping();
+DROP USER MAPPING IF EXISTS FOR "Public" SERVER sv7;
+SELECT * FROM chkumapping();
+DROP USER MAPPING IF EXISTS FOR testrolx SERVER sv8;
+SELECT * FROM chkumapping();
+
+DROP USER MAPPING IF EXISTS FOR CURRENT_ROLE SERVER sv9; --error
+DROP USER MAPPING IF EXISTS FOR nonexistent SERVER sv9;  -- error
+
+-- GRANT/REVOKE
+UPDATE pg_proc SET proacl = null WHERE proname LIKE 'testagg_';
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+
+REVOKE ALL PRIVILEGES ON FUNCTION testagg1(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg2(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg3(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg4(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg5(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg6(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg7(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg8(int2) FROM PUBLIC;
+
+GRANT ALL PRIVILEGES ON FUNCTION testagg1(int2) TO PUBLIC;
+GRANT ALL PRIVILEGES ON FUNCTION testagg2(int2) TO CURRENT_USER;
+GRANT ALL PRIVILEGES ON FUNCTION testagg3(int2) TO "current_user";
+GRANT ALL PRIVILEGES ON FUNCTION testagg4(int2) TO SESSION_USER;
+GRANT ALL PRIVILEGES ON FUNCTION testagg5(int2) TO "Public";
+GRANT ALL PRIVILEGES ON FUNCTION testagg6(int2) TO testrolx;
+GRANT ALL PRIVILEGES ON FUNCTION testagg7(int2) TO "public";
+GRANT ALL PRIVILEGES ON FUNCTION testagg8(int2)
+          TO current_user, public, testrolx;
+
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO CURRENT_ROLE; --error
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO USER; --error
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO NONE; --error
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO "none"; --error
+
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+
+REVOKE ALL PRIVILEGES ON FUNCTION testagg1(int2) FROM PUBLIC;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg2(int2) FROM CURRENT_USER;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg3(int2) FROM "current_user";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg4(int2) FROM SESSION_USER;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg5(int2) FROM "Public";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg6(int2) FROM testrolx;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg7(int2) FROM "public";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg8(int2)
+          FROM current_user, public, testrolx;
+
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM CURRENT_ROLE; --error
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM USER; --error
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM NONE; --error
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM "none"; --error
+
+SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
+
+-- clean up
+\c
+
+DROP OWNED BY testrol0, "Public", "current_user", testrol1, testrol2, testrolx CASCADE;
+DROP ROLE testrol0, testrol1, testrol2, testrolx;
+DROP ROLE "Public", "None", "current_user", "session_user", "user";