Allow CURRENT_ROLE in GRANTED BY

Started by Peter Eisentrautover 5 years ago19 messages
#1Peter Eisentraut
peter.eisentraut@2ndquadrant.com
1 attachment(s)

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are
equivalent. Here is a trivial patch to add that.

--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

Attachments:

0001-Allow-CURRENT_ROLE-in-GRANTED-BY.patchtext/plain; charset=UTF-8; name=0001-Allow-CURRENT_ROLE-in-GRANTED-BY.patch; x-mac-creator=0; x-mac-type=0Download
From f46554c2bba025b62b796748d3aa3a65fd080f7f Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 24 Jun 2020 08:21:48 +0200
Subject: [PATCH 1/2] Allow CURRENT_ROLE in GRANTED BY

This is specified in the SQL standard.  Since in PostgreSQL,
CURRENT_ROLE is equivalent to CURRENT_USER, and CURRENT_USER is
already supported here, adding CURRENT_ROLE is trivial.
---
 doc/src/sgml/ref/grant.sgml  | 1 +
 doc/src/sgml/ref/revoke.sgml | 1 +
 src/backend/parser/gram.y    | 4 ++++
 3 files changed, 6 insertions(+)

diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index bc573f7826..fe231aa30c 100644
--- a/doc/src/sgml/ref/grant.sgml
+++ b/doc/src/sgml/ref/grant.sgml
@@ -87,6 +87,7 @@
 
     [ GROUP ] <replaceable class="parameter">role_name</replaceable>
   | PUBLIC
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml
index b6bac21c57..b50f99dfe7 100644
--- a/doc/src/sgml/ref/revoke.sgml
+++ b/doc/src/sgml/ref/revoke.sgml
@@ -114,6 +114,7 @@
 
     [ GROUP ] <replaceable class="parameter">role_name</replaceable>
   | PUBLIC
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e669d75a5a..6e6565dc26 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -14949,6 +14949,10 @@ RoleSpec:	NonReservedWord
 						}
 						$$ = n;
 					}
+			| CURRENT_ROLE
+					{
+						$$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1);
+					}
 			| CURRENT_USER
 					{
 						$$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1);
-- 
2.27.0

#2Vik Fearing
vik@postgresfriends.org
In reply to: Peter Eisentraut (#1)
Re: Allow CURRENT_ROLE in GRANTED BY

On 6/24/20 8:35 AM, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are
equivalent.  Here is a trivial patch to add that.

The only thing that isn't dead-obvious about this patch is the commit
message says "[PATCH 1/2]". What is in the other part?

Assuming that's just a remnant of development, this LGTM.
--
Vik Fearing

#3Peter Eisentraut
peter.eisentraut@2ndquadrant.com
In reply to: Vik Fearing (#2)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-06-24 10:12, Vik Fearing wrote:

On 6/24/20 8:35 AM, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are
equivalent.  Here is a trivial patch to add that.

The only thing that isn't dead-obvious about this patch is the commit
message says "[PATCH 1/2]". What is in the other part?

Hehe. The second patch is some in-progress work to add the GRANTED BY
clause to the regular GRANT command. More on that perhaps at a later date.

--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#4Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Peter Eisentraut (#1)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-Jun-24, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are equivalent.
Here is a trivial patch to add that.

Hmm, since this adds to RoleSpec, this change makes every place that
uses that production also take CURRENT_ROLE, so we'd need to document in
all those places. For example, alter_role.sgml, create_schema.sgml,
etc.

This also affects role_list (but maybe the docs for those are already
vague enough -- eg. ALTER INDEX .. OWNED BY only says "role_name" with
no further explanation, even though it does take "current_user".)

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#5Peter Eisentraut
peter.eisentraut@2ndquadrant.com
In reply to: Alvaro Herrera (#4)
1 attachment(s)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-06-24 23:08, Alvaro Herrera wrote:

On 2020-Jun-24, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are equivalent.
Here is a trivial patch to add that.

Hmm, since this adds to RoleSpec, this change makes every place that
uses that production also take CURRENT_ROLE, so we'd need to document in
all those places. For example, alter_role.sgml, create_schema.sgml,
etc.

Good point. Here is an updated patch that updates all the documentation
places where CURRENT_USER is mentioned.

--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

Attachments:

v2-0001-Allow-CURRENT_ROLE-where-CURRENT_USER-is-accepted.patchtext/plain; charset=UTF-8; name=v2-0001-Allow-CURRENT_ROLE-where-CURRENT_USER-is-accepted.patch; x-mac-creator=0; x-mac-type=0Download
From 3dea85cf0391828e02f901ab808dad31422ee30b Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 24 Jun 2020 08:21:48 +0200
Subject: [PATCH v2] Allow CURRENT_ROLE where CURRENT_USER is accepted

In the particular case of GRANTED BY, this is specified in the SQL
standard.  Since in PostgreSQL, CURRENT_ROLE is equivalent to
CURRENT_USER, and CURRENT_USER is already supported here, adding
CURRENT_ROLE is trivial.  The other cases are PostgreSQL extensions,
but for the same reason it also makes sense there.
---
 doc/src/sgml/ref/alter_aggregate.sgml            | 2 +-
 doc/src/sgml/ref/alter_collation.sgml            | 2 +-
 doc/src/sgml/ref/alter_conversion.sgml           | 2 +-
 doc/src/sgml/ref/alter_database.sgml             | 2 +-
 doc/src/sgml/ref/alter_domain.sgml               | 2 +-
 doc/src/sgml/ref/alter_event_trigger.sgml        | 2 +-
 doc/src/sgml/ref/alter_foreign_data_wrapper.sgml | 2 +-
 doc/src/sgml/ref/alter_foreign_table.sgml        | 2 +-
 doc/src/sgml/ref/alter_function.sgml             | 2 +-
 doc/src/sgml/ref/alter_group.sgml                | 1 +
 doc/src/sgml/ref/alter_language.sgml             | 2 +-
 doc/src/sgml/ref/alter_large_object.sgml         | 2 +-
 doc/src/sgml/ref/alter_materialized_view.sgml    | 2 +-
 doc/src/sgml/ref/alter_opclass.sgml              | 2 +-
 doc/src/sgml/ref/alter_operator.sgml             | 2 +-
 doc/src/sgml/ref/alter_opfamily.sgml             | 2 +-
 doc/src/sgml/ref/alter_policy.sgml               | 2 +-
 doc/src/sgml/ref/alter_procedure.sgml            | 2 +-
 doc/src/sgml/ref/alter_publication.sgml          | 2 +-
 doc/src/sgml/ref/alter_role.sgml                 | 2 ++
 doc/src/sgml/ref/alter_routine.sgml              | 2 +-
 doc/src/sgml/ref/alter_schema.sgml               | 2 +-
 doc/src/sgml/ref/alter_sequence.sgml             | 2 +-
 doc/src/sgml/ref/alter_server.sgml               | 2 +-
 doc/src/sgml/ref/alter_statistics.sgml           | 2 +-
 doc/src/sgml/ref/alter_subscription.sgml         | 2 +-
 doc/src/sgml/ref/alter_table.sgml                | 2 +-
 doc/src/sgml/ref/alter_tablespace.sgml           | 2 +-
 doc/src/sgml/ref/alter_tsconfig.sgml             | 2 +-
 doc/src/sgml/ref/alter_tsdictionary.sgml         | 2 +-
 doc/src/sgml/ref/alter_type.sgml                 | 2 +-
 doc/src/sgml/ref/alter_user.sgml                 | 1 +
 doc/src/sgml/ref/alter_user_mapping.sgml         | 4 ++--
 doc/src/sgml/ref/alter_view.sgml                 | 2 +-
 doc/src/sgml/ref/create_policy.sgml              | 2 +-
 doc/src/sgml/ref/create_schema.sgml              | 1 +
 doc/src/sgml/ref/create_tablespace.sgml          | 2 +-
 doc/src/sgml/ref/create_user_mapping.sgml        | 4 ++--
 doc/src/sgml/ref/drop_owned.sgml                 | 2 +-
 doc/src/sgml/ref/drop_user_mapping.sgml          | 4 ++--
 doc/src/sgml/ref/grant.sgml                      | 1 +
 doc/src/sgml/ref/reassign_owned.sgml             | 4 ++--
 doc/src/sgml/ref/revoke.sgml                     | 1 +
 src/backend/parser/gram.y                        | 4 ++++
 44 files changed, 52 insertions(+), 41 deletions(-)

diff --git a/doc/src/sgml/ref/alter_aggregate.sgml b/doc/src/sgml/ref/alter_aggregate.sgml
index 2ad3e0440b..95934a100f 100644
--- a/doc/src/sgml/ref/alter_aggregate.sgml
+++ b/doc/src/sgml/ref/alter_aggregate.sgml
@@ -23,7 +23,7 @@
 <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> | CURRENT_USER | SESSION_USER }
+                OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_collation.sgml b/doc/src/sgml/ref/alter_collation.sgml
index bee6f0dd3c..af9ff2867b 100644
--- a/doc/src/sgml/ref/alter_collation.sgml
+++ b/doc/src/sgml/ref/alter_collation.sgml
@@ -24,7 +24,7 @@
 ALTER COLLATION <replaceable>name</replaceable> REFRESH VERSION
 
 ALTER COLLATION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER COLLATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER COLLATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER COLLATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_conversion.sgml b/doc/src/sgml/ref/alter_conversion.sgml
index c42bd8b3e4..a128f20f3e 100644
--- a/doc/src/sgml/ref/alter_conversion.sgml
+++ b/doc/src/sgml/ref/alter_conversion.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER CONVERSION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER CONVERSION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER CONVERSION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_database.sgml b/doc/src/sgml/ref/alter_database.sgml
index 7db878cf53..81e37536a3 100644
--- a/doc/src/sgml/ref/alter_database.sgml
+++ b/doc/src/sgml/ref/alter_database.sgml
@@ -31,7 +31,7 @@
 
 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> | CURRENT_USER | SESSION_USER }
+ALTER DATABASE <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 
 ALTER DATABASE <replaceable class="parameter">name</replaceable> SET TABLESPACE <replaceable class="parameter">new_tablespace</replaceable>
 
diff --git a/doc/src/sgml/ref/alter_domain.sgml b/doc/src/sgml/ref/alter_domain.sgml
index 8201cbb65f..afa42b4926 100644
--- a/doc/src/sgml/ref/alter_domain.sgml
+++ b/doc/src/sgml/ref/alter_domain.sgml
@@ -36,7 +36,7 @@
 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> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_event_trigger.sgml b/doc/src/sgml/ref/alter_event_trigger.sgml
index 61919f7845..ef5253bf37 100644
--- a/doc/src/sgml/ref/alter_event_trigger.sgml
+++ b/doc/src/sgml/ref/alter_event_trigger.sgml
@@ -23,7 +23,7 @@
 <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> | CURRENT_USER | SESSION_USER }
+ALTER EVENT TRIGGER <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER EVENT TRIGGER <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
index 14f3d616e7..54f34c2c01 100644
--- a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
+++ b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
@@ -25,7 +25,7 @@
     [ 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> | CURRENT_USER | SESSION_USER }
+ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_foreign_table.sgml b/doc/src/sgml/ref/alter_foreign_table.sgml
index 0f11897c99..04d53628ec 100644
--- a/doc/src/sgml/ref/alter_foreign_table.sgml
+++ b/doc/src/sgml/ref/alter_foreign_table.sgml
@@ -53,7 +53,7 @@
     SET WITHOUT OIDS
     INHERIT <replaceable class="parameter">parent_table</replaceable>
     NO INHERIT <replaceable class="parameter">parent_table</replaceable>
-    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
     OPTIONS ( [ ADD | SET | DROP ] <replaceable class="parameter">option</replaceable> ['<replaceable class="parameter">value</replaceable>'] [, ... ])
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml
index 70b1f24bc0..54e61e7d78 100644
--- a/doc/src/sgml/ref/alter_function.sgml
+++ b/doc/src/sgml/ref/alter_function.sgml
@@ -26,7 +26,7 @@
 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> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | 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>
 ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
diff --git a/doc/src/sgml/ref/alter_group.sgml b/doc/src/sgml/ref/alter_group.sgml
index 39cc2b88cf..f6e5163109 100644
--- a/doc/src/sgml/ref/alter_group.sgml
+++ b/doc/src/sgml/ref/alter_group.sgml
@@ -27,6 +27,7 @@
 <phrase>where <replaceable class="parameter">role_specification</replaceable> can be:</phrase>
 
     <replaceable class="parameter">role_name</replaceable>
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 
diff --git a/doc/src/sgml/ref/alter_language.sgml b/doc/src/sgml/ref/alter_language.sgml
index eac63dec13..0b61c18aee 100644
--- a/doc/src/sgml/ref/alter_language.sgml
+++ b/doc/src/sgml/ref/alter_language.sgml
@@ -22,7 +22,7 @@
  <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> | CURRENT_USER | SESSION_USER }
+ALTER [ PROCEDURAL ] LANGUAGE <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/alter_large_object.sgml b/doc/src/sgml/ref/alter_large_object.sgml
index 356f8a8eab..17ea1491ba 100644
--- a/doc/src/sgml/ref/alter_large_object.sgml
+++ b/doc/src/sgml/ref/alter_large_object.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-ALTER LARGE OBJECT <replaceable class="parameter">large_object_oid</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER LARGE OBJECT <replaceable class="parameter">large_object_oid</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/alter_materialized_view.sgml b/doc/src/sgml/ref/alter_materialized_view.sgml
index 9df8a79977..a9935b7629 100644
--- a/doc/src/sgml/ref/alter_materialized_view.sgml
+++ b/doc/src/sgml/ref/alter_materialized_view.sgml
@@ -44,7 +44,7 @@
     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> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/alter_opclass.sgml b/doc/src/sgml/ref/alter_opclass.sgml
index 59a64caa4f..b1db459b11 100644
--- a/doc/src/sgml/ref/alter_opclass.sgml
+++ b/doc/src/sgml/ref/alter_opclass.sgml
@@ -25,7 +25,7 @@
     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 }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 
 ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
     SET SCHEMA <replaceable>new_schema</replaceable>
diff --git a/doc/src/sgml/ref/alter_operator.sgml b/doc/src/sgml/ref/alter_operator.sgml
index b3bfa9ccbe..ac35f229a0 100644
--- a/doc/src/sgml/ref/alter_operator.sgml
+++ b/doc/src/sgml/ref/alter_operator.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 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 }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_opfamily.sgml b/doc/src/sgml/ref/alter_opfamily.sgml
index 4ac1cca95a..59d5bf1070 100644
--- a/doc/src/sgml/ref/alter_opfamily.sgml
+++ b/doc/src/sgml/ref/alter_opfamily.sgml
@@ -37,7 +37,7 @@
     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 }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 
 ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
     SET SCHEMA <replaceable>new_schema</replaceable>
diff --git a/doc/src/sgml/ref/alter_policy.sgml b/doc/src/sgml/ref/alter_policy.sgml
index a1c720a956..1c38324b59 100644
--- a/doc/src/sgml/ref/alter_policy.sgml
+++ b/doc/src/sgml/ref/alter_policy.sgml
@@ -24,7 +24,7 @@
 ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 
 ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
-    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
+    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
     [ USING ( <replaceable class="parameter">using_expression</replaceable> ) ]
     [ WITH CHECK ( <replaceable class="parameter">check_expression</replaceable> ) ]
 </synopsis>
diff --git a/doc/src/sgml/ref/alter_procedure.sgml b/doc/src/sgml/ref/alter_procedure.sgml
index dae80076d9..bcf45c7a85 100644
--- a/doc/src/sgml/ref/alter_procedure.sgml
+++ b/doc/src/sgml/ref/alter_procedure.sgml
@@ -26,7 +26,7 @@
 ALTER PROCEDURE <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 PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
-    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
     SET SCHEMA <replaceable>new_schema</replaceable>
 ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index 534e598d93..c2946dfe0f 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -25,7 +25,7 @@
 ALTER PUBLICATION <replaceable class="parameter">name</replaceable> SET TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ...]
 ALTER PUBLICATION <replaceable class="parameter">name</replaceable> DROP TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ...]
 ALTER PUBLICATION <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">publication_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )
-ALTER PUBLICATION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_role.sgml b/doc/src/sgml/ref/alter_role.sgml
index dbf258ef50..d5f166c129 100644
--- a/doc/src/sgml/ref/alter_role.sgml
+++ b/doc/src/sgml/ref/alter_role.sgml
@@ -46,6 +46,7 @@
 <phrase>where <replaceable class="parameter">role_specification</replaceable> can be:</phrase>
 
     <replaceable class="parameter">role_name</replaceable>
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
@@ -134,6 +135,7 @@ <title>Parameters</title>
      </varlistentry>
 
      <varlistentry>
+      <term><literal>CURRENT_ROLE</literal></term>
       <term><literal>CURRENT_USER</literal></term>
       <listitem>
        <para>
diff --git a/doc/src/sgml/ref/alter_routine.sgml b/doc/src/sgml/ref/alter_routine.sgml
index d1699691e1..36acaff319 100644
--- a/doc/src/sgml/ref/alter_routine.sgml
+++ b/doc/src/sgml/ref/alter_routine.sgml
@@ -26,7 +26,7 @@
 ALTER ROUTINE <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 ROUTINE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
-    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER ROUTINE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
     SET SCHEMA <replaceable>new_schema</replaceable>
 ALTER ROUTINE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
diff --git a/doc/src/sgml/ref/alter_schema.sgml b/doc/src/sgml/ref/alter_schema.sgml
index 2937214026..04624c5a5e 100644
--- a/doc/src/sgml/ref/alter_schema.sgml
+++ b/doc/src/sgml/ref/alter_schema.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER SCHEMA <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER SCHEMA <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/alter_sequence.sgml b/doc/src/sgml/ref/alter_sequence.sgml
index bfd20af6d3..3cd9ece49f 100644
--- a/doc/src/sgml/ref/alter_sequence.sgml
+++ b/doc/src/sgml/ref/alter_sequence.sgml
@@ -31,7 +31,7 @@
     [ 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> | CURRENT_USER | SESSION_USER }
+ALTER SEQUENCE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_server.sgml b/doc/src/sgml/ref/alter_server.sgml
index 17e55b093e..186f38b5f8 100644
--- a/doc/src/sgml/ref/alter_server.sgml
+++ b/doc/src/sgml/ref/alter_server.sgml
@@ -23,7 +23,7 @@
 <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> | CURRENT_USER | SESSION_USER }
+ALTER SERVER <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER SERVER <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_statistics.sgml b/doc/src/sgml/ref/alter_statistics.sgml
index be4c3f1f05..112f5d8924 100644
--- a/doc/src/sgml/ref/alter_statistics.sgml
+++ b/doc/src/sgml/ref/alter_statistics.sgml
@@ -23,7 +23,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-ALTER STATISTICS <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER STATISTICS <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER STATISTICS <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
 ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET STATISTICS <replaceable class="parameter">new_target</replaceable>
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index c24ace14d1..447a5847fc 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -27,7 +27,7 @@
 ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> ENABLE
 ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> DISABLE
 ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">subscription_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )
-ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index cbfb4828e5..cbbc8f2f91 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -82,7 +82,7 @@
     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> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
     REPLICA IDENTITY { DEFAULT | USING INDEX <replaceable class="parameter">index_name</replaceable> | FULL | NOTHING }
 
 <phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase>
diff --git a/doc/src/sgml/ref/alter_tablespace.sgml b/doc/src/sgml/ref/alter_tablespace.sgml
index 356fb9f93f..6de80746d5 100644
--- a/doc/src/sgml/ref/alter_tablespace.sgml
+++ b/doc/src/sgml/ref/alter_tablespace.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 ALTER TABLESPACE <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER TABLESPACE <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER TABLESPACE <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_tsconfig.sgml b/doc/src/sgml/ref/alter_tsconfig.sgml
index ebe0b94b27..8fafcd3bbd 100644
--- a/doc/src/sgml/ref/alter_tsconfig.sgml
+++ b/doc/src/sgml/ref/alter_tsconfig.sgml
@@ -32,7 +32,7 @@
 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> | CURRENT_USER | SESSION_USER }
+ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_tsdictionary.sgml b/doc/src/sgml/ref/alter_tsdictionary.sgml
index b29865e11e..d1923ef160 100644
--- a/doc/src/sgml/ref/alter_tsdictionary.sgml
+++ b/doc/src/sgml/ref/alter_tsdictionary.sgml
@@ -25,7 +25,7 @@
     <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> | CURRENT_USER | SESSION_USER }
+ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_type.sgml b/doc/src/sgml/ref/alter_type.sgml
index f015fcd268..a4f09c660b 100644
--- a/doc/src/sgml/ref/alter_type.sgml
+++ b/doc/src/sgml/ref/alter_type.sgml
@@ -23,7 +23,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-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> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 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>
 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 ]
diff --git a/doc/src/sgml/ref/alter_user.sgml b/doc/src/sgml/ref/alter_user.sgml
index 6769c8ecc4..51527cefb4 100644
--- a/doc/src/sgml/ref/alter_user.sgml
+++ b/doc/src/sgml/ref/alter_user.sgml
@@ -46,6 +46,7 @@
 <phrase>where <replaceable class="parameter">role_specification</replaceable> can be:</phrase>
 
     <replaceable class="parameter">role_name</replaceable>
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/doc/src/sgml/ref/alter_user_mapping.sgml b/doc/src/sgml/ref/alter_user_mapping.sgml
index 7a9b5a188a..ee5aee9bc9 100644
--- a/doc/src/sgml/ref/alter_user_mapping.sgml
+++ b/doc/src/sgml/ref/alter_user_mapping.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-ALTER USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_USER | SESSION_USER | PUBLIC }
+ALTER USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_ROLE | 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>
@@ -51,7 +51,7 @@ <title>Parameters</title>
     <term><replaceable class="parameter">user_name</replaceable></term>
     <listitem>
      <para>
-      User name of the mapping. <literal>CURRENT_USER</literal>
+      User name of the mapping. <literal>CURRENT_ROLE</literal>, <literal>CURRENT_USER</literal>,
       and <literal>USER</literal> match the name of the current
       user. <literal>PUBLIC</literal> is used to match all present and future
       user names in the system.
diff --git a/doc/src/sgml/ref/alter_view.sgml b/doc/src/sgml/ref/alter_view.sgml
index e8d9e11e0f..98c312c5bf 100644
--- a/doc/src/sgml/ref/alter_view.sgml
+++ b/doc/src/sgml/ref/alter_view.sgml
@@ -23,7 +23,7 @@
 <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> | CURRENT_USER | SESSION_USER }
+ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME [ COLUMN ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
 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>
diff --git a/doc/src/sgml/ref/create_policy.sgml b/doc/src/sgml/ref/create_policy.sgml
index 2e1229c4f9..b4f9056101 100644
--- a/doc/src/sgml/ref/create_policy.sgml
+++ b/doc/src/sgml/ref/create_policy.sgml
@@ -24,7 +24,7 @@
 CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
     [ AS { PERMISSIVE | RESTRICTIVE } ]
     [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
-    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
+    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
     [ USING ( <replaceable class="parameter">using_expression</replaceable> ) ]
     [ WITH CHECK ( <replaceable class="parameter">check_expression</replaceable> ) ]
 </synopsis>
diff --git a/doc/src/sgml/ref/create_schema.sgml b/doc/src/sgml/ref/create_schema.sgml
index ffbe1ba3bc..3c2dddb163 100644
--- a/doc/src/sgml/ref/create_schema.sgml
+++ b/doc/src/sgml/ref/create_schema.sgml
@@ -29,6 +29,7 @@
 <phrase>where <replaceable class="parameter">role_specification</replaceable> can be:</phrase>
 
     <replaceable class="parameter">user_name</replaceable>
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/doc/src/sgml/ref/create_tablespace.sgml b/doc/src/sgml/ref/create_tablespace.sgml
index 462b8831c2..84fa7ee5e2 100644
--- a/doc/src/sgml/ref/create_tablespace.sgml
+++ b/doc/src/sgml/ref/create_tablespace.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 CREATE TABLESPACE <replaceable class="parameter">tablespace_name</replaceable>
-    [ OWNER { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER } ]
+    [ OWNER { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER } ]
     LOCATION '<replaceable class="parameter">directory</replaceable>'
     [ WITH ( <replaceable class="parameter">tablespace_option</replaceable> = <replaceable class="parameter">value</replaceable> [, ... ] ) ]
 </synopsis>
diff --git a/doc/src/sgml/ref/create_user_mapping.sgml b/doc/src/sgml/ref/create_user_mapping.sgml
index 9719a4ff2c..55debd5401 100644
--- a/doc/src/sgml/ref/create_user_mapping.sgml
+++ b/doc/src/sgml/ref/create_user_mapping.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-CREATE USER MAPPING [ IF NOT EXISTS ] FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_USER | PUBLIC }
+CREATE USER MAPPING [ IF NOT EXISTS ] FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC }
     SERVER <replaceable class="parameter">server_name</replaceable>
     [ OPTIONS ( <replaceable class="parameter">option</replaceable> '<replaceable class="parameter">value</replaceable>' [ , ... ] ) ]
 </synopsis>
@@ -67,7 +67,7 @@ <title>Parameters</title>
     <listitem>
      <para>
       The name of an existing user that is mapped to foreign server.
-      <literal>CURRENT_USER</literal> and <literal>USER</literal> match the name of
+      <literal>CURRENT_ROLE</literal>, <literal>CURRENT_USER</literal>, and <literal>USER</literal> match the name of
       the current user.  When <literal>PUBLIC</literal> is specified, a
       so-called public mapping is created that is used when no
       user-specific mapping is applicable.
diff --git a/doc/src/sgml/ref/drop_owned.sgml b/doc/src/sgml/ref/drop_owned.sgml
index 09107bef64..dcc375f33b 100644
--- a/doc/src/sgml/ref/drop_owned.sgml
+++ b/doc/src/sgml/ref/drop_owned.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-DROP OWNED BY { <replaceable class="parameter">name</replaceable> | CURRENT_USER | SESSION_USER } [, ...] [ CASCADE | RESTRICT ]
+DROP OWNED BY { <replaceable class="parameter">name</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] [ CASCADE | RESTRICT ]
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/drop_user_mapping.sgml b/doc/src/sgml/ref/drop_user_mapping.sgml
index 7cb09f1166..9e8896a307 100644
--- a/doc/src/sgml/ref/drop_user_mapping.sgml
+++ b/doc/src/sgml/ref/drop_user_mapping.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-DROP USER MAPPING [ IF EXISTS ] FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_USER | PUBLIC } SERVER <replaceable class="parameter">server_name</replaceable>
+DROP USER MAPPING [ IF EXISTS ] FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER <replaceable class="parameter">server_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -59,7 +59,7 @@ <title>Parameters</title>
     <term><replaceable class="parameter">user_name</replaceable></term>
     <listitem>
      <para>
-      User name of the mapping.  <literal>CURRENT_USER</literal>
+      User name of the mapping.  <literal>CURRENT_ROLE</literal>, <literal>CURRENT_USER</literal>,
       and <literal>USER</literal> match the name of the current
       user.  <literal>PUBLIC</literal> is used to match all present and
       future user names in the system.
diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index bc573f7826..fe231aa30c 100644
--- a/doc/src/sgml/ref/grant.sgml
+++ b/doc/src/sgml/ref/grant.sgml
@@ -87,6 +87,7 @@
 
     [ GROUP ] <replaceable class="parameter">role_name</replaceable>
   | PUBLIC
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/doc/src/sgml/ref/reassign_owned.sgml b/doc/src/sgml/ref/reassign_owned.sgml
index 42f72a726f..783389df4e 100644
--- a/doc/src/sgml/ref/reassign_owned.sgml
+++ b/doc/src/sgml/ref/reassign_owned.sgml
@@ -21,8 +21,8 @@
 
  <refsynopsisdiv>
 <synopsis>
-REASSIGN OWNED BY { <replaceable class="parameter">old_role</replaceable> | CURRENT_USER | SESSION_USER } [, ...]
-               TO { <replaceable class="parameter">new_role</replaceable> | CURRENT_USER | SESSION_USER }
+REASSIGN OWNED BY { <replaceable class="parameter">old_role</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...]
+               TO { <replaceable class="parameter">new_role</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml
index b6bac21c57..b50f99dfe7 100644
--- a/doc/src/sgml/ref/revoke.sgml
+++ b/doc/src/sgml/ref/revoke.sgml
@@ -114,6 +114,7 @@
 
     [ GROUP ] <replaceable class="parameter">role_name</replaceable>
   | PUBLIC
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e669d75a5a..6e6565dc26 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -14949,6 +14949,10 @@ RoleSpec:	NonReservedWord
 						}
 						$$ = n;
 					}
+			| CURRENT_ROLE
+					{
+						$$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1);
+					}
 			| CURRENT_USER
 					{
 						$$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1);
-- 
2.27.0

#6Peter Eisentraut
peter.eisentraut@2ndquadrant.com
In reply to: Peter Eisentraut (#5)
1 attachment(s)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-06-29 14:47, Peter Eisentraut wrote:

On 2020-06-24 23:08, Alvaro Herrera wrote:

On 2020-Jun-24, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are equivalent.
Here is a trivial patch to add that.

Hmm, since this adds to RoleSpec, this change makes every place that
uses that production also take CURRENT_ROLE, so we'd need to document in
all those places. For example, alter_role.sgml, create_schema.sgml,
etc.

Good point. Here is an updated patch that updates all the documentation
places where CURRENT_USER is mentioned.

Here is another patch that also makes comprehensive updates to the
rolenames tests under src/test/modules/unsafe_tests/.

I think this should now cover all the required ancillary changes.

--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

Attachments:

v3-0001-Allow-CURRENT_ROLE-where-CURRENT_USER-is-accepted.patchtext/plain; charset=UTF-8; name=v3-0001-Allow-CURRENT_ROLE-where-CURRENT_USER-is-accepted.patch; x-mac-creator=0; x-mac-type=0Download
From 5038b835a5233bac2bd3a17dd4d9406e045661c2 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 26 Aug 2020 08:14:46 +0200
Subject: [PATCH v3] Allow CURRENT_ROLE where CURRENT_USER is accepted

In the particular case of GRANTED BY, this is specified in the SQL
standard.  Since in PostgreSQL, CURRENT_ROLE is equivalent to
CURRENT_USER, and CURRENT_USER is already supported here, adding
CURRENT_ROLE is trivial.  The other cases are PostgreSQL extensions,
but for the same reason it also makes sense there.

Reviewed-by: Vik Fearing <vik@postgresfriends.org>
Discussion: https://www.postgresql.org/message-id/flat/f2feac44-b4c5-f38f-3699-2851d6a76dc9%402ndquadrant.com
---
 doc/src/sgml/ref/alter_aggregate.sgml         |   2 +-
 doc/src/sgml/ref/alter_collation.sgml         |   2 +-
 doc/src/sgml/ref/alter_conversion.sgml        |   2 +-
 doc/src/sgml/ref/alter_database.sgml          |   2 +-
 doc/src/sgml/ref/alter_domain.sgml            |   2 +-
 doc/src/sgml/ref/alter_event_trigger.sgml     |   2 +-
 .../sgml/ref/alter_foreign_data_wrapper.sgml  |   2 +-
 doc/src/sgml/ref/alter_foreign_table.sgml     |   2 +-
 doc/src/sgml/ref/alter_function.sgml          |   2 +-
 doc/src/sgml/ref/alter_group.sgml             |   1 +
 doc/src/sgml/ref/alter_language.sgml          |   2 +-
 doc/src/sgml/ref/alter_large_object.sgml      |   2 +-
 doc/src/sgml/ref/alter_materialized_view.sgml |   2 +-
 doc/src/sgml/ref/alter_opclass.sgml           |   2 +-
 doc/src/sgml/ref/alter_operator.sgml          |   2 +-
 doc/src/sgml/ref/alter_opfamily.sgml          |   2 +-
 doc/src/sgml/ref/alter_policy.sgml            |   2 +-
 doc/src/sgml/ref/alter_procedure.sgml         |   2 +-
 doc/src/sgml/ref/alter_publication.sgml       |   2 +-
 doc/src/sgml/ref/alter_role.sgml              |   2 +
 doc/src/sgml/ref/alter_routine.sgml           |   2 +-
 doc/src/sgml/ref/alter_schema.sgml            |   2 +-
 doc/src/sgml/ref/alter_sequence.sgml          |   2 +-
 doc/src/sgml/ref/alter_server.sgml            |   2 +-
 doc/src/sgml/ref/alter_statistics.sgml        |   2 +-
 doc/src/sgml/ref/alter_subscription.sgml      |   2 +-
 doc/src/sgml/ref/alter_table.sgml             |   2 +-
 doc/src/sgml/ref/alter_tablespace.sgml        |   2 +-
 doc/src/sgml/ref/alter_tsconfig.sgml          |   2 +-
 doc/src/sgml/ref/alter_tsdictionary.sgml      |   2 +-
 doc/src/sgml/ref/alter_type.sgml              |   2 +-
 doc/src/sgml/ref/alter_user.sgml              |   1 +
 doc/src/sgml/ref/alter_user_mapping.sgml      |   4 +-
 doc/src/sgml/ref/alter_view.sgml              |   2 +-
 doc/src/sgml/ref/create_policy.sgml           |   2 +-
 doc/src/sgml/ref/create_schema.sgml           |   1 +
 doc/src/sgml/ref/create_tablespace.sgml       |   2 +-
 doc/src/sgml/ref/create_user_mapping.sgml     |   4 +-
 doc/src/sgml/ref/drop_owned.sgml              |   2 +-
 doc/src/sgml/ref/drop_user_mapping.sgml       |   4 +-
 doc/src/sgml/ref/grant.sgml                   |   1 +
 doc/src/sgml/ref/reassign_owned.sgml          |   4 +-
 doc/src/sgml/ref/revoke.sgml                  |   1 +
 src/backend/parser/gram.y                     |  11 +
 src/backend/utils/adt/acl.c                   |   2 +
 src/include/nodes/parsenodes.h                |   1 +
 .../unsafe_tests/expected/rolenames.out       | 618 ++++++++++--------
 .../modules/unsafe_tests/sql/rolenames.sql    | 221 ++++---
 48 files changed, 530 insertions(+), 412 deletions(-)

diff --git a/doc/src/sgml/ref/alter_aggregate.sgml b/doc/src/sgml/ref/alter_aggregate.sgml
index 2ad3e0440b..95934a100f 100644
--- a/doc/src/sgml/ref/alter_aggregate.sgml
+++ b/doc/src/sgml/ref/alter_aggregate.sgml
@@ -23,7 +23,7 @@
 <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> | CURRENT_USER | SESSION_USER }
+                OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_collation.sgml b/doc/src/sgml/ref/alter_collation.sgml
index bee6f0dd3c..af9ff2867b 100644
--- a/doc/src/sgml/ref/alter_collation.sgml
+++ b/doc/src/sgml/ref/alter_collation.sgml
@@ -24,7 +24,7 @@
 ALTER COLLATION <replaceable>name</replaceable> REFRESH VERSION
 
 ALTER COLLATION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER COLLATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER COLLATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER COLLATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_conversion.sgml b/doc/src/sgml/ref/alter_conversion.sgml
index c42bd8b3e4..a128f20f3e 100644
--- a/doc/src/sgml/ref/alter_conversion.sgml
+++ b/doc/src/sgml/ref/alter_conversion.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER CONVERSION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER CONVERSION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER CONVERSION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_database.sgml b/doc/src/sgml/ref/alter_database.sgml
index 7db878cf53..81e37536a3 100644
--- a/doc/src/sgml/ref/alter_database.sgml
+++ b/doc/src/sgml/ref/alter_database.sgml
@@ -31,7 +31,7 @@
 
 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> | CURRENT_USER | SESSION_USER }
+ALTER DATABASE <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 
 ALTER DATABASE <replaceable class="parameter">name</replaceable> SET TABLESPACE <replaceable class="parameter">new_tablespace</replaceable>
 
diff --git a/doc/src/sgml/ref/alter_domain.sgml b/doc/src/sgml/ref/alter_domain.sgml
index 8201cbb65f..afa42b4926 100644
--- a/doc/src/sgml/ref/alter_domain.sgml
+++ b/doc/src/sgml/ref/alter_domain.sgml
@@ -36,7 +36,7 @@
 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> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_event_trigger.sgml b/doc/src/sgml/ref/alter_event_trigger.sgml
index 61919f7845..ef5253bf37 100644
--- a/doc/src/sgml/ref/alter_event_trigger.sgml
+++ b/doc/src/sgml/ref/alter_event_trigger.sgml
@@ -23,7 +23,7 @@
 <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> | CURRENT_USER | SESSION_USER }
+ALTER EVENT TRIGGER <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER EVENT TRIGGER <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
index 14f3d616e7..54f34c2c01 100644
--- a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
+++ b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
@@ -25,7 +25,7 @@
     [ 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> | CURRENT_USER | SESSION_USER }
+ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_foreign_table.sgml b/doc/src/sgml/ref/alter_foreign_table.sgml
index 0f11897c99..04d53628ec 100644
--- a/doc/src/sgml/ref/alter_foreign_table.sgml
+++ b/doc/src/sgml/ref/alter_foreign_table.sgml
@@ -53,7 +53,7 @@
     SET WITHOUT OIDS
     INHERIT <replaceable class="parameter">parent_table</replaceable>
     NO INHERIT <replaceable class="parameter">parent_table</replaceable>
-    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
     OPTIONS ( [ ADD | SET | DROP ] <replaceable class="parameter">option</replaceable> ['<replaceable class="parameter">value</replaceable>'] [, ... ])
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml
index 70b1f24bc0..54e61e7d78 100644
--- a/doc/src/sgml/ref/alter_function.sgml
+++ b/doc/src/sgml/ref/alter_function.sgml
@@ -26,7 +26,7 @@
 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> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | 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>
 ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
diff --git a/doc/src/sgml/ref/alter_group.sgml b/doc/src/sgml/ref/alter_group.sgml
index 39cc2b88cf..f6e5163109 100644
--- a/doc/src/sgml/ref/alter_group.sgml
+++ b/doc/src/sgml/ref/alter_group.sgml
@@ -27,6 +27,7 @@
 <phrase>where <replaceable class="parameter">role_specification</replaceable> can be:</phrase>
 
     <replaceable class="parameter">role_name</replaceable>
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 
diff --git a/doc/src/sgml/ref/alter_language.sgml b/doc/src/sgml/ref/alter_language.sgml
index eac63dec13..0b61c18aee 100644
--- a/doc/src/sgml/ref/alter_language.sgml
+++ b/doc/src/sgml/ref/alter_language.sgml
@@ -22,7 +22,7 @@
  <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> | CURRENT_USER | SESSION_USER }
+ALTER [ PROCEDURAL ] LANGUAGE <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/alter_large_object.sgml b/doc/src/sgml/ref/alter_large_object.sgml
index 356f8a8eab..17ea1491ba 100644
--- a/doc/src/sgml/ref/alter_large_object.sgml
+++ b/doc/src/sgml/ref/alter_large_object.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-ALTER LARGE OBJECT <replaceable class="parameter">large_object_oid</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER LARGE OBJECT <replaceable class="parameter">large_object_oid</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/alter_materialized_view.sgml b/doc/src/sgml/ref/alter_materialized_view.sgml
index 7321183dd0..78ee99bb9c 100644
--- a/doc/src/sgml/ref/alter_materialized_view.sgml
+++ b/doc/src/sgml/ref/alter_materialized_view.sgml
@@ -44,7 +44,7 @@
     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> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/alter_opclass.sgml b/doc/src/sgml/ref/alter_opclass.sgml
index 59a64caa4f..b1db459b11 100644
--- a/doc/src/sgml/ref/alter_opclass.sgml
+++ b/doc/src/sgml/ref/alter_opclass.sgml
@@ -25,7 +25,7 @@
     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 }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 
 ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
     SET SCHEMA <replaceable>new_schema</replaceable>
diff --git a/doc/src/sgml/ref/alter_operator.sgml b/doc/src/sgml/ref/alter_operator.sgml
index b3bfa9ccbe..ac35f229a0 100644
--- a/doc/src/sgml/ref/alter_operator.sgml
+++ b/doc/src/sgml/ref/alter_operator.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 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 }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_opfamily.sgml b/doc/src/sgml/ref/alter_opfamily.sgml
index 4ac1cca95a..59d5bf1070 100644
--- a/doc/src/sgml/ref/alter_opfamily.sgml
+++ b/doc/src/sgml/ref/alter_opfamily.sgml
@@ -37,7 +37,7 @@
     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 }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 
 ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable>
     SET SCHEMA <replaceable>new_schema</replaceable>
diff --git a/doc/src/sgml/ref/alter_policy.sgml b/doc/src/sgml/ref/alter_policy.sgml
index a1c720a956..1c38324b59 100644
--- a/doc/src/sgml/ref/alter_policy.sgml
+++ b/doc/src/sgml/ref/alter_policy.sgml
@@ -24,7 +24,7 @@
 ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 
 ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
-    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
+    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
     [ USING ( <replaceable class="parameter">using_expression</replaceable> ) ]
     [ WITH CHECK ( <replaceable class="parameter">check_expression</replaceable> ) ]
 </synopsis>
diff --git a/doc/src/sgml/ref/alter_procedure.sgml b/doc/src/sgml/ref/alter_procedure.sgml
index dae80076d9..bcf45c7a85 100644
--- a/doc/src/sgml/ref/alter_procedure.sgml
+++ b/doc/src/sgml/ref/alter_procedure.sgml
@@ -26,7 +26,7 @@
 ALTER PROCEDURE <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 PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
-    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
     SET SCHEMA <replaceable>new_schema</replaceable>
 ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index 534e598d93..c2946dfe0f 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -25,7 +25,7 @@
 ALTER PUBLICATION <replaceable class="parameter">name</replaceable> SET TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ...]
 ALTER PUBLICATION <replaceable class="parameter">name</replaceable> DROP TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ...]
 ALTER PUBLICATION <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">publication_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )
-ALTER PUBLICATION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_role.sgml b/doc/src/sgml/ref/alter_role.sgml
index dbf258ef50..d5f166c129 100644
--- a/doc/src/sgml/ref/alter_role.sgml
+++ b/doc/src/sgml/ref/alter_role.sgml
@@ -46,6 +46,7 @@
 <phrase>where <replaceable class="parameter">role_specification</replaceable> can be:</phrase>
 
     <replaceable class="parameter">role_name</replaceable>
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
@@ -134,6 +135,7 @@ <title>Parameters</title>
      </varlistentry>
 
      <varlistentry>
+      <term><literal>CURRENT_ROLE</literal></term>
       <term><literal>CURRENT_USER</literal></term>
       <listitem>
        <para>
diff --git a/doc/src/sgml/ref/alter_routine.sgml b/doc/src/sgml/ref/alter_routine.sgml
index d1699691e1..36acaff319 100644
--- a/doc/src/sgml/ref/alter_routine.sgml
+++ b/doc/src/sgml/ref/alter_routine.sgml
@@ -26,7 +26,7 @@
 ALTER ROUTINE <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 ROUTINE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
-    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER ROUTINE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
     SET SCHEMA <replaceable>new_schema</replaceable>
 ALTER ROUTINE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
diff --git a/doc/src/sgml/ref/alter_schema.sgml b/doc/src/sgml/ref/alter_schema.sgml
index 2937214026..04624c5a5e 100644
--- a/doc/src/sgml/ref/alter_schema.sgml
+++ b/doc/src/sgml/ref/alter_schema.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER SCHEMA <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER SCHEMA <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/alter_sequence.sgml b/doc/src/sgml/ref/alter_sequence.sgml
index bfd20af6d3..3cd9ece49f 100644
--- a/doc/src/sgml/ref/alter_sequence.sgml
+++ b/doc/src/sgml/ref/alter_sequence.sgml
@@ -31,7 +31,7 @@
     [ 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> | CURRENT_USER | SESSION_USER }
+ALTER SEQUENCE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_server.sgml b/doc/src/sgml/ref/alter_server.sgml
index 17e55b093e..186f38b5f8 100644
--- a/doc/src/sgml/ref/alter_server.sgml
+++ b/doc/src/sgml/ref/alter_server.sgml
@@ -23,7 +23,7 @@
 <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> | CURRENT_USER | SESSION_USER }
+ALTER SERVER <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER SERVER <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_statistics.sgml b/doc/src/sgml/ref/alter_statistics.sgml
index be4c3f1f05..112f5d8924 100644
--- a/doc/src/sgml/ref/alter_statistics.sgml
+++ b/doc/src/sgml/ref/alter_statistics.sgml
@@ -23,7 +23,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-ALTER STATISTICS <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER STATISTICS <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER STATISTICS <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
 ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET STATISTICS <replaceable class="parameter">new_target</replaceable>
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index 81c4e70cdf..36c065c32c 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -27,7 +27,7 @@
 ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> ENABLE
 ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> DISABLE
 ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">subscription_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )
-ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index b2eb7097a9..eec4a3ae2f 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -82,7 +82,7 @@
     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> | CURRENT_USER | SESSION_USER }
+    OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
     REPLICA IDENTITY { DEFAULT | USING INDEX <replaceable class="parameter">index_name</replaceable> | FULL | NOTHING }
 
 <phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase>
diff --git a/doc/src/sgml/ref/alter_tablespace.sgml b/doc/src/sgml/ref/alter_tablespace.sgml
index 356fb9f93f..6de80746d5 100644
--- a/doc/src/sgml/ref/alter_tablespace.sgml
+++ b/doc/src/sgml/ref/alter_tablespace.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 ALTER TABLESPACE <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-ALTER TABLESPACE <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER TABLESPACE <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | 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>
diff --git a/doc/src/sgml/ref/alter_tsconfig.sgml b/doc/src/sgml/ref/alter_tsconfig.sgml
index ebe0b94b27..8fafcd3bbd 100644
--- a/doc/src/sgml/ref/alter_tsconfig.sgml
+++ b/doc/src/sgml/ref/alter_tsconfig.sgml
@@ -32,7 +32,7 @@
 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> | CURRENT_USER | SESSION_USER }
+ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_tsdictionary.sgml b/doc/src/sgml/ref/alter_tsdictionary.sgml
index b29865e11e..d1923ef160 100644
--- a/doc/src/sgml/ref/alter_tsdictionary.sgml
+++ b/doc/src/sgml/ref/alter_tsdictionary.sgml
@@ -25,7 +25,7 @@
     <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> | CURRENT_USER | SESSION_USER }
+ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
 </synopsis>
  </refsynopsisdiv>
diff --git a/doc/src/sgml/ref/alter_type.sgml b/doc/src/sgml/ref/alter_type.sgml
index f015fcd268..a4f09c660b 100644
--- a/doc/src/sgml/ref/alter_type.sgml
+++ b/doc/src/sgml/ref/alter_type.sgml
@@ -23,7 +23,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-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> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 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>
 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 ]
diff --git a/doc/src/sgml/ref/alter_user.sgml b/doc/src/sgml/ref/alter_user.sgml
index 6769c8ecc4..51527cefb4 100644
--- a/doc/src/sgml/ref/alter_user.sgml
+++ b/doc/src/sgml/ref/alter_user.sgml
@@ -46,6 +46,7 @@
 <phrase>where <replaceable class="parameter">role_specification</replaceable> can be:</phrase>
 
     <replaceable class="parameter">role_name</replaceable>
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/doc/src/sgml/ref/alter_user_mapping.sgml b/doc/src/sgml/ref/alter_user_mapping.sgml
index 7a9b5a188a..ee5aee9bc9 100644
--- a/doc/src/sgml/ref/alter_user_mapping.sgml
+++ b/doc/src/sgml/ref/alter_user_mapping.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-ALTER USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_USER | SESSION_USER | PUBLIC }
+ALTER USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_ROLE | 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>
@@ -51,7 +51,7 @@ <title>Parameters</title>
     <term><replaceable class="parameter">user_name</replaceable></term>
     <listitem>
      <para>
-      User name of the mapping. <literal>CURRENT_USER</literal>
+      User name of the mapping. <literal>CURRENT_ROLE</literal>, <literal>CURRENT_USER</literal>,
       and <literal>USER</literal> match the name of the current
       user. <literal>PUBLIC</literal> is used to match all present and future
       user names in the system.
diff --git a/doc/src/sgml/ref/alter_view.sgml b/doc/src/sgml/ref/alter_view.sgml
index e8d9e11e0f..98c312c5bf 100644
--- a/doc/src/sgml/ref/alter_view.sgml
+++ b/doc/src/sgml/ref/alter_view.sgml
@@ -23,7 +23,7 @@
 <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> | CURRENT_USER | SESSION_USER }
+ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME [ COLUMN ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
 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>
diff --git a/doc/src/sgml/ref/create_policy.sgml b/doc/src/sgml/ref/create_policy.sgml
index 2e1229c4f9..b4f9056101 100644
--- a/doc/src/sgml/ref/create_policy.sgml
+++ b/doc/src/sgml/ref/create_policy.sgml
@@ -24,7 +24,7 @@
 CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
     [ AS { PERMISSIVE | RESTRICTIVE } ]
     [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
-    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
+    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
     [ USING ( <replaceable class="parameter">using_expression</replaceable> ) ]
     [ WITH CHECK ( <replaceable class="parameter">check_expression</replaceable> ) ]
 </synopsis>
diff --git a/doc/src/sgml/ref/create_schema.sgml b/doc/src/sgml/ref/create_schema.sgml
index ffbe1ba3bc..3c2dddb163 100644
--- a/doc/src/sgml/ref/create_schema.sgml
+++ b/doc/src/sgml/ref/create_schema.sgml
@@ -29,6 +29,7 @@
 <phrase>where <replaceable class="parameter">role_specification</replaceable> can be:</phrase>
 
     <replaceable class="parameter">user_name</replaceable>
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/doc/src/sgml/ref/create_tablespace.sgml b/doc/src/sgml/ref/create_tablespace.sgml
index 462b8831c2..84fa7ee5e2 100644
--- a/doc/src/sgml/ref/create_tablespace.sgml
+++ b/doc/src/sgml/ref/create_tablespace.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 CREATE TABLESPACE <replaceable class="parameter">tablespace_name</replaceable>
-    [ OWNER { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER } ]
+    [ OWNER { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER } ]
     LOCATION '<replaceable class="parameter">directory</replaceable>'
     [ WITH ( <replaceable class="parameter">tablespace_option</replaceable> = <replaceable class="parameter">value</replaceable> [, ... ] ) ]
 </synopsis>
diff --git a/doc/src/sgml/ref/create_user_mapping.sgml b/doc/src/sgml/ref/create_user_mapping.sgml
index 9719a4ff2c..55debd5401 100644
--- a/doc/src/sgml/ref/create_user_mapping.sgml
+++ b/doc/src/sgml/ref/create_user_mapping.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-CREATE USER MAPPING [ IF NOT EXISTS ] FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_USER | PUBLIC }
+CREATE USER MAPPING [ IF NOT EXISTS ] FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC }
     SERVER <replaceable class="parameter">server_name</replaceable>
     [ OPTIONS ( <replaceable class="parameter">option</replaceable> '<replaceable class="parameter">value</replaceable>' [ , ... ] ) ]
 </synopsis>
@@ -67,7 +67,7 @@ <title>Parameters</title>
     <listitem>
      <para>
       The name of an existing user that is mapped to foreign server.
-      <literal>CURRENT_USER</literal> and <literal>USER</literal> match the name of
+      <literal>CURRENT_ROLE</literal>, <literal>CURRENT_USER</literal>, and <literal>USER</literal> match the name of
       the current user.  When <literal>PUBLIC</literal> is specified, a
       so-called public mapping is created that is used when no
       user-specific mapping is applicable.
diff --git a/doc/src/sgml/ref/drop_owned.sgml b/doc/src/sgml/ref/drop_owned.sgml
index 09107bef64..dcc375f33b 100644
--- a/doc/src/sgml/ref/drop_owned.sgml
+++ b/doc/src/sgml/ref/drop_owned.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-DROP OWNED BY { <replaceable class="parameter">name</replaceable> | CURRENT_USER | SESSION_USER } [, ...] [ CASCADE | RESTRICT ]
+DROP OWNED BY { <replaceable class="parameter">name</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] [ CASCADE | RESTRICT ]
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/drop_user_mapping.sgml b/doc/src/sgml/ref/drop_user_mapping.sgml
index 7cb09f1166..9e8896a307 100644
--- a/doc/src/sgml/ref/drop_user_mapping.sgml
+++ b/doc/src/sgml/ref/drop_user_mapping.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-DROP USER MAPPING [ IF EXISTS ] FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_USER | PUBLIC } SERVER <replaceable class="parameter">server_name</replaceable>
+DROP USER MAPPING [ IF EXISTS ] FOR { <replaceable class="parameter">user_name</replaceable> | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER <replaceable class="parameter">server_name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -59,7 +59,7 @@ <title>Parameters</title>
     <term><replaceable class="parameter">user_name</replaceable></term>
     <listitem>
      <para>
-      User name of the mapping.  <literal>CURRENT_USER</literal>
+      User name of the mapping.  <literal>CURRENT_ROLE</literal>, <literal>CURRENT_USER</literal>,
       and <literal>USER</literal> match the name of the current
       user.  <literal>PUBLIC</literal> is used to match all present and
       future user names in the system.
diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index bc573f7826..fe231aa30c 100644
--- a/doc/src/sgml/ref/grant.sgml
+++ b/doc/src/sgml/ref/grant.sgml
@@ -87,6 +87,7 @@
 
     [ GROUP ] <replaceable class="parameter">role_name</replaceable>
   | PUBLIC
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/doc/src/sgml/ref/reassign_owned.sgml b/doc/src/sgml/ref/reassign_owned.sgml
index 42f72a726f..783389df4e 100644
--- a/doc/src/sgml/ref/reassign_owned.sgml
+++ b/doc/src/sgml/ref/reassign_owned.sgml
@@ -21,8 +21,8 @@
 
  <refsynopsisdiv>
 <synopsis>
-REASSIGN OWNED BY { <replaceable class="parameter">old_role</replaceable> | CURRENT_USER | SESSION_USER } [, ...]
-               TO { <replaceable class="parameter">new_role</replaceable> | CURRENT_USER | SESSION_USER }
+REASSIGN OWNED BY { <replaceable class="parameter">old_role</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...]
+               TO { <replaceable class="parameter">new_role</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml
index b6bac21c57..b50f99dfe7 100644
--- a/doc/src/sgml/ref/revoke.sgml
+++ b/doc/src/sgml/ref/revoke.sgml
@@ -114,6 +114,7 @@
 
     [ GROUP ] <replaceable class="parameter">role_name</replaceable>
   | PUBLIC
+  | CURRENT_ROLE
   | CURRENT_USER
   | SESSION_USER
 </synopsis>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index dbb47d4982..c7f95170a2 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -14915,6 +14915,13 @@ RoleId:		RoleSpec
 											"CURRENT_USER"),
 									 parser_errposition(@1)));
 							break;
+						case ROLESPEC_CURRENT_ROLE:
+							ereport(ERROR,
+									(errcode(ERRCODE_RESERVED_NAME),
+									 errmsg("%s cannot be used as a role name here",
+											"CURRENT_ROLE"),
+									 parser_errposition(@1)));
+							break;
 					}
 				}
 			;
@@ -14946,6 +14953,10 @@ RoleSpec:	NonReservedWord
 						}
 						$$ = n;
 					}
+			| CURRENT_ROLE
+					{
+						$$ = makeRoleSpec(ROLESPEC_CURRENT_ROLE, @1);
+					}
 			| CURRENT_USER
 					{
 						$$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1);
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index de3f49637e..f97489f064 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -5217,6 +5217,7 @@ get_rolespec_oid(const RoleSpec *role, bool missing_ok)
 			oid = get_role_oid(role->rolename, missing_ok);
 			break;
 
+		case ROLESPEC_CURRENT_ROLE:
 		case ROLESPEC_CURRENT_USER:
 			oid = GetUserId();
 			break;
@@ -5259,6 +5260,7 @@ get_rolespec_tuple(const RoleSpec *role)
 						 errmsg("role \"%s\" does not exist", role->rolename)));
 			break;
 
+		case ROLESPEC_CURRENT_ROLE:
 		case ROLESPEC_CURRENT_USER:
 			tuple = SearchSysCache1(AUTHOID, GetUserId());
 			if (!HeapTupleIsValid(tuple))
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 47d4c07306..9b49cbe0d3 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -318,6 +318,7 @@ typedef struct CollateClause
 typedef enum RoleSpecType
 {
 	ROLESPEC_CSTRING,			/* role name is stored as a C string */
+	ROLESPEC_CURRENT_ROLE,		/* role spec is CURRENT_ROLE */
 	ROLESPEC_CURRENT_USER,		/* role spec is CURRENT_USER */
 	ROLESPEC_SESSION_USER,		/* role spec is SESSION_USER */
 	ROLESPEC_PUBLIC				/* role name is "public" */
diff --git a/src/test/modules/unsafe_tests/expected/rolenames.out b/src/test/modules/unsafe_tests/expected/rolenames.out
index ff6aa69fc0..fff55a67c4 100644
--- a/src/test/modules/unsafe_tests/expected/rolenames.out
+++ b/src/test/modules/unsafe_tests/expected/rolenames.out
@@ -3,8 +3,10 @@ CREATE OR REPLACE FUNCTION chkrolattr()
  AS $$
 SELECT r.rolname, v.keyword, r.rolcanlogin, r.rolreplication
  FROM pg_roles r
- JOIN (VALUES(CURRENT_USER, 'current_user'),
+ JOIN (VALUES(CURRENT_ROLE, 'current_role'),
+             (CURRENT_USER, 'current_user'),
              (SESSION_USER, 'session_user'),
+             ('current_role', '-'),
              ('current_user', '-'),
              ('session_user', '-'),
              ('Public', '-'),
@@ -21,8 +23,9 @@ SELECT COALESCE(d.datname, 'ALL'), COALESCE(r.rolname, 'ALL'),
  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'))
+ LEFT JOIN (VALUES(CURRENT_ROLE, 'current_role'),
+                  (CURRENT_USER, 'current_user'),
+                  (SESSION_USER, 'session_user'))
       AS v(uname, keyword)
       ON (r.rolname = v.uname)
    WHERE (r.rolname) IN ('Public', 'current_user', 'regress_testrol1', 'regress_testrol2')
@@ -46,6 +49,7 @@ $$ LANGUAGE SQL;
 SET client_min_messages = ERROR;
 CREATE ROLE "Public";
 CREATE ROLE "None";
+CREATE ROLE "current_role";
 CREATE ROLE "current_user";
 CREATE ROLE "session_user";
 CREATE ROLE "user";
@@ -55,7 +59,7 @@ ERROR:  CURRENT_USER cannot be used as a role name here
 LINE 1: CREATE ROLE current_user;
                     ^
 CREATE ROLE current_role; -- error
-ERROR:  syntax error at or near "current_role"
+ERROR:  CURRENT_ROLE cannot be used as a role name here
 LINE 1: CREATE ROLE current_role;
                     ^
 CREATE ROLE session_user; -- error
@@ -112,23 +116,56 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | f
  current_user     | -            | f        | f
  regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | f
  regress_testrol2 | current_user | f        | f
  session_user     | -            | f        | f
-(6 rows)
+(8 rows)
+
+ALTER ROLE CURRENT_ROLE WITH REPLICATION;
+SELECT * FROM chkrolattr();
+       role       | rolekeyword  | canlogin | replication 
+------------------+--------------+----------+-------------
+ None             | -            | f        | f
+ Public           | -            | f        | f
+ current_role     | -            | f        | f
+ current_user     | -            | f        | f
+ regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | t
+ regress_testrol2 | current_user | f        | t
+ session_user     | -            | f        | f
+(8 rows)
 
+ALTER ROLE "current_role" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+       role       | rolekeyword  | canlogin | replication 
+------------------+--------------+----------+-------------
+ None             | -            | f        | f
+ Public           | -            | f        | f
+ current_role     | -            | f        | t
+ current_user     | -            | f        | f
+ regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | t
+ regress_testrol2 | current_user | f        | t
+ session_user     | -            | f        | f
+(8 rows)
+
+ALTER ROLE CURRENT_ROLE WITH NOREPLICATION;
 ALTER ROLE CURRENT_USER WITH REPLICATION;
 SELECT * FROM chkrolattr();
        role       | rolekeyword  | canlogin | replication 
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | t
  current_user     | -            | f        | f
  regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | f
-(6 rows)
+(8 rows)
 
 ALTER ROLE "current_user" WITH REPLICATION;
 SELECT * FROM chkrolattr();
@@ -136,11 +173,13 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | f
-(6 rows)
+(8 rows)
 
 ALTER ROLE SESSION_USER WITH REPLICATION;
 SELECT * FROM chkrolattr();
@@ -148,11 +187,13 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | t
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | f
-(6 rows)
+(8 rows)
 
 ALTER ROLE "session_user" WITH REPLICATION;
 SELECT * FROM chkrolattr();
@@ -160,11 +201,13 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | t
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | t
-(6 rows)
+(8 rows)
 
 ALTER USER "Public" WITH REPLICATION;
 ALTER USER "None" WITH REPLICATION;
@@ -173,11 +216,13 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | t
  Public           | -            | f        | t
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | t
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | t
-(6 rows)
+(8 rows)
 
 ALTER USER regress_testrol1 WITH NOREPLICATION;
 ALTER USER regress_testrol2 WITH NOREPLICATION;
@@ -186,21 +231,19 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | t
  Public           | -            | f        | t
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | f
  regress_testrol2 | current_user | f        | f
  session_user     | -            | f        | t
-(6 rows)
+(8 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;
@@ -228,23 +271,56 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | f
  current_user     | -            | f        | f
  regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | f
  regress_testrol2 | current_user | f        | f
  session_user     | -            | f        | f
-(6 rows)
+(8 rows)
+
+ALTER USER CURRENT_ROLE WITH REPLICATION;
+SELECT * FROM chkrolattr();
+       role       | rolekeyword  | canlogin | replication 
+------------------+--------------+----------+-------------
+ None             | -            | f        | f
+ Public           | -            | f        | f
+ current_role     | -            | f        | f
+ current_user     | -            | f        | f
+ regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | t
+ regress_testrol2 | current_user | f        | t
+ session_user     | -            | f        | f
+(8 rows)
+
+ALTER USER "current_role" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+       role       | rolekeyword  | canlogin | replication 
+------------------+--------------+----------+-------------
+ None             | -            | f        | f
+ Public           | -            | f        | f
+ current_role     | -            | f        | t
+ current_user     | -            | f        | f
+ regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | t
+ regress_testrol2 | current_user | f        | t
+ session_user     | -            | f        | f
+(8 rows)
 
+ALTER USER CURRENT_ROLE WITH NOREPLICATION;
 ALTER USER CURRENT_USER WITH REPLICATION;
 SELECT * FROM chkrolattr();
        role       | rolekeyword  | canlogin | replication 
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | t
  current_user     | -            | f        | f
  regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | f
-(6 rows)
+(8 rows)
 
 ALTER USER "current_user" WITH REPLICATION;
 SELECT * FROM chkrolattr();
@@ -252,11 +328,13 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | f
-(6 rows)
+(8 rows)
 
 ALTER USER SESSION_USER WITH REPLICATION;
 SELECT * FROM chkrolattr();
@@ -264,11 +342,13 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | t
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | f
-(6 rows)
+(8 rows)
 
 ALTER USER "session_user" WITH REPLICATION;
 SELECT * FROM chkrolattr();
@@ -276,11 +356,13 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | f
  Public           | -            | f        | f
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | t
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | t
-(6 rows)
+(8 rows)
 
 ALTER USER "Public" WITH REPLICATION;
 ALTER USER "None" WITH REPLICATION;
@@ -289,11 +371,13 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | t
  Public           | -            | f        | t
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | t
+ regress_testrol2 | current_role | f        | t
  regress_testrol2 | current_user | f        | t
  session_user     | -            | f        | t
-(6 rows)
+(8 rows)
 
 ALTER USER regress_testrol1 WITH NOREPLICATION;
 ALTER USER regress_testrol2 WITH NOREPLICATION;
@@ -302,21 +386,19 @@ SELECT * FROM chkrolattr();
 ------------------+--------------+----------+-------------
  None             | -            | f        | t
  Public           | -            | f        | t
+ current_role     | -            | f        | t
  current_user     | -            | f        | t
  regress_testrol1 | session_user | t        | f
+ regress_testrol2 | current_role | f        | f
  regress_testrol2 | current_user | f        | f
  session_user     | -            | f        | t
-(6 rows)
+(8 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 "WITH"
 LINE 1: ALTER USER ALL WITH REPLICATION;
@@ -343,6 +425,7 @@ SELECT * FROM chksetconfig();
 ----+------+------------+-----------
 (0 rows)
 
+ALTER ROLE CURRENT_ROLE SET application_name to 'BAZ';
 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';
@@ -355,7 +438,8 @@ SELECT * FROM chksetconfig();
  ALL | current_user     | -            | {application_name=FOOFOO}
  ALL | regress_testrol1 | session_user | {application_name=BAR}
  ALL | regress_testrol2 | current_user | {application_name=FOO}
-(4 rows)
+ ALL | regress_testrol2 | current_role | {application_name=FOO}
+(5 rows)
 
 ALTER ROLE regress_testrol1 SET application_name to 'SLAM';
 SELECT * FROM chksetconfig();
@@ -365,8 +449,10 @@ SELECT * FROM chksetconfig();
  ALL | current_user     | -            | {application_name=FOOFOO}
  ALL | regress_testrol1 | session_user | {application_name=SLAM}
  ALL | regress_testrol2 | current_user | {application_name=FOO}
-(4 rows)
+ ALL | regress_testrol2 | current_role | {application_name=FOO}
+(5 rows)
 
+ALTER ROLE CURRENT_ROLE RESET application_name;
 ALTER ROLE CURRENT_USER RESET application_name;
 ALTER ROLE SESSION_USER RESET application_name;
 ALTER ROLE "current_user" RESET application_name;
@@ -377,10 +463,6 @@ SELECT * FROM chksetconfig();
 ----+------+------------+-----------
 (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';
@@ -395,6 +477,7 @@ SELECT * FROM chksetconfig();
 ----+------+------------+-----------
 (0 rows)
 
+ALTER USER CURRENT_ROLE SET application_name to 'BAZ';
 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';
@@ -407,7 +490,8 @@ SELECT * FROM chksetconfig();
  ALL | current_user     | -            | {application_name=FOOFOO}
  ALL | regress_testrol1 | session_user | {application_name=BAR}
  ALL | regress_testrol2 | current_user | {application_name=FOO}
-(4 rows)
+ ALL | regress_testrol2 | current_role | {application_name=FOO}
+(5 rows)
 
 ALTER USER regress_testrol1 SET application_name to 'SLAM';
 SELECT * FROM chksetconfig();
@@ -417,8 +501,10 @@ SELECT * FROM chksetconfig();
  ALL | current_user     | -            | {application_name=FOOFOO}
  ALL | regress_testrol1 | session_user | {application_name=SLAM}
  ALL | regress_testrol2 | current_user | {application_name=FOO}
-(4 rows)
+ ALL | regress_testrol2 | current_role | {application_name=FOO}
+(5 rows)
 
+ALTER USER CURRENT_ROLE RESET application_name;
 ALTER USER CURRENT_USER RESET application_name;
 ALTER USER SESSION_USER RESET application_name;
 ALTER USER "current_user" RESET application_name;
@@ -429,10 +515,6 @@ SELECT * FROM chksetconfig();
 ----+------+------------+-----------
 (0 rows)
 
-ALTER USER CURRENT_ROLE SET application_name to 'BAZ'; -- error
-ERROR:  syntax error at or near "CURRENT_ROLE"
-LINE 1: ALTER USER CURRENT_ROLE SET application_name to 'BAZ';
-                   ^
 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';
@@ -448,26 +530,23 @@ ERROR:  role "nonexistent" does not exist
 -- CREATE SCHEMA
 CREATE SCHEMA newschema1 AUTHORIZATION CURRENT_USER;
 CREATE SCHEMA newschema2 AUTHORIZATION "current_user";
-CREATE SCHEMA newschema3 AUTHORIZATION SESSION_USER;
-CREATE SCHEMA newschema4 AUTHORIZATION regress_testrolx;
-CREATE SCHEMA newschema5 AUTHORIZATION "Public";
-CREATE SCHEMA newschema6 AUTHORIZATION USER; -- error
+CREATE SCHEMA newschema3 AUTHORIZATION CURRENT_ROLE;
+CREATE SCHEMA newschema4 AUTHORIZATION SESSION_USER;
+CREATE SCHEMA newschema5 AUTHORIZATION regress_testrolx;
+CREATE SCHEMA newschema6 AUTHORIZATION "Public";
+CREATE SCHEMA newschemax AUTHORIZATION USER; -- error
 ERROR:  syntax error at or near "USER"
-LINE 1: CREATE SCHEMA newschema6 AUTHORIZATION USER;
+LINE 1: CREATE SCHEMA newschemax 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
+CREATE SCHEMA newschemax AUTHORIZATION PUBLIC; -- error
 ERROR:  role "public" does not exist
-CREATE SCHEMA newschema6 AUTHORIZATION "public"; -- error
+CREATE SCHEMA newschemax AUTHORIZATION "public"; -- error
 ERROR:  role "public" does not exist
-CREATE SCHEMA newschema6 AUTHORIZATION NONE; -- error
+CREATE SCHEMA newschemax AUTHORIZATION NONE; -- error
 ERROR:  role name "none" is reserved
-LINE 1: CREATE SCHEMA newschema6 AUTHORIZATION NONE;
+LINE 1: CREATE SCHEMA newschemax AUTHORIZATION NONE;
                                                ^
-CREATE SCHEMA newschema6 AUTHORIZATION nonexistent; -- error
+CREATE SCHEMA newschemax 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)
@@ -476,38 +555,37 @@ SELECT n.nspname, r.rolname FROM pg_namespace n
 ------------+------------------
  newschema1 | regress_testrol2
  newschema2 | current_user
- newschema3 | regress_testrol1
- newschema4 | regress_testrolx
- newschema5 | Public
-(5 rows)
+ newschema3 | regress_testrol2
+ newschema4 | regress_testrol1
+ newschema5 | regress_testrolx
+ newschema6 | Public
+(6 rows)
 
 CREATE SCHEMA IF NOT EXISTS newschema1 AUTHORIZATION CURRENT_USER;
 NOTICE:  schema "newschema1" already exists, skipping
 CREATE SCHEMA IF NOT EXISTS newschema2 AUTHORIZATION "current_user";
 NOTICE:  schema "newschema2" already exists, skipping
-CREATE SCHEMA IF NOT EXISTS newschema3 AUTHORIZATION SESSION_USER;
+CREATE SCHEMA IF NOT EXISTS newschema3 AUTHORIZATION CURRENT_ROLE;
 NOTICE:  schema "newschema3" already exists, skipping
-CREATE SCHEMA IF NOT EXISTS newschema4 AUTHORIZATION regress_testrolx;
+CREATE SCHEMA IF NOT EXISTS newschema4 AUTHORIZATION SESSION_USER;
 NOTICE:  schema "newschema4" already exists, skipping
-CREATE SCHEMA IF NOT EXISTS newschema5 AUTHORIZATION "Public";
+CREATE SCHEMA IF NOT EXISTS newschema5 AUTHORIZATION regress_testrolx;
 NOTICE:  schema "newschema5" already exists, skipping
-CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION USER; -- error
+CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION "Public";
+NOTICE:  schema "newschema6" already exists, skipping
+CREATE SCHEMA IF NOT EXISTS newschemax 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...
+LINE 1: CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION USER;
                                                              ^
-CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION PUBLIC; -- error
+CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION PUBLIC; -- error
 ERROR:  role "public" does not exist
-CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION "public"; -- error
+CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION "public"; -- error
 ERROR:  role "public" does not exist
-CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION NONE; -- error
+CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION NONE; -- error
 ERROR:  role name "none" is reserved
-LINE 1: CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION NONE;
+LINE 1: CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION NONE;
                                                              ^
-CREATE SCHEMA IF NOT EXISTS newschema6 AUTHORIZATION nonexistent; -- error
+CREATE SCHEMA IF NOT EXISTS newschemax 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)
@@ -516,10 +594,11 @@ SELECT n.nspname, r.rolname FROM pg_namespace n
 ------------+------------------
  newschema1 | regress_testrol2
  newschema2 | current_user
- newschema3 | regress_testrol1
- newschema4 | regress_testrolx
- newschema5 | Public
-(5 rows)
+ newschema3 | regress_testrol2
+ newschema4 | regress_testrol1
+ newschema5 | regress_testrolx
+ newschema6 | Public
+(6 rows)
 
 -- ALTER TABLE OWNER TO
 \c -
@@ -530,27 +609,25 @@ CREATE TABLE testtab3 (a int);
 CREATE TABLE testtab4 (a int);
 CREATE TABLE testtab5 (a int);
 CREATE TABLE testtab6 (a int);
+CREATE TABLE testtab7 (a int);
 \c -
 SET SESSION AUTHORIZATION regress_testrol1;
 SET ROLE regress_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 regress_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
+ALTER TABLE testtab3 OWNER TO CURRENT_ROLE;
+ALTER TABLE testtab4 OWNER TO SESSION_USER;
+ALTER TABLE testtab5 OWNER TO regress_testrolx;
+ALTER TABLE testtab6 OWNER TO "Public";
+ALTER TABLE testtab7 OWNER TO USER; --error
 ERROR:  syntax error at or near "USER"
-LINE 1: ALTER TABLE testtab6 OWNER TO USER;
+LINE 1: ALTER TABLE testtab7 OWNER TO USER;
                                       ^
-ALTER TABLE testtab6 OWNER TO PUBLIC; -- error
+ALTER TABLE testtab7 OWNER TO PUBLIC; -- error
 ERROR:  role "public" does not exist
-ALTER TABLE testtab6 OWNER TO "public"; -- error
+ALTER TABLE testtab7 OWNER TO "public"; -- error
 ERROR:  role "public" does not exist
-ALTER TABLE testtab6 OWNER TO nonexistent; -- error
+ALTER TABLE testtab7 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)
@@ -560,11 +637,12 @@ SELECT c.relname, r.rolname
 ----------+------------------
  testtab1 | regress_testrol2
  testtab2 | current_user
- testtab3 | regress_testrol1
- testtab4 | regress_testrolx
- testtab5 | Public
- testtab6 | regress_testrol0
-(6 rows)
+ testtab3 | regress_testrol2
+ testtab4 | regress_testrol1
+ testtab5 | regress_testrolx
+ testtab6 | Public
+ testtab7 | regress_testrol0
+(7 rows)
 
 -- ALTER TABLE, VIEW, MATERIALIZED VIEW, FOREIGN TABLE, SEQUENCE are
 -- changed their owner in the same way.
@@ -580,27 +658,25 @@ 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);
+CREATE AGGREGATE testagga(int2) (SFUNC = int2_sum, STYPE = int8);
 \c -
 SET SESSION AUTHORIZATION regress_testrol1;
 SET ROLE regress_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 regress_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
+ALTER AGGREGATE testagg3(int2) OWNER TO CURRENT_ROLE;
+ALTER AGGREGATE testagg4(int2) OWNER TO SESSION_USER;
+ALTER AGGREGATE testagg5(int2) OWNER TO regress_testrolx;
+ALTER AGGREGATE testagg6(int2) OWNER TO "Public";
+ALTER AGGREGATE testagg6(int2) OWNER TO USER; -- error
 ERROR:  syntax error at or near "USER"
-LINE 1: ALTER AGGREGATE testagg5(int2) OWNER TO USER;
+LINE 1: ALTER AGGREGATE testagg6(int2) OWNER TO USER;
                                                 ^
-ALTER AGGREGATE testagg5(int2) OWNER TO PUBLIC; -- error
+ALTER AGGREGATE testagg6(int2) OWNER TO PUBLIC; -- error
 ERROR:  role "public" does not exist
-ALTER AGGREGATE testagg5(int2) OWNER TO "public"; -- error
+ALTER AGGREGATE testagg6(int2) OWNER TO "public"; -- error
 ERROR:  role "public" does not exist
-ALTER AGGREGATE testagg5(int2) OWNER TO nonexistent; -- error
+ALTER AGGREGATE testagg6(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)
@@ -610,14 +686,15 @@ SELECT p.proname, r.rolname
 ----------+------------------
  testagg1 | regress_testrol2
  testagg2 | current_user
- testagg3 | regress_testrol1
- testagg4 | regress_testrolx
- testagg5 | Public
- testagg6 | regress_testrol0
+ testagg3 | regress_testrol2
+ testagg4 | regress_testrol1
+ testagg5 | regress_testrolx
+ testagg6 | Public
  testagg7 | regress_testrol0
  testagg8 | regress_testrol0
  testagg9 | regress_testrol0
-(9 rows)
+ testagga | regress_testrol0
+(10 rows)
 
 -- CREATE USER MAPPING
 CREATE FOREIGN DATA WRAPPER test_wrapper;
@@ -630,58 +707,52 @@ 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 SERVER sv10 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 regress_testrolx SERVER sv8 OPTIONS (user 'regress_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;
+CREATE USER MAPPING FOR CURRENT_ROLE SERVER sv3 OPTIONS (user 'CURRENT_ROLE');
+CREATE USER MAPPING FOR USER SERVER sv4 OPTIONS (user 'USER');
+CREATE USER MAPPING FOR "user" SERVER sv5 OPTIONS (user '"USER"');
+CREATE USER MAPPING FOR SESSION_USER SERVER sv6 OPTIONS (user 'SESSION_USER');
+CREATE USER MAPPING FOR PUBLIC SERVER sv7 OPTIONS (user 'PUBLIC');
+CREATE USER MAPPING FOR "Public" SERVER sv8 OPTIONS (user '"Public"');
+CREATE USER MAPPING FOR regress_testrolx SERVER sv9 OPTIONS (user 'regress_testrolx');
+CREATE USER MAPPING FOR nonexistent SERVER sv10 OPTIONS (user 'nonexistent'); -- error;
 ERROR:  role "nonexistent" does not exist
 SELECT * FROM chkumapping();
       umname      | umserver |         umoptions         
 ------------------+----------+---------------------------
  regress_testrol2 | sv1      | {user=CURRENT_USER}
  current_user     | sv2      | {"user=\"current_user\""}
- regress_testrol2 | sv3      | {user=USER}
- user             | sv4      | {"user=\"USER\""}
- regress_testrol1 | sv5      | {user=SESSION_USER}
-                  | sv6      | {user=PUBLIC}
- Public           | sv7      | {"user=\"Public\""}
- regress_testrolx | sv8      | {user=regress_testrolx}
-(8 rows)
+ regress_testrol2 | sv3      | {user=CURRENT_ROLE}
+ regress_testrol2 | sv4      | {user=USER}
+ user             | sv5      | {"user=\"USER\""}
+ regress_testrol1 | sv6      | {user=SESSION_USER}
+                  | sv7      | {user=PUBLIC}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
+(9 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
+ALTER USER MAPPING FOR CURRENT_ROLE SERVER sv3
+ OPTIONS (SET user 'CURRENT_ROLE_alt');
+ALTER USER MAPPING FOR USER SERVER sv4
  OPTIONS (SET user 'USER_alt');
-ALTER USER MAPPING FOR "user" SERVER sv4
+ALTER USER MAPPING FOR "user" SERVER sv5
  OPTIONS (SET user '"user"_alt');
-ALTER USER MAPPING FOR SESSION_USER SERVER sv5
+ALTER USER MAPPING FOR SESSION_USER SERVER sv6
  OPTIONS (SET user 'SESSION_USER_alt');
-ALTER USER MAPPING FOR PUBLIC SERVER sv6
+ALTER USER MAPPING FOR PUBLIC SERVER sv7
  OPTIONS (SET user 'public_alt');
-ALTER USER MAPPING FOR "Public" SERVER sv7
+ALTER USER MAPPING FOR "Public" SERVER sv8
  OPTIONS (SET user '"Public"_alt');
-ALTER USER MAPPING FOR regress_testrolx SERVER sv8
+ALTER USER MAPPING FOR regress_testrolx SERVER sv9
  OPTIONS (SET user 'regress_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
+ALTER USER MAPPING FOR nonexistent SERVER sv10
  OPTIONS (SET user 'nonexistent_alt'); -- error
 ERROR:  role "nonexistent" does not exist
 SELECT * FROM chkumapping();
@@ -689,28 +760,26 @@ SELECT * FROM chkumapping();
 ------------------+----------+-------------------------------
  regress_testrol2 | sv1      | {user=CURRENT_USER_alt}
  current_user     | sv2      | {"user=\"current_user\"_alt"}
- regress_testrol2 | sv3      | {user=USER_alt}
- user             | sv4      | {"user=\"user\"_alt"}
- regress_testrol1 | sv5      | {user=SESSION_USER_alt}
-                  | sv6      | {user=public_alt}
- Public           | sv7      | {"user=\"Public\"_alt"}
- regress_testrolx | sv8      | {user=regress_testrolx_alt}
-(8 rows)
+ regress_testrol2 | sv3      | {user=CURRENT_ROLE_alt}
+ regress_testrol2 | sv4      | {user=USER_alt}
+ user             | sv5      | {"user=\"user\"_alt"}
+ regress_testrol1 | sv6      | {user=SESSION_USER_alt}
+                  | sv7      | {user=public_alt}
+ Public           | sv8      | {"user=\"Public\"_alt"}
+ regress_testrolx | sv9      | {user=regress_testrolx_alt}
+(9 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 regress_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
+DROP USER MAPPING FOR CURRENT_ROLE SERVER sv3;
+DROP USER MAPPING FOR USER SERVER sv4;
+DROP USER MAPPING FOR "user" SERVER sv5;
+DROP USER MAPPING FOR SESSION_USER SERVER sv6;
+DROP USER MAPPING FOR PUBLIC SERVER sv7;
+DROP USER MAPPING FOR "Public" SERVER sv8;
+DROP USER MAPPING FOR regress_testrolx SERVER sv9;
+DROP USER MAPPING FOR nonexistent SERVER sv10;  -- error
 ERROR:  role "nonexistent" does not exist
 SELECT * FROM chkumapping();
  umname | umserver | umoptions 
@@ -719,24 +788,26 @@ 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 regress_testrolx SERVER sv8 OPTIONS (user 'regress_testrolx');
+CREATE USER MAPPING FOR CURRENT_ROLE SERVER sv3 OPTIONS (user 'CURRENT_ROLE');
+CREATE USER MAPPING FOR USER SERVER sv4 OPTIONS (user 'USER');
+CREATE USER MAPPING FOR "user" SERVER sv5 OPTIONS (user '"USER"');
+CREATE USER MAPPING FOR SESSION_USER SERVER sv6 OPTIONS (user 'SESSION_USER');
+CREATE USER MAPPING FOR PUBLIC SERVER sv7 OPTIONS (user 'PUBLIC');
+CREATE USER MAPPING FOR "Public" SERVER sv8 OPTIONS (user '"Public"');
+CREATE USER MAPPING FOR regress_testrolx SERVER sv9 OPTIONS (user 'regress_testrolx');
 SELECT * FROM chkumapping();
       umname      | umserver |         umoptions         
 ------------------+----------+---------------------------
  regress_testrol2 | sv1      | {user=CURRENT_USER}
  current_user     | sv2      | {"user=\"current_user\""}
- regress_testrol2 | sv3      | {user=USER}
- user             | sv4      | {"user=\"USER\""}
- regress_testrol1 | sv5      | {user=SESSION_USER}
-                  | sv6      | {user=PUBLIC}
- Public           | sv7      | {"user=\"Public\""}
- regress_testrolx | sv8      | {user=regress_testrolx}
-(8 rows)
+ regress_testrol2 | sv3      | {user=CURRENT_ROLE}
+ regress_testrol2 | sv4      | {user=USER}
+ user             | sv5      | {"user=\"USER\""}
+ regress_testrol1 | sv6      | {user=SESSION_USER}
+                  | sv7      | {user=PUBLIC}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
+(9 rows)
 
 -- DROP USER MAPPING IF EXISTS
 DROP USER MAPPING IF EXISTS FOR CURRENT_USER SERVER sv1;
@@ -744,82 +815,92 @@ SELECT * FROM chkumapping();
       umname      | umserver |         umoptions         
 ------------------+----------+---------------------------
  current_user     | sv2      | {"user=\"current_user\""}
- regress_testrol2 | sv3      | {user=USER}
- user             | sv4      | {"user=\"USER\""}
- regress_testrol1 | sv5      | {user=SESSION_USER}
-                  | sv6      | {user=PUBLIC}
- Public           | sv7      | {"user=\"Public\""}
- regress_testrolx | sv8      | {user=regress_testrolx}
-(7 rows)
+ regress_testrol2 | sv3      | {user=CURRENT_ROLE}
+ regress_testrol2 | sv4      | {user=USER}
+ user             | sv5      | {"user=\"USER\""}
+ regress_testrol1 | sv6      | {user=SESSION_USER}
+                  | sv7      | {user=PUBLIC}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
+(8 rows)
 
 DROP USER MAPPING IF EXISTS FOR "current_user" SERVER sv2;
 SELECT * FROM chkumapping();
       umname      | umserver |        umoptions        
 ------------------+----------+-------------------------
- regress_testrol2 | sv3      | {user=USER}
- user             | sv4      | {"user=\"USER\""}
- regress_testrol1 | sv5      | {user=SESSION_USER}
-                  | sv6      | {user=PUBLIC}
- Public           | sv7      | {"user=\"Public\""}
- regress_testrolx | sv8      | {user=regress_testrolx}
+ regress_testrol2 | sv3      | {user=CURRENT_ROLE}
+ regress_testrol2 | sv4      | {user=USER}
+ user             | sv5      | {"user=\"USER\""}
+ regress_testrol1 | sv6      | {user=SESSION_USER}
+                  | sv7      | {user=PUBLIC}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
+(7 rows)
+
+DROP USER MAPPING IF EXISTS FOR CURRENT_USER SERVER sv3;
+SELECT * FROM chkumapping();
+      umname      | umserver |        umoptions        
+------------------+----------+-------------------------
+ regress_testrol2 | sv4      | {user=USER}
+ user             | sv5      | {"user=\"USER\""}
+ regress_testrol1 | sv6      | {user=SESSION_USER}
+                  | sv7      | {user=PUBLIC}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
 (6 rows)
 
-DROP USER MAPPING IF EXISTS FOR USER SERVER sv3;
+DROP USER MAPPING IF EXISTS FOR USER SERVER sv4;
 SELECT * FROM chkumapping();
       umname      | umserver |        umoptions        
 ------------------+----------+-------------------------
- user             | sv4      | {"user=\"USER\""}
- regress_testrol1 | sv5      | {user=SESSION_USER}
-                  | sv6      | {user=PUBLIC}
- Public           | sv7      | {"user=\"Public\""}
- regress_testrolx | sv8      | {user=regress_testrolx}
+ user             | sv5      | {"user=\"USER\""}
+ regress_testrol1 | sv6      | {user=SESSION_USER}
+                  | sv7      | {user=PUBLIC}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
 (5 rows)
 
-DROP USER MAPPING IF EXISTS FOR "user" SERVER sv4;
+DROP USER MAPPING IF EXISTS FOR "user" SERVER sv5;
 SELECT * FROM chkumapping();
       umname      | umserver |        umoptions        
 ------------------+----------+-------------------------
- regress_testrol1 | sv5      | {user=SESSION_USER}
-                  | sv6      | {user=PUBLIC}
- Public           | sv7      | {"user=\"Public\""}
- regress_testrolx | sv8      | {user=regress_testrolx}
+ regress_testrol1 | sv6      | {user=SESSION_USER}
+                  | sv7      | {user=PUBLIC}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
 (4 rows)
 
-DROP USER MAPPING IF EXISTS FOR SESSION_USER SERVER sv5;
+DROP USER MAPPING IF EXISTS FOR SESSION_USER SERVER sv6;
 SELECT * FROM chkumapping();
       umname      | umserver |        umoptions        
 ------------------+----------+-------------------------
-                  | sv6      | {user=PUBLIC}
- Public           | sv7      | {"user=\"Public\""}
- regress_testrolx | sv8      | {user=regress_testrolx}
+                  | sv7      | {user=PUBLIC}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
 (3 rows)
 
-DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER sv6;
+DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER sv7;
 SELECT * FROM chkumapping();
       umname      | umserver |        umoptions        
 ------------------+----------+-------------------------
- Public           | sv7      | {"user=\"Public\""}
- regress_testrolx | sv8      | {user=regress_testrolx}
+ Public           | sv8      | {"user=\"Public\""}
+ regress_testrolx | sv9      | {user=regress_testrolx}
 (2 rows)
 
-DROP USER MAPPING IF EXISTS FOR "Public" SERVER sv7;
+DROP USER MAPPING IF EXISTS FOR "Public" SERVER sv8;
 SELECT * FROM chkumapping();
       umname      | umserver |        umoptions        
 ------------------+----------+-------------------------
- regress_testrolx | sv8      | {user=regress_testrolx}
+ regress_testrolx | sv9      | {user=regress_testrolx}
 (1 row)
 
-DROP USER MAPPING IF EXISTS FOR regress_testrolx SERVER sv8;
+DROP USER MAPPING IF EXISTS FOR regress_testrolx SERVER sv9;
 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
+DROP USER MAPPING IF EXISTS FOR nonexistent SERVER sv10;  -- error
 NOTICE:  role "nonexistent" does not exist, skipping
 -- GRANT/REVOKE
 GRANT regress_testrol0 TO pg_signal_backend; -- success
@@ -840,7 +921,8 @@ SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
  testagg7 | 
  testagg8 | 
  testagg9 | 
-(9 rows)
+ testagga | 
+(10 rows)
 
 REVOKE ALL PRIVILEGES ON FUNCTION testagg1(int2) FROM PUBLIC;
 REVOKE ALL PRIVILEGES ON FUNCTION testagg2(int2) FROM PUBLIC;
@@ -853,108 +935,106 @@ 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 regress_testrolx;
-GRANT ALL PRIVILEGES ON FUNCTION testagg7(int2) TO "public";
-GRANT ALL PRIVILEGES ON FUNCTION testagg8(int2)
+GRANT ALL PRIVILEGES ON FUNCTION testagg4(int2) TO CURRENT_ROLE;
+GRANT ALL PRIVILEGES ON FUNCTION testagg5(int2) TO SESSION_USER;
+GRANT ALL PRIVILEGES ON FUNCTION testagg6(int2) TO "Public";
+GRANT ALL PRIVILEGES ON FUNCTION testagg7(int2) TO regress_testrolx;
+GRANT ALL PRIVILEGES ON FUNCTION testagg8(int2) TO "public";
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2)
  TO current_user, public, regress_testrolx;
 SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
  proname  |                                                              proacl                                                               
 ----------+-----------------------------------------------------------------------------------------------------------------------------------
  testagg1 | {regress_testrol2=X/regress_testrol2,=X/regress_testrol2}
  testagg2 | {current_user=X/current_user,regress_testrol2=X/current_user}
- testagg3 | {regress_testrol1=X/regress_testrol1,current_user=X/regress_testrol1}
- testagg4 | {regress_testrolx=X/regress_testrolx,regress_testrol1=X/regress_testrolx}
- testagg5 | {Public=X/Public}
- testagg6 | {regress_testrol0=X/regress_testrol0,regress_testrolx=X/regress_testrol0}
- testagg7 | {regress_testrol0=X/regress_testrol0,=X/regress_testrol0}
- testagg8 | {regress_testrol0=X/regress_testrol0,regress_testrol2=X/regress_testrol0,=X/regress_testrol0,regress_testrolx=X/regress_testrol0}
- testagg9 | 
-(9 rows)
+ testagg3 | {regress_testrol2=X/regress_testrol2,current_user=X/regress_testrol2}
+ testagg4 | {regress_testrol1=X/regress_testrol1,regress_testrol2=X/regress_testrol1}
+ testagg5 | {regress_testrolx=X/regress_testrolx,regress_testrol1=X/regress_testrolx}
+ testagg6 | {Public=X/Public}
+ testagg7 | {regress_testrol0=X/regress_testrol0,regress_testrolx=X/regress_testrol0}
+ testagg8 | {regress_testrol0=X/regress_testrol0,=X/regress_testrol0}
+ testagg9 | {=X/regress_testrol0,regress_testrol0=X/regress_testrol0,regress_testrol2=X/regress_testrol0,regress_testrolx=X/regress_testrol0}
+ testagga | 
+(10 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
+GRANT ALL PRIVILEGES ON FUNCTION testagga(int2) TO USER; --error
 ERROR:  syntax error at or near "USER"
-LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO USER;
+LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagga(int2) TO USER;
                                                            ^
-GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO NONE; --error
+GRANT ALL PRIVILEGES ON FUNCTION testagga(int2) TO NONE; --error
 ERROR:  role name "none" is reserved
-LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO NONE;
+LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagga(int2) TO NONE;
                                                            ^
-GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO "none"; --error
+GRANT ALL PRIVILEGES ON FUNCTION testagga(int2) TO "none"; --error
 ERROR:  role name "none" is reserved
-LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2) TO "none";
+LINE 1: GRANT ALL PRIVILEGES ON FUNCTION testagga(int2) TO "none";
                                                            ^
 SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
  proname  |                                                              proacl                                                               
 ----------+-----------------------------------------------------------------------------------------------------------------------------------
  testagg1 | {regress_testrol2=X/regress_testrol2,=X/regress_testrol2}
  testagg2 | {current_user=X/current_user,regress_testrol2=X/current_user}
- testagg3 | {regress_testrol1=X/regress_testrol1,current_user=X/regress_testrol1}
- testagg4 | {regress_testrolx=X/regress_testrolx,regress_testrol1=X/regress_testrolx}
- testagg5 | {Public=X/Public}
- testagg6 | {regress_testrol0=X/regress_testrol0,regress_testrolx=X/regress_testrol0}
- testagg7 | {regress_testrol0=X/regress_testrol0,=X/regress_testrol0}
- testagg8 | {regress_testrol0=X/regress_testrol0,regress_testrol2=X/regress_testrol0,=X/regress_testrol0,regress_testrolx=X/regress_testrol0}
- testagg9 | 
-(9 rows)
+ testagg3 | {regress_testrol2=X/regress_testrol2,current_user=X/regress_testrol2}
+ testagg4 | {regress_testrol1=X/regress_testrol1,regress_testrol2=X/regress_testrol1}
+ testagg5 | {regress_testrolx=X/regress_testrolx,regress_testrol1=X/regress_testrolx}
+ testagg6 | {Public=X/Public}
+ testagg7 | {regress_testrol0=X/regress_testrol0,regress_testrolx=X/regress_testrol0}
+ testagg8 | {regress_testrol0=X/regress_testrol0,=X/regress_testrol0}
+ testagg9 | {=X/regress_testrol0,regress_testrol0=X/regress_testrol0,regress_testrol2=X/regress_testrol0,regress_testrolx=X/regress_testrol0}
+ testagga | 
+(10 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 regress_testrolx;
-REVOKE ALL PRIVILEGES ON FUNCTION testagg7(int2) FROM "public";
-REVOKE ALL PRIVILEGES ON FUNCTION testagg8(int2)
+REVOKE ALL PRIVILEGES ON FUNCTION testagg4(int2) FROM CURRENT_ROLE;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg5(int2) FROM SESSION_USER;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg6(int2) FROM "Public";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg7(int2) FROM regress_testrolx;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg8(int2) FROM "public";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2)
  FROM current_user, public, regress_testrolx;
 SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
  proname  |                proacl                 
 ----------+---------------------------------------
  testagg1 | {regress_testrol2=X/regress_testrol2}
  testagg2 | {current_user=X/current_user}
- testagg3 | {regress_testrol1=X/regress_testrol1}
- testagg4 | {regress_testrolx=X/regress_testrolx}
- testagg5 | {}
- testagg6 | {regress_testrol0=X/regress_testrol0}
+ testagg3 | {regress_testrol2=X/regress_testrol2}
+ testagg4 | {regress_testrol1=X/regress_testrol1}
+ testagg5 | {regress_testrolx=X/regress_testrolx}
+ testagg6 | {}
  testagg7 | {regress_testrol0=X/regress_testrol0}
  testagg8 | {regress_testrol0=X/regress_testrol0}
- testagg9 | 
-(9 rows)
+ testagg9 | {regress_testrol0=X/regress_testrol0}
+ testagga | 
+(10 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
+REVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM USER; --error
 ERROR:  syntax error at or near "USER"
-LINE 1: REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM USER;
+LINE 1: REVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM USER;
                                                               ^
-REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM NONE; --error
+REVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM NONE; --error
 ERROR:  role name "none" is reserved
-LINE 1: REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM NONE;
+LINE 1: REVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM NONE;
                                                               ^
-REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM "none"; --error
+REVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM "none"; --error
 ERROR:  role name "none" is reserved
-LINE 1: ...EVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2) FROM "none";
+LINE 1: ...EVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM "none";
                                                                 ^
 SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
  proname  |                proacl                 
 ----------+---------------------------------------
  testagg1 | {regress_testrol2=X/regress_testrol2}
  testagg2 | {current_user=X/current_user}
- testagg3 | {regress_testrol1=X/regress_testrol1}
- testagg4 | {regress_testrolx=X/regress_testrolx}
- testagg5 | {}
- testagg6 | {regress_testrol0=X/regress_testrol0}
+ testagg3 | {regress_testrol2=X/regress_testrol2}
+ testagg4 | {regress_testrol1=X/regress_testrol1}
+ testagg5 | {regress_testrolx=X/regress_testrolx}
+ testagg6 | {}
  testagg7 | {regress_testrol0=X/regress_testrol0}
  testagg8 | {regress_testrol0=X/regress_testrol0}
- testagg9 | 
-(9 rows)
+ testagg9 | {regress_testrol0=X/regress_testrol0}
+ testagga | 
+(10 rows)
 
 -- DEFAULT MONITORING ROLES
 CREATE ROLE regress_role_haspriv;
diff --git a/src/test/modules/unsafe_tests/sql/rolenames.sql b/src/test/modules/unsafe_tests/sql/rolenames.sql
index c3013c1464..9227de9e8c 100644
--- a/src/test/modules/unsafe_tests/sql/rolenames.sql
+++ b/src/test/modules/unsafe_tests/sql/rolenames.sql
@@ -3,8 +3,10 @@ CREATE OR REPLACE FUNCTION chkrolattr()
  AS $$
 SELECT r.rolname, v.keyword, r.rolcanlogin, r.rolreplication
  FROM pg_roles r
- JOIN (VALUES(CURRENT_USER, 'current_user'),
+ JOIN (VALUES(CURRENT_ROLE, 'current_role'),
+             (CURRENT_USER, 'current_user'),
              (SESSION_USER, 'session_user'),
+             ('current_role', '-'),
              ('current_user', '-'),
              ('session_user', '-'),
              ('Public', '-'),
@@ -22,8 +24,9 @@ CREATE OR REPLACE FUNCTION chksetconfig()
  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'))
+ LEFT JOIN (VALUES(CURRENT_ROLE, 'current_role'),
+                  (CURRENT_USER, 'current_user'),
+                  (SESSION_USER, 'session_user'))
       AS v(uname, keyword)
       ON (r.rolname = v.uname)
    WHERE (r.rolname) IN ('Public', 'current_user', 'regress_testrol1', 'regress_testrol2')
@@ -50,6 +53,7 @@ CREATE OR REPLACE FUNCTION chkumapping()
 
 CREATE ROLE "Public";
 CREATE ROLE "None";
+CREATE ROLE "current_role";
 CREATE ROLE "current_user";
 CREATE ROLE "session_user";
 CREATE ROLE "user";
@@ -84,6 +88,11 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 --  ALTER ROLE
 BEGIN;
 SELECT * FROM chkrolattr();
+ALTER ROLE CURRENT_ROLE WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER ROLE "current_role" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER ROLE CURRENT_ROLE WITH NOREPLICATION;
 ALTER ROLE CURRENT_USER WITH REPLICATION;
 SELECT * FROM chkrolattr();
 ALTER ROLE "current_user" WITH REPLICATION;
@@ -101,7 +110,6 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 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
@@ -113,6 +121,11 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 --  ALTER USER
 BEGIN;
 SELECT * FROM chkrolattr();
+ALTER USER CURRENT_ROLE WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER "current_role" WITH REPLICATION;
+SELECT * FROM chkrolattr();
+ALTER USER CURRENT_ROLE WITH NOREPLICATION;
 ALTER USER CURRENT_USER WITH REPLICATION;
 SELECT * FROM chkrolattr();
 ALTER USER "current_user" WITH REPLICATION;
@@ -130,7 +143,6 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 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
@@ -141,6 +153,7 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 
 --  ALTER ROLE SET/RESET
 SELECT * FROM chksetconfig();
+ALTER ROLE CURRENT_ROLE SET application_name to 'BAZ';
 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';
@@ -149,6 +162,7 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 SELECT * FROM chksetconfig();
 ALTER ROLE regress_testrol1 SET application_name to 'SLAM';
 SELECT * FROM chksetconfig();
+ALTER ROLE CURRENT_ROLE RESET application_name;
 ALTER ROLE CURRENT_USER RESET application_name;
 ALTER ROLE SESSION_USER RESET application_name;
 ALTER ROLE "current_user" RESET application_name;
@@ -157,13 +171,13 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 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_ROLE SET application_name to 'BAZ';
 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';
@@ -172,6 +186,7 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 SELECT * FROM chksetconfig();
 ALTER USER regress_testrol1 SET application_name to 'SLAM';
 SELECT * FROM chksetconfig();
+ALTER USER CURRENT_ROLE RESET application_name;
 ALTER USER CURRENT_USER RESET application_name;
 ALTER USER SESSION_USER RESET application_name;
 ALTER USER "current_user" RESET application_name;
@@ -180,7 +195,6 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 SELECT * FROM chksetconfig();
 
 
-ALTER USER CURRENT_ROLE 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
@@ -189,16 +203,16 @@ CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2;
 -- CREATE SCHEMA
 CREATE SCHEMA newschema1 AUTHORIZATION CURRENT_USER;
 CREATE SCHEMA newschema2 AUTHORIZATION "current_user";
-CREATE SCHEMA newschema3 AUTHORIZATION SESSION_USER;
-CREATE SCHEMA newschema4 AUTHORIZATION regress_testrolx;
-CREATE SCHEMA newschema5 AUTHORIZATION "Public";
+CREATE SCHEMA newschema3 AUTHORIZATION CURRENT_ROLE;
+CREATE SCHEMA newschema4 AUTHORIZATION SESSION_USER;
+CREATE SCHEMA newschema5 AUTHORIZATION regress_testrolx;
+CREATE SCHEMA newschema6 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
+CREATE SCHEMA newschemax AUTHORIZATION USER; -- error
+CREATE SCHEMA newschemax AUTHORIZATION PUBLIC; -- error
+CREATE SCHEMA newschemax AUTHORIZATION "public"; -- error
+CREATE SCHEMA newschemax AUTHORIZATION NONE; -- error
+CREATE SCHEMA newschemax AUTHORIZATION nonexistent; -- error
 
 SELECT n.nspname, r.rolname FROM pg_namespace n
  JOIN pg_roles r ON (r.oid = n.nspowner)
@@ -206,16 +220,16 @@ CREATE SCHEMA newschema6 AUTHORIZATION nonexistent; -- error
 
 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 regress_testrolx;
-CREATE SCHEMA IF NOT EXISTS newschema5 AUTHORIZATION "Public";
+CREATE SCHEMA IF NOT EXISTS newschema3 AUTHORIZATION CURRENT_ROLE;
+CREATE SCHEMA IF NOT EXISTS newschema4 AUTHORIZATION SESSION_USER;
+CREATE SCHEMA IF NOT EXISTS newschema5 AUTHORIZATION regress_testrolx;
+CREATE SCHEMA IF NOT EXISTS newschema6 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
+CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION USER; -- error
+CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION PUBLIC; -- error
+CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION "public"; -- error
+CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION NONE; -- error
+CREATE SCHEMA IF NOT EXISTS newschemax AUTHORIZATION nonexistent; -- error
 
 SELECT n.nspname, r.rolname FROM pg_namespace n
  JOIN pg_roles r ON (r.oid = n.nspowner)
@@ -230,6 +244,7 @@ CREATE TABLE testtab3 (a int);
 CREATE TABLE testtab4 (a int);
 CREATE TABLE testtab5 (a int);
 CREATE TABLE testtab6 (a int);
+CREATE TABLE testtab7 (a int);
 
 \c -
 SET SESSION AUTHORIZATION regress_testrol1;
@@ -237,15 +252,15 @@ CREATE TABLE testtab6 (a int);
 
 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 regress_testrolx;
-ALTER TABLE testtab5 OWNER TO "Public";
+ALTER TABLE testtab3 OWNER TO CURRENT_ROLE;
+ALTER TABLE testtab4 OWNER TO SESSION_USER;
+ALTER TABLE testtab5 OWNER TO regress_testrolx;
+ALTER TABLE testtab6 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
+ALTER TABLE testtab7 OWNER TO USER; --error
+ALTER TABLE testtab7 OWNER TO PUBLIC; -- error
+ALTER TABLE testtab7 OWNER TO "public"; -- error
+ALTER TABLE testtab7 OWNER TO nonexistent; -- error
 
 SELECT c.relname, r.rolname
  FROM pg_class c JOIN pg_roles r ON (r.oid = c.relowner)
@@ -267,6 +282,7 @@ 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);
+CREATE AGGREGATE testagga(int2) (SFUNC = int2_sum, STYPE = int8);
 
 \c -
 SET SESSION AUTHORIZATION regress_testrol1;
@@ -274,15 +290,15 @@ CREATE AGGREGATE testagg9(int2) (SFUNC = int2_sum, STYPE = int8);
 
 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 regress_testrolx;
-ALTER AGGREGATE testagg5(int2) OWNER TO "Public";
+ALTER AGGREGATE testagg3(int2) OWNER TO CURRENT_ROLE;
+ALTER AGGREGATE testagg4(int2) OWNER TO SESSION_USER;
+ALTER AGGREGATE testagg5(int2) OWNER TO regress_testrolx;
+ALTER AGGREGATE testagg6(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
+ALTER AGGREGATE testagg6(int2) OWNER TO USER; -- error
+ALTER AGGREGATE testagg6(int2) OWNER TO PUBLIC; -- error
+ALTER AGGREGATE testagg6(int2) OWNER TO "public"; -- error
+ALTER AGGREGATE testagg6(int2) OWNER TO nonexistent; -- error
 
 SELECT p.proname, r.rolname
  FROM pg_proc p JOIN pg_roles r ON (r.oid = p.proowner)
@@ -300,20 +316,19 @@ 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 SERVER sv10 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 regress_testrolx SERVER sv8 OPTIONS (user 'regress_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;
+CREATE USER MAPPING FOR CURRENT_ROLE SERVER sv3 OPTIONS (user 'CURRENT_ROLE');
+CREATE USER MAPPING FOR USER SERVER sv4 OPTIONS (user 'USER');
+CREATE USER MAPPING FOR "user" SERVER sv5 OPTIONS (user '"USER"');
+CREATE USER MAPPING FOR SESSION_USER SERVER sv6 OPTIONS (user 'SESSION_USER');
+CREATE USER MAPPING FOR PUBLIC SERVER sv7 OPTIONS (user 'PUBLIC');
+CREATE USER MAPPING FOR "Public" SERVER sv8 OPTIONS (user '"Public"');
+CREATE USER MAPPING FOR regress_testrolx SERVER sv9 OPTIONS (user 'regress_testrolx');
+
+CREATE USER MAPPING FOR nonexistent SERVER sv10 OPTIONS (user 'nonexistent'); -- error;
 
 SELECT * FROM chkumapping();
 
@@ -322,22 +337,22 @@ CREATE USER MAPPING FOR nonexistent SERVER sv9
  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
+ALTER USER MAPPING FOR CURRENT_ROLE SERVER sv3
+ OPTIONS (SET user 'CURRENT_ROLE_alt');
+ALTER USER MAPPING FOR USER SERVER sv4
  OPTIONS (SET user 'USER_alt');
-ALTER USER MAPPING FOR "user" SERVER sv4
+ALTER USER MAPPING FOR "user" SERVER sv5
  OPTIONS (SET user '"user"_alt');
-ALTER USER MAPPING FOR SESSION_USER SERVER sv5
+ALTER USER MAPPING FOR SESSION_USER SERVER sv6
  OPTIONS (SET user 'SESSION_USER_alt');
-ALTER USER MAPPING FOR PUBLIC SERVER sv6
+ALTER USER MAPPING FOR PUBLIC SERVER sv7
  OPTIONS (SET user 'public_alt');
-ALTER USER MAPPING FOR "Public" SERVER sv7
+ALTER USER MAPPING FOR "Public" SERVER sv8
  OPTIONS (SET user '"Public"_alt');
-ALTER USER MAPPING FOR regress_testrolx SERVER sv8
+ALTER USER MAPPING FOR regress_testrolx SERVER sv9
  OPTIONS (SET user 'regress_testrolx_alt');
 
-ALTER USER MAPPING FOR CURRENT_ROLE SERVER sv9
- OPTIONS (SET user 'CURRENT_ROLE_alt');
-ALTER USER MAPPING FOR nonexistent SERVER sv9
+ALTER USER MAPPING FOR nonexistent SERVER sv10
  OPTIONS (SET user 'nonexistent_alt'); -- error
 
 SELECT * FROM chkumapping();
@@ -345,25 +360,26 @@ CREATE USER MAPPING FOR nonexistent SERVER sv9
 -- 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 regress_testrolx SERVER sv8;
-
-DROP USER MAPPING FOR CURRENT_ROLE SERVER sv9; -- error
-DROP USER MAPPING FOR nonexistent SERVER sv;  -- error
+DROP USER MAPPING FOR CURRENT_ROLE SERVER sv3;
+DROP USER MAPPING FOR USER SERVER sv4;
+DROP USER MAPPING FOR "user" SERVER sv5;
+DROP USER MAPPING FOR SESSION_USER SERVER sv6;
+DROP USER MAPPING FOR PUBLIC SERVER sv7;
+DROP USER MAPPING FOR "Public" SERVER sv8;
+DROP USER MAPPING FOR regress_testrolx SERVER sv9;
+
+DROP USER MAPPING FOR nonexistent SERVER sv10;  -- 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 regress_testrolx SERVER sv8 OPTIONS (user 'regress_testrolx');
+CREATE USER MAPPING FOR CURRENT_ROLE SERVER sv3 OPTIONS (user 'CURRENT_ROLE');
+CREATE USER MAPPING FOR USER SERVER sv4 OPTIONS (user 'USER');
+CREATE USER MAPPING FOR "user" SERVER sv5 OPTIONS (user '"USER"');
+CREATE USER MAPPING FOR SESSION_USER SERVER sv6 OPTIONS (user 'SESSION_USER');
+CREATE USER MAPPING FOR PUBLIC SERVER sv7 OPTIONS (user 'PUBLIC');
+CREATE USER MAPPING FOR "Public" SERVER sv8 OPTIONS (user '"Public"');
+CREATE USER MAPPING FOR regress_testrolx SERVER sv9 OPTIONS (user 'regress_testrolx');
 SELECT * FROM chkumapping();
 
 -- DROP USER MAPPING IF EXISTS
@@ -371,21 +387,22 @@ CREATE USER MAPPING FOR regress_testrolx SERVER sv8 OPTIONS (user 'regress_testr
 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;
+DROP USER MAPPING IF EXISTS FOR CURRENT_USER SERVER sv3;
+SELECT * FROM chkumapping();
+DROP USER MAPPING IF EXISTS FOR USER SERVER sv4;
 SELECT * FROM chkumapping();
-DROP USER MAPPING IF EXISTS FOR "user" SERVER sv4;
+DROP USER MAPPING IF EXISTS FOR "user" SERVER sv5;
 SELECT * FROM chkumapping();
-DROP USER MAPPING IF EXISTS FOR SESSION_USER SERVER sv5;
+DROP USER MAPPING IF EXISTS FOR SESSION_USER SERVER sv6;
 SELECT * FROM chkumapping();
-DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER sv6;
+DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER sv7;
 SELECT * FROM chkumapping();
-DROP USER MAPPING IF EXISTS FOR "Public" SERVER sv7;
+DROP USER MAPPING IF EXISTS FOR "Public" SERVER sv8;
 SELECT * FROM chkumapping();
-DROP USER MAPPING IF EXISTS FOR regress_testrolx SERVER sv8;
+DROP USER MAPPING IF EXISTS FOR regress_testrolx SERVER sv9;
 SELECT * FROM chkumapping();
 
-DROP USER MAPPING IF EXISTS FOR CURRENT_ROLE SERVER sv9; --error
-DROP USER MAPPING IF EXISTS FOR nonexistent SERVER sv9;  -- error
+DROP USER MAPPING IF EXISTS FOR nonexistent SERVER sv10;  -- error
 
 -- GRANT/REVOKE
 GRANT regress_testrol0 TO pg_signal_backend; -- success
@@ -410,38 +427,38 @@ CREATE SCHEMA test_roles_schema AUTHORIZATION pg_signal_backend; --success
 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 regress_testrolx;
-GRANT ALL PRIVILEGES ON FUNCTION testagg7(int2) TO "public";
-GRANT ALL PRIVILEGES ON FUNCTION testagg8(int2)
+GRANT ALL PRIVILEGES ON FUNCTION testagg4(int2) TO CURRENT_ROLE;
+GRANT ALL PRIVILEGES ON FUNCTION testagg5(int2) TO SESSION_USER;
+GRANT ALL PRIVILEGES ON FUNCTION testagg6(int2) TO "Public";
+GRANT ALL PRIVILEGES ON FUNCTION testagg7(int2) TO regress_testrolx;
+GRANT ALL PRIVILEGES ON FUNCTION testagg8(int2) TO "public";
+GRANT ALL PRIVILEGES ON FUNCTION testagg9(int2)
  TO current_user, public, regress_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
+GRANT ALL PRIVILEGES ON FUNCTION testagga(int2) TO USER; --error
+GRANT ALL PRIVILEGES ON FUNCTION testagga(int2) TO NONE; --error
+GRANT ALL PRIVILEGES ON FUNCTION testagga(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 regress_testrolx;
-REVOKE ALL PRIVILEGES ON FUNCTION testagg7(int2) FROM "public";
-REVOKE ALL PRIVILEGES ON FUNCTION testagg8(int2)
+REVOKE ALL PRIVILEGES ON FUNCTION testagg4(int2) FROM CURRENT_ROLE;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg5(int2) FROM SESSION_USER;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg6(int2) FROM "Public";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg7(int2) FROM regress_testrolx;
+REVOKE ALL PRIVILEGES ON FUNCTION testagg8(int2) FROM "public";
+REVOKE ALL PRIVILEGES ON FUNCTION testagg9(int2)
  FROM current_user, public, regress_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
+REVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM USER; --error
+REVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM NONE; --error
+REVOKE ALL PRIVILEGES ON FUNCTION testagga(int2) FROM "none"; --error
 
 SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';
 
-- 
2.28.0

#7Asif Rehman
asifr.rehman@gmail.com
In reply to: Peter Eisentraut (#6)
Re: Allow CURRENT_ROLE in GRANTED BY

The following review has been posted through the commitfest application:
make installcheck-world: tested, passed
Implements feature: tested, passed
Spec compliant: tested, passed
Documentation: tested, passed

The patch applies cleanly and looks fine to me. However wouldn't it be better to just map the CURRENT_ROLE to CURRENT_USER in backend grammar?

The new status of this patch is: Waiting on Author

#8Peter Eisentraut
peter.eisentraut@2ndquadrant.com
In reply to: Asif Rehman (#7)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-09-07 12:02, Asif Rehman wrote:

The following review has been posted through the commitfest application:
make installcheck-world: tested, passed
Implements feature: tested, passed
Spec compliant: tested, passed
Documentation: tested, passed

The patch applies cleanly and looks fine to me. However wouldn't it be better to just map the CURRENT_ROLE to CURRENT_USER in backend grammar?

Existing code treats them differently. I think, given that the code is
already written, it is good to preserve what the user wrote.

--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#9Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Peter Eisentraut (#6)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-Aug-26, Peter Eisentraut wrote:

Here is another patch that also makes comprehensive updates to the rolenames
tests under src/test/modules/unsafe_tests/.

Looks good to me. You need to DROP ROLE "current_role" at the bottom of
rolenames.sql, though (as well as DROP OWNED BY, I suppose.)

I think this should now cover all the required ancillary changes.

\o/

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#10Peter Eisentraut
peter.eisentraut@2ndquadrant.com
In reply to: Alvaro Herrera (#9)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-09-11 22:05, Alvaro Herrera wrote:

On 2020-Aug-26, Peter Eisentraut wrote:

Here is another patch that also makes comprehensive updates to the rolenames
tests under src/test/modules/unsafe_tests/.

Looks good to me. You need to DROP ROLE "current_role" at the bottom of
rolenames.sql, though (as well as DROP OWNED BY, I suppose.)

I think this should now cover all the required ancillary changes.

\o/

committed

--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#10)
Re: Allow CURRENT_ROLE in GRANTED BY
#12Peter Eisentraut
peter.eisentraut@2ndquadrant.com
In reply to: Peter Eisentraut (#3)
1 attachment(s)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-06-24 20:21, Peter Eisentraut wrote:

On 2020-06-24 10:12, Vik Fearing wrote:

On 6/24/20 8:35 AM, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are
equivalent.  Here is a trivial patch to add that.

The only thing that isn't dead-obvious about this patch is the commit
message says "[PATCH 1/2]". What is in the other part?

Hehe. The second patch is some in-progress work to add the GRANTED BY
clause to the regular GRANT command. More on that perhaps at a later date.

Here is the highly anticipated and quite underwhelming second part of
this patch set.

--
Peter Eisentraut
2ndQuadrant, an EDB company
https://www.2ndquadrant.com/

Attachments:

0001-Allow-GRANTED-BY-clause-in-normal-GRANT-and-REVOKE-s.patchtext/plain; charset=UTF-8; name=0001-Allow-GRANTED-BY-clause-in-normal-GRANT-and-REVOKE-s.patch; x-mac-creator=0; x-mac-type=0Download
From 72b1e99337b6fc9e72bcca003eb2d18351079261 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 10 Dec 2020 19:38:21 +0100
Subject: [PATCH] Allow GRANTED BY clause in normal GRANT and REVOKE statements

The SQL standard allows a GRANTED BY clause on GRANT and
REVOKE (privilege) statements that can specify CURRENT_USER or
CURRENT_ROLE.  In PostgreSQL, both of these are the default behavior.
Since we already have all the parsing support for this for the
GRANT (role) statement, we might as well add basic support for this
for the privilege variant as well.  This allows us to check of SQL
feature T332.  In the future, perhaps more interesting things could be
done with this, too.
---
 doc/src/sgml/ref/grant.sgml          | 25 ++++++++++++++++++++++---
 doc/src/sgml/ref/revoke.sgml         | 13 +++++++++++++
 src/backend/catalog/aclchk.c         | 16 ++++++++++++++++
 src/backend/catalog/sql_features.txt |  2 +-
 src/backend/nodes/copyfuncs.c        |  1 +
 src/backend/nodes/equalfuncs.c       |  1 +
 src/backend/parser/gram.y            | 13 ++++++++-----
 src/include/nodes/parsenodes.h       |  1 +
 8 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index c3db393bde..a897712de2 100644
--- a/doc/src/sgml/ref/grant.sgml
+++ b/doc/src/sgml/ref/grant.sgml
@@ -26,58 +26,71 @@
     ON { [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...]
          | ALL TABLES IN SCHEMA <replaceable class="parameter">schema_name</replaceable> [, ...] }
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 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 <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 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 <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
     ON DATABASE <replaceable>database_name</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON DOMAIN <replaceable>domain_name</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON FOREIGN DATA WRAPPER <replaceable>fdw_name</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON FOREIGN SERVER <replaceable>server_name</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { EXECUTE | ALL [ PRIVILEGES ] }
     ON { { FUNCTION | PROCEDURE | ROUTINE } <replaceable>routine_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) ] [, ...]
          | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA <replaceable class="parameter">schema_name</replaceable> [, ...] }
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON LANGUAGE <replaceable>lang_name</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
     ON LARGE OBJECT <replaceable class="parameter">loid</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
     ON SCHEMA <replaceable>schema_name</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { CREATE | ALL [ PRIVILEGES ] }
     ON TABLESPACE <replaceable>tablespace_name</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON TYPE <replaceable>type_name</replaceable> [, ...]
     TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
 
 GRANT <replaceable class="parameter">role_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...]
     [ WITH ADMIN OPTION ]
@@ -133,6 +146,12 @@ <title>GRANT on Database Objects</title>
    to <literal>PUBLIC</literal>.
   </para>
 
+  <para>
+   If <literal>GRANTED BY</literal> is specified, the specified grantor must
+   be the current user.  This clause is currently present in this form only
+   for SQL compatibility.
+  </para>
+
   <para>
    There is no need to grant privileges to the owner of an object
    (usually the user that created it),
@@ -410,9 +429,9 @@ <title>Compatibility</title>
 
    <para>
     The SQL standard allows the <literal>GRANTED BY</literal> option to
-    be used in all forms of <command>GRANT</command>.  PostgreSQL only
-    supports it when granting role membership, and even then only superusers
-    may use it in nontrivial ways.
+    specify only <literal>CURRENT_USER</literal> or
+    <literal>CURRENT_ROLE</literal>.  The other variants are PostgreSQL
+    extensions.
    </para>
 
    <para>
diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml
index 35ff87a4f5..3014c864ea 100644
--- a/doc/src/sgml/ref/revoke.sgml
+++ b/doc/src/sgml/ref/revoke.sgml
@@ -27,6 +27,7 @@
     ON { [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...]
          | ALL TABLES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
@@ -34,6 +35,7 @@
     [, ...] | ALL [ PRIVILEGES ] ( <replaceable class="parameter">column_name</replaceable> [, ...] ) }
     ON [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
@@ -42,30 +44,35 @@
     ON { SEQUENCE <replaceable class="parameter">sequence_name</replaceable> [, ...]
          | ALL SEQUENCES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
     ON DATABASE <replaceable>database_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON DOMAIN <replaceable>domain_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON FOREIGN DATA WRAPPER <replaceable>fdw_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON FOREIGN SERVER <replaceable>server_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
@@ -73,36 +80,42 @@
     ON { { FUNCTION | PROCEDURE | ROUTINE } <replaceable>function_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) ] [, ...]
          | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON LANGUAGE <replaceable>lang_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
     ON LARGE OBJECT <replaceable class="parameter">loid</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
     ON SCHEMA <replaceable>schema_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { CREATE | ALL [ PRIVILEGES ] }
     ON TABLESPACE <replaceable>tablespace_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON TYPE <replaceable>type_name</replaceable> [, ...]
     FROM <replaceable class="parameter">role_specification</replaceable> [, ...]
+    [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ ADMIN OPTION FOR ]
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index c4594b0b09..1fa8f4d575 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -363,6 +363,22 @@ ExecuteGrantStmt(GrantStmt *stmt)
 	const char *errormsg;
 	AclMode		all_privileges;
 
+	if (stmt->grantor)
+	{
+		Oid			grantor;
+
+		grantor = get_rolespec_oid(stmt->grantor, false);
+
+		/*
+		 * Currently, this clause is only for SQL compatibility, not very
+		 * interesting otherwise.
+		 */
+		if (grantor != GetUserId())
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("grantor must be current user")));
+	}
+
 	/*
 	 * Turn the regular GrantStmt into the InternalGrant form.
 	 */
diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt
index caa971c435..86519ad297 100644
--- a/src/backend/catalog/sql_features.txt
+++ b/src/backend/catalog/sql_features.txt
@@ -475,7 +475,7 @@ T324	Explicit security for SQL routines			NO
 T325	Qualified SQL parameter references			YES	
 T326	Table functions			NO	
 T331	Basic roles			YES	
-T332	Extended roles			NO	mostly supported
+T332	Extended roles			YES	
 T341	Overloading of SQL-invoked functions and procedures			YES	
 T351	Bracketed SQL comments (/*...*/ comments)			YES	
 T431	Extended grouping capabilities			YES	
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 70f8b718e0..fe4082adbc 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3256,6 +3256,7 @@ _copyGrantStmt(const GrantStmt *from)
 	COPY_NODE_FIELD(privileges);
 	COPY_NODE_FIELD(grantees);
 	COPY_SCALAR_FIELD(grant_option);
+	COPY_NODE_FIELD(grantor);
 	COPY_SCALAR_FIELD(behavior);
 
 	return newnode;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 541e0e6b48..7f898e4b36 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1133,6 +1133,7 @@ _equalGrantStmt(const GrantStmt *a, const GrantStmt *b)
 	COMPARE_NODE_FIELD(privileges);
 	COMPARE_NODE_FIELD(grantees);
 	COMPARE_SCALAR_FIELD(grant_option);
+	COMPARE_NODE_FIELD(grantor);
 	COMPARE_SCALAR_FIELD(behavior);
 
 	return true;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 8f341ac006..95c397ecd2 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -6722,7 +6722,7 @@ opt_from_in:	from_in
  *****************************************************************************/
 
 GrantStmt:	GRANT privileges ON privilege_target TO grantee_list
-			opt_grant_grant_option
+			opt_grant_grant_option opt_granted_by
 				{
 					GrantStmt *n = makeNode(GrantStmt);
 					n->is_grant = true;
@@ -6732,13 +6732,14 @@ GrantStmt:	GRANT privileges ON privilege_target TO grantee_list
 					n->objects = ($4)->objs;
 					n->grantees = $6;
 					n->grant_option = $7;
+					n->grantor = $8;
 					$$ = (Node*)n;
 				}
 		;
 
 RevokeStmt:
 			REVOKE privileges ON privilege_target
-			FROM grantee_list opt_drop_behavior
+			FROM grantee_list opt_granted_by opt_drop_behavior
 				{
 					GrantStmt *n = makeNode(GrantStmt);
 					n->is_grant = false;
@@ -6748,11 +6749,12 @@ RevokeStmt:
 					n->objtype = ($4)->objtype;
 					n->objects = ($4)->objs;
 					n->grantees = $6;
-					n->behavior = $7;
+					n->grantor = $7;
+					n->behavior = $8;
 					$$ = (Node *)n;
 				}
 			| REVOKE GRANT OPTION FOR privileges ON privilege_target
-			FROM grantee_list opt_drop_behavior
+			FROM grantee_list opt_granted_by opt_drop_behavior
 				{
 					GrantStmt *n = makeNode(GrantStmt);
 					n->is_grant = false;
@@ -6762,7 +6764,8 @@ RevokeStmt:
 					n->objtype = ($7)->objtype;
 					n->objects = ($7)->objs;
 					n->grantees = $9;
-					n->behavior = $10;
+					n->grantor = $10;
+					n->behavior = $11;
 					$$ = (Node *)n;
 				}
 		;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 48a79a7657..41d6f4f191 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1930,6 +1930,7 @@ typedef struct GrantStmt
 	/* privileges == NIL denotes ALL PRIVILEGES */
 	List	   *grantees;		/* list of RoleSpec nodes */
 	bool		grant_option;	/* grant or revoke grant option */
+	RoleSpec   *grantor;
 	DropBehavior behavior;		/* drop behavior (for REVOKE) */
 } GrantStmt;
 
-- 
2.29.2

#13Simon Riggs
simon@2ndquadrant.com
In reply to: Peter Eisentraut (#12)
Re: Allow CURRENT_ROLE in GRANTED BY

On Thu, 10 Dec 2020 at 18:40, Peter Eisentraut
<peter.eisentraut@2ndquadrant.com> wrote:

On 2020-06-24 20:21, Peter Eisentraut wrote:

On 2020-06-24 10:12, Vik Fearing wrote:

On 6/24/20 8:35 AM, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are
equivalent. Here is a trivial patch to add that.

The only thing that isn't dead-obvious about this patch is the commit
message says "[PATCH 1/2]". What is in the other part?

Hehe. The second patch is some in-progress work to add the GRANTED BY
clause to the regular GRANT command. More on that perhaps at a later date.

Here is the highly anticipated and quite underwhelming second part of
this patch set.

Looks great, but no test to confirm it works. I would suggest adding a
test and committing directly since I don't see any cause for further
discussion.

--
Simon Riggs http://www.EnterpriseDB.com/

#14Peter Eisentraut
peter.eisentraut@2ndquadrant.com
In reply to: Simon Riggs (#13)
Re: Allow CURRENT_ROLE in GRANTED BY

On 2020-12-30 13:43, Simon Riggs wrote:

On Thu, 10 Dec 2020 at 18:40, Peter Eisentraut
<peter.eisentraut@2ndquadrant.com> wrote:

On 2020-06-24 20:21, Peter Eisentraut wrote:

On 2020-06-24 10:12, Vik Fearing wrote:

On 6/24/20 8:35 AM, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are
equivalent. Here is a trivial patch to add that.

The only thing that isn't dead-obvious about this patch is the commit
message says "[PATCH 1/2]". What is in the other part?

Hehe. The second patch is some in-progress work to add the GRANTED BY
clause to the regular GRANT command. More on that perhaps at a later date.

Here is the highly anticipated and quite underwhelming second part of
this patch set.

Looks great, but no test to confirm it works. I would suggest adding a
test and committing directly since I don't see any cause for further
discussion.

Committed with some tests. Thanks.

--
Peter Eisentraut
2ndQuadrant, an EDB company
https://www.2ndquadrant.com/

#15Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#14)
1 attachment(s)
Re: Allow CURRENT_ROLE in GRANTED BY

On 30 Jan 2021, at 09:51, Peter Eisentraut <peter.eisentraut@2ndquadrant.com> wrote:

On 2020-12-30 13:43, Simon Riggs wrote:

On Thu, 10 Dec 2020 at 18:40, Peter Eisentraut
<peter.eisentraut@2ndquadrant.com> wrote:

On 2020-06-24 20:21, Peter Eisentraut wrote:

On 2020-06-24 10:12, Vik Fearing wrote:

On 6/24/20 8:35 AM, Peter Eisentraut wrote:

I was checking some loose ends in SQL conformance, when I noticed: We
support GRANT role ... GRANTED BY CURRENT_USER, but we don't support
CURRENT_ROLE in that place, even though in PostgreSQL they are
equivalent. Here is a trivial patch to add that.

The only thing that isn't dead-obvious about this patch is the commit
message says "[PATCH 1/2]". What is in the other part?

Hehe. The second patch is some in-progress work to add the GRANTED BY
clause to the regular GRANT command. More on that perhaps at a later date.

Here is the highly anticipated and quite underwhelming second part of
this patch set.

Looks great, but no test to confirm it works. I would suggest adding a
test and committing directly since I don't see any cause for further
discussion.

Committed with some tests. Thanks.

While looking at the proposed privileges.sql test patch from Mark Dilger [0]333B0203-D19B-4335-AE64-90EB0FAF46F0@enterprisedb.com I
realized that the commit above seems to have missed the RevokeRoleStmt syntax.
As per the SQL Spec it should be supported there as well AFAICT. Was this
intentional or should the attached small diff be applied to fix it?

--
Daniel Gustafsson https://vmware.com/

[0]: 333B0203-D19B-4335-AE64-90EB0FAF46F0@enterprisedb.com

Attachments:

granted_by.diffapplication/octet-stream; name=granted_by.diff; x-unix-mode=0644Download
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a6d0cefa6b..86ce33bd97 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7196,6 +7196,7 @@ RevokeRoleStmt:
 					n->admin_opt = false;
 					n->granted_roles = $2;
 					n->grantee_roles = $4;
+					n->grantor = $5;
 					n->behavior = $6;
 					$$ = (Node*)n;
 				}
@@ -7206,6 +7207,7 @@ RevokeRoleStmt:
 					n->admin_opt = true;
 					n->granted_roles = $5;
 					n->grantee_roles = $7;
+					n->grantor = $8;
 					n->behavior = $9;
 					$$ = (Node*)n;
 				}
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 9b91865dcc..d17f41bc27 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -29,6 +29,7 @@ CREATE USER regress_priv_user5;	-- duplicate
 ERROR:  role "regress_priv_user5" already exists
 CREATE USER regress_priv_user6;
 CREATE USER regress_priv_user7;
+CREATE ROLE regress_priv_role;
 GRANT pg_read_all_data TO regress_priv_user6;
 GRANT pg_write_all_data TO regress_priv_user7;
 CREATE GROUP regress_priv_group1;
@@ -44,6 +45,12 @@ CREATE FUNCTION leak(integer,integer) RETURNS boolean
   LANGUAGE internal IMMUTABLE STRICT;  -- but deliberately not LEAKPROOF
 ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1;
 -- test owner privileges
+GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE;
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error
+ERROR:  role "foo" does not exist
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_USER;
+REVOKE regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_ROLE;
+DROP ROLE regress_priv_role;
 SET SESSION AUTHORIZATION regress_priv_user1;
 SELECT session_user, current_user;
     session_user    |    current_user    
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 6353a1cb8c..72ff14e19e 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -32,6 +32,7 @@ CREATE USER regress_priv_user5;
 CREATE USER regress_priv_user5;	-- duplicate
 CREATE USER regress_priv_user6;
 CREATE USER regress_priv_user7;
+CREATE ROLE regress_priv_role;
 
 GRANT pg_read_all_data TO regress_priv_user6;
 GRANT pg_write_all_data TO regress_priv_user7;
@@ -53,6 +54,12 @@ ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1;
 
 -- test owner privileges
 
+GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE;
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_USER;
+REVOKE regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_ROLE;
+DROP ROLE regress_priv_role;
+
 SET SESSION AUTHORIZATION regress_priv_user1;
 SELECT session_user, current_user;
 
#16Daniel Gustafsson
daniel@yesql.se
In reply to: Daniel Gustafsson (#15)
1 attachment(s)
Re: Allow CURRENT_ROLE in GRANTED BY

On 16 Nov 2021, at 15:04, Daniel Gustafsson <daniel@yesql.se> wrote:

..or should the attached small diff be applied to fix it?

Actually it shouldn't, I realized when hitting Send that it was the wrong
version. The attached is the proposed diff.

--
Daniel Gustafsson https://vmware.com/

Attachments:

granted_by_v2.diffapplication/octet-stream; name=granted_by_v2.diff; x-unix-mode=0644Download
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index aa69821be4..9869eb1703 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1259,7 +1259,13 @@ GrantRole(GrantRoleStmt *stmt)
 	ListCell   *item;
 
 	if (stmt->grantor)
+	{
 		grantor = get_rolespec_oid(stmt->grantor, false);
+		if (grantor != GetUserId())
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("grantor must be current user")));
+	}
 	else
 		grantor = GetUserId();
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a6d0cefa6b..86ce33bd97 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7196,6 +7196,7 @@ RevokeRoleStmt:
 					n->admin_opt = false;
 					n->granted_roles = $2;
 					n->grantee_roles = $4;
+					n->grantor = $5;
 					n->behavior = $6;
 					$$ = (Node*)n;
 				}
@@ -7206,6 +7207,7 @@ RevokeRoleStmt:
 					n->admin_opt = true;
 					n->granted_roles = $5;
 					n->grantee_roles = $7;
+					n->grantor = $8;
 					n->behavior = $9;
 					$$ = (Node*)n;
 				}
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 9b91865dcc..1d7ce4d0ea 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -29,6 +29,7 @@ CREATE USER regress_priv_user5;	-- duplicate
 ERROR:  role "regress_priv_user5" already exists
 CREATE USER regress_priv_user6;
 CREATE USER regress_priv_user7;
+CREATE ROLE regress_priv_role;
 GRANT pg_read_all_data TO regress_priv_user6;
 GRANT pg_write_all_data TO regress_priv_user7;
 CREATE GROUP regress_priv_group1;
@@ -44,6 +45,14 @@ CREATE FUNCTION leak(integer,integer) RETURNS boolean
   LANGUAGE internal IMMUTABLE STRICT;  -- but deliberately not LEAKPROOF
 ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1;
 -- test owner privileges
+GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE;
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error
+ERROR:  role "foo" does not exist
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY regress_priv_user2; -- error
+ERROR:  grantor must be current user
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_USER;
+REVOKE regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_ROLE;
+DROP ROLE regress_priv_role;
 SET SESSION AUTHORIZATION regress_priv_user1;
 SELECT session_user, current_user;
     session_user    |    current_user    
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 6353a1cb8c..5c84df1a13 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -32,6 +32,7 @@ CREATE USER regress_priv_user5;
 CREATE USER regress_priv_user5;	-- duplicate
 CREATE USER regress_priv_user6;
 CREATE USER regress_priv_user7;
+CREATE ROLE regress_priv_role;
 
 GRANT pg_read_all_data TO regress_priv_user6;
 GRANT pg_write_all_data TO regress_priv_user7;
@@ -53,6 +54,13 @@ ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1;
 
 -- test owner privileges
 
+GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE;
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY regress_priv_user2; -- error
+REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_USER;
+REVOKE regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_ROLE;
+DROP ROLE regress_priv_role;
+
 SET SESSION AUTHORIZATION regress_priv_user1;
 SELECT session_user, current_user;
 
#17Peter Eisentraut
peter.eisentraut@enterprisedb.com
In reply to: Daniel Gustafsson (#16)
Re: Allow CURRENT_ROLE in GRANTED BY

On 16.11.21 15:27, Daniel Gustafsson wrote:

On 16 Nov 2021, at 15:04, Daniel Gustafsson <daniel@yesql.se> wrote:

..or should the attached small diff be applied to fix it?

Actually it shouldn't, I realized when hitting Send that it was the wrong
version. The attached is the proposed diff.

This appears to have been an oversight.

#18Daniel Gustafsson
daniel@yesql.se
In reply to: Peter Eisentraut (#17)
Re: Allow CURRENT_ROLE in GRANTED BY

On 18 Nov 2021, at 14:41, Peter Eisentraut <peter.eisentraut@enterprisedb.com> wrote:

On 16.11.21 15:27, Daniel Gustafsson wrote:

On 16 Nov 2021, at 15:04, Daniel Gustafsson <daniel@yesql.se> wrote:

..or should the attached small diff be applied to fix it?

Actually it shouldn't, I realized when hitting Send that it was the wrong
version. The attached is the proposed diff.

This appears to have been an oversight.

Thanks for confirming, I’ll take another pass over the proposed diff in a bit.

#19Daniel Gustafsson
daniel@yesql.se
In reply to: Daniel Gustafsson (#18)
Re: Allow CURRENT_ROLE in GRANTED BY

On 18 Nov 2021, at 14:42, Daniel Gustafsson <daniel@yesql.se> wrote:

On 18 Nov 2021, at 14:41, Peter Eisentraut <peter.eisentraut@enterprisedb.com> wrote:

On 16.11.21 15:27, Daniel Gustafsson wrote:

On 16 Nov 2021, at 15:04, Daniel Gustafsson <daniel@yesql.se> wrote:

..or should the attached small diff be applied to fix it?

Actually it shouldn't, I realized when hitting Send that it was the wrong
version. The attached is the proposed diff.

This appears to have been an oversight.

Thanks for confirming, I’ll take another pass over the proposed diff in a bit.

Polished a little and pushed to master with a backpatch to 14 where it was
introduced.

--
Daniel Gustafsson https://vmware.com/