<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>
 
  <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>
 
  <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>
 
 
 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>
 
 
 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>
 
 <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>
 
     [ 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>
 
     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>
 
 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>
 
 
 
  <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>
 
  <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>
 
 
 
  <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>
 
 
     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>
 
 
  <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>
 
 
 
  <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>
 
 
  <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>
 
 
 
  <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>
 
 
 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>
 
       </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>
 
  <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>
 
 
     [ 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>
 
 <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>
 
     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>
 
  <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>
 
 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>
 
     <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>
 
  <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>
 
 
  <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>
 
 
 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>
 
 
 
  <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>
 
 <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>] [, ... ] )
 
 
  <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>
 
 
     [, ...] | 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>
 
    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);
    }
 
    /*
    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);
    }
 
    /*
 
 ObjectAddress
 ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
 {
-   Oid         newowner = get_role_oid(stmt->newowner, false);
+   Oid         newowner = get_rolespec_oid(stmt->newowner, false);
 
    switch (stmt->objectType)
    {
 
            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);
 
 }
 
 
-/*
- * 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.
  *
    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);
    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,
    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)
 
 
 /*
  * 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)
 
    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,
 
 #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"
 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;
    /*
     * 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
 
            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 */
    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 &&
 
 
    /* 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();
 
 
 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);
 
 
     * 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 */
    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];
    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,
     * 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
                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] =
        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);
 
    /*
 
    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);
 
        /*
 
    foreach(item, stmt->roles)
    {
-       const char *role = strVal(lfirst(item));
+       RoleSpec   *rolspec = lfirst(item);
+       char       *role;
        HeapTuple   tuple,
                    tmp_tuple;
        ScanKeyData scankey;
        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))
        {
    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);
 void
 DropOwnedObjects(DropOwnedStmt *stmt)
 {
-   List       *role_ids = roleNamesToIds(stmt->roles);
+   List       *role_ids = roleSpecsToIds(stmt->roles);
    ListCell   *cell;
 
    /* Check privileges */
 void
 ReassignOwnedObjects(ReassignOwnedStmt *stmt)
 {
-   List       *role_ids = roleNamesToIds(stmt->roles);
+   List       *role_ids = roleSpecsToIds(stmt->roles);
    ListCell   *cell;
    Oid         newrole;
 
    }
 
    /* 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,
 }
 
 /*
- * 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;
  *
  * 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?
  */
 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)
    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;
            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
        {
            ereport(NOTICE,
                    (errmsg("role \"%s\" is already a member of role \"%s\"",
-                           membername, rolename)));
+                           get_rolespec_name((Node *) memberRole), rolename)));
            ReleaseSysCache(authmem_tuple);
            continue;
        }
  *
  * 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?
  *
  */
 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)
    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;
 
        {
            ereport(WARNING,
                    (errmsg("role \"%s\" is not a member of role \"%s\"",
-                           membername, rolename)));
+                           get_rolespec_name((Node *) memberRole), rolename)));
            continue;
        }
 
 
    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)
 {
 
    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);
    return newnode;
 }
 
-static PrivGrantee *
-_copyPrivGrantee(const PrivGrantee *from)
-{
-   PrivGrantee *newnode = makeNode(PrivGrantee);
-
-   COPY_STRING_FIELD(rolname);
-
-   return newnode;
-}
-
 static FuncWithArgs *
 _copyFuncWithArgs(const FuncWithArgs *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;
    COPY_NODE_FIELD(relation);
    COPY_NODE_FIELD(object);
    COPY_NODE_FIELD(objarg);
-   COPY_STRING_FIELD(newowner);
+   COPY_NODE_FIELD(newowner);
 
    return newnode;
 }
    CreateTableSpaceStmt *newnode = makeNode(CreateTableSpaceStmt);
 
    COPY_STRING_FIELD(tablespacename);
-   COPY_STRING_FIELD(owner);
+   COPY_NODE_FIELD(owner);
    COPY_STRING_FIELD(location);
    COPY_NODE_FIELD(options);
 
 {
    CreateUserMappingStmt *newnode = makeNode(CreateUserMappingStmt);
 
-   COPY_STRING_FIELD(username);
+   COPY_NODE_FIELD(user);
    COPY_STRING_FIELD(servername);
    COPY_NODE_FIELD(options);
 
 {
    AlterUserMappingStmt *newnode = makeNode(AlterUserMappingStmt);
 
-   COPY_STRING_FIELD(username);
+   COPY_NODE_FIELD(user);
    COPY_STRING_FIELD(servername);
    COPY_NODE_FIELD(options);
 
 {
    DropUserMappingStmt *newnode = makeNode(DropUserMappingStmt);
 
-   COPY_STRING_FIELD(username);
+   COPY_NODE_FIELD(user);
    COPY_STRING_FIELD(servername);
    COPY_SCALAR_FIELD(missing_ok);
 
 {
    AlterRoleStmt *newnode = makeNode(AlterRoleStmt);
 
-   COPY_STRING_FIELD(role);
+   COPY_NODE_FIELD(role);
    COPY_NODE_FIELD(options);
    COPY_SCALAR_FIELD(action);
 
 {
    AlterRoleSetStmt *newnode = makeNode(AlterRoleSetStmt);
 
-   COPY_STRING_FIELD(role);
+   COPY_NODE_FIELD(role);
    COPY_STRING_FIELD(database);
    COPY_NODE_FIELD(setstmt);
 
    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);
 
    ReassignOwnedStmt *newnode = makeNode(ReassignOwnedStmt);
 
    COPY_NODE_FIELD(roles);
-   COPY_STRING_FIELD(newrole);
+   COPY_NODE_FIELD(newrole);
 
    return newnode;
 }
        case T_CommonTableExpr:
            retval = _copyCommonTableExpr(from);
            break;
-       case T_PrivGrantee:
-           retval = _copyPrivGrantee(from);
-           break;
        case T_FuncWithArgs:
            retval = _copyFuncWithArgs(from);
            break;
        case T_XmlSerialize:
            retval = _copyXmlSerialize(from);
            break;
+       case T_RoleSpec:
+           retval = _copyRoleSpec(from);
+           break;
 
        default:
            elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from));
 
 {
    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);
    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)
 {
    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;
    COMPARE_NODE_FIELD(relation);
    COMPARE_NODE_FIELD(object);
    COMPARE_NODE_FIELD(objarg);
-   COMPARE_STRING_FIELD(newowner);
+   COMPARE_NODE_FIELD(newowner);
 
    return true;
 }
 _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);
 
 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);
 
 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);
 
 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);
 
 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);
 
 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);
 
 _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);
 
 _equalReassignOwnedStmt(const ReassignOwnedStmt *a, const ReassignOwnedStmt *b)
 {
    COMPARE_NODE_FIELD(roles);
-   COMPARE_STRING_FIELD(newrole);
+   COMPARE_NODE_FIELD(newrole);
 
    return true;
 }
    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
  */
        case T_CommonTableExpr:
            retval = _equalCommonTableExpr(a, b);
            break;
-       case T_PrivGrantee:
-           retval = _equalPrivGrantee(a, b);
-           break;
        case T_FuncWithArgs:
            retval = _equalFuncWithArgs(a, b);
            break;
        case T_XmlSerialize:
            retval = _equalXmlSerialize(a, b);
            break;
+       case T_RoleSpec:
+           retval = _equalRoleSpec(a, b);
+           break;
 
        default:
            elog(ERROR, "unrecognized node type: %d",
 
 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);
 
 %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
 
 %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
 
 %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
  *****************************************************************************/
 
 AlterRoleStmt:
-           ALTER ROLE RoleId opt_with AlterOptRoleList
+           ALTER ROLE RoleSpec opt_with AlterOptRoleList
                 {
                    AlterRoleStmt *n = makeNode(AlterRoleStmt);
                    n->role = $3;
        ;
 
 AlterRoleSetStmt:
-           ALTER ROLE RoleId opt_in_database SetResetClause
+           ALTER ROLE RoleSpec opt_in_database SetResetClause
                {
                    AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
                    n->role = $3;
  *****************************************************************************/
 
 AlterUserStmt:
-           ALTER USER RoleId opt_with AlterOptRoleList
+           ALTER USER RoleSpec opt_with AlterOptRoleList
                 {
                    AlterRoleStmt *n = makeNode(AlterRoleStmt);
                    n->role = $3;
 
 
 AlterUserSetStmt:
-           ALTER USER RoleId SetResetClause
+           ALTER USER RoleSpec SetResetClause
                {
                    AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
                    n->role = $3;
  *****************************************************************************/
 
 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;
  *****************************************************************************/
 
 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;
                    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),
            | 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),
                    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> */
                }
        ;
 
-OptTableSpaceOwner: OWNER name         { $$ = $2; }
+OptTableSpaceOwner: OWNER RoleSpec     { $$ = $2; }
            | /*EMPTY */                { $$ = NULL; }
        ;
 
 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;
        ;
 
 /* 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); }
        ;
 
 /*****************************************************************************
 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;
                |  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;
 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;
 
 RowSecurityDefaultToRole:
            TO role_list            { $$ = $2; }
-           | /* EMPTY */           { $$ = list_make1(makeString("public")); }
+           | /* EMPTY */           { $$ = list_make1(makeRoleSpec(ROLESPEC_PUBLIC, -1)); }
        ;
 
 RowSecurityOptionalToRole:
        ;
 
 ReassignOwnedStmt:
-           REASSIGN OWNED BY role_list TO name
+           REASSIGN OWNED BY role_list TO RoleSpec
                {
                    ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt);
                    n->roles = $4;
            | 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; }
        ;
 
 
            | /*EMPTY*/                                 { $$ = FALSE; }
        ;
 
-opt_granted_by: GRANTED BY RoleId                      { $$ = $3; }
+opt_granted_by: GRANTED BY RoleSpec                        { $$ = $3; }
            | /*EMPTY*/                                 { $$ = NULL; }
        ;
 
  *
  *****************************************************************************/
 
-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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
                    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;
 
 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.
  *
    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
 
 {
    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 */
 
    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;
 
 /*
  * 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
 
    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;
+}
 
 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 */
 
    T_XmlSerialize,
    T_WithClause,
    T_CommonTableExpr,
+   T_RoleSpec,
 
    /*
     * TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)
 
    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
  *
 {
    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;
    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 */
                                 * 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
    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;
 
 {
    NodeTag     type;
    char       *tablespacename;
-   char       *owner;
+   Node       *owner;
    char       *location;
    List       *options;
 } CreateTableSpaceStmt;
 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;
 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;
 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;
 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;
 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;
    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;
 
 
 {
    NodeTag     type;
    List       *roles;
-   char       *newrole;
+   Node       *newrole;
 } ReassignOwnedStmt;
 
 /*
 
 #ifndef ACL_H
 #define ACL_H
 
+#include "access/htup.h"
 #include "nodes/parsenodes.h"
 #include "utils/array.h"
 #include "utils/snapshot.h"
 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,
 
--- /dev/null
+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";
 
 # ----------
 # 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 *
 
 test: vacuum
 test: drop_if_exists
 test: updatable_views
+test: rolenames
 test: sanity_check
 test: errors
 test: select
 
--- /dev/null
+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";