Thank you for completing this and very sorry not to respond these
days.

I understood that it is committed after I noticed that rebasing
my code failed..

Although after committed, I found some issues as I looked on
it. Please forgive me to comment it now after all this time.

Several changes in docs according to the changed syntax and one
change in code itself to allow CURRENT_USER in GRANT <roleid> TO
<roleid> syntax.


At Mon, 9 Mar 2015 15:50:32 -0300, Alvaro Herrera <alvhe...@2ndquadrant.com> 
wrote in <20150309185032.gq3...@alvh.no-ip.org>
> Alvaro Herrera wrote:
> 
> > With this patch applied, doing
> > \h ALTER ROLE
> > in psql looks quite odd: note how wide it has become.  Maybe we should
> > be doing this differently?  (Hmm, why don't we accept ALL in the first SET
> > line?  Maybe that's just a mistake and the four lines should be all
> > identical in the first half ...)
> 
> I have fixed the remaining issues, completed the doc changes, and
> pushed.  Given the lack of feedback I had to follow my gut on the best
> way to change the docs.  I added the regression test you submitted with
> some additional changes, mainly to make sure they don't fail immediately
> when other databases exist; maybe some more concurrency or platform
> issues will show up there, but let's see what the buildfarm says.
> 
> Thanks Horiguchi-san for the patch and everyone for the reviews.  (It's
> probably worthwhile giving things an extra look.)

====
| =# alter role current_user rename to "PubLic";
| ERROR:  CURRENT_USER cannot be used as a role name
| LINE 1: alter role current_user rename to "PubLic";
|                    ^

The error message sounds somewhat different from the intention. I
think the following message would be clearer.

| ERROR:  CURRENT_USER cannot be used as a role name here

====
The document sql-altergroup.html says

| ALTER GROUP role_specification ADD USER user_name [, ... ]

But current_user is also usable in user_name list. So the doc
should be as following, but it would not be necessary to be fixed
because it is an obsolete commnand..

| ALTER GROUP role_specification ADD USER role_specification [, ... ]

"ALTER GROUP role_spec ADD/DROP USER role_spec" is naturally
denied so I think no additional description is needed.

====
sql-alterpolicy.html

"ALTER POLICY name ON table_name TO" also accepts current_user
and so as the role to which the policy applies.

# As a different topic, the syntax "ALTER POLICY <pname> ON
# <tname> TO <user>" looks a bit wired, it might be better be to
# be "ON <tname> APPLY TO <user>" but I shouldn't try to fix it
# since it is a long standing syntax..

====
sql-createtablespace.html

"OWNER username" should be "OWNER user_name | (CURRENT|SESSION)_USER"

====
sql-drop-owned.html, sql-reassign-owned.html

"name" should be " {name | (CURRENT|SESSION)_USER}"

For REASSIGN OWNED, TO clause also needs the same fix.

======
sql-grant.html, sql-revoke.html,

"GRANT <roles> TO <roles>" and "REVOKE <roles> FROM <roles>" are
the modern equivalents of the deprecated syntaxes "ALTER <roles>
ADD USER <roles>" and "ALTER <roles> DROP USER <roles>"
respectively. But the current parser infrastructure doesn't allow
coexistence of the two following syntaxes but I couldn't find the
way to their coexistence.

# more precisely, I guess the GRANT followed by both
# privelege_list and role_list will steps out of the realm of
# LALR(1), which I don't know well of..

"GRANT <privs> ON ..." 
"GRANT <roles> TO ..."

After some struggle, I decided to add special rules
(CURRENT|SESSION)_USER to the non-terminal "privilege" and make a
room to store RoleSpec in AccessPriv. This is quite ugly but
there seems no way other than that to accomplish it.. (AccessPriv
already conveys other than the information different from what
its name represents:p)

After this fix, the commands like following are processed
properly. public and none are simply handled as nonexistent
names.

GRANT test1 TO CURRENT_USER;

GRANT <priv> ON <table> TO <role> properly rejects CURRENT_USER
as <priv>.

But the change in gram.y cuases changes in preproc.y as following,

>  privilege:
>  SELECT opt_column_list
>  { 
...
> |  ColId opt_column_list
>  { 
>  $$ = cat_str(2,$1,$2);
> }
+ |  CURRENT_USER
+  { 
+  $$ = mm_strdup("current_user");
+ }
+ |  SESSION_USER
+  { 
+  $$ = mm_strdup("session_user");
+ }
> ;

I don't understand what this change causes...

=====

I haven't looked on the docs for syntaxes related to
AlterOwnerStatement. But perhaps they don't be wrong.

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
>From 26afc656576c8778921ff44519e3de86866ab138 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyot...@lab.ntt.co.jp>
Date: Thu, 12 Mar 2015 20:56:14 +0900
Subject: [PATCH] Some additional changes for ALTER ROLE/USER CURRENT_USER.

Some documents are not edit according to new specs. Addition to it,
"GRANT <roles> TO <roles>" and "REVOKE <roles> FROM <roles>" syntaxes,
which are the modern replacement of "ALTER GROUP ADD/DROP USER"
syntax, are not accepted by the previous patch.

This patch fixes some docs and changes the syntax of GRANT command to
accept CURRENT_ROLE and SESSION_ROLE as other similar command does.
---
 doc/src/sgml/ref/alter_policy.sgml      |  2 +-
 doc/src/sgml/ref/create_policy.sgml     |  2 +-
 doc/src/sgml/ref/create_tablespace.sgml |  2 +-
 doc/src/sgml/ref/drop_owned.sgml        |  2 +-
 doc/src/sgml/ref/grant.sgml             |  3 ++-
 doc/src/sgml/ref/reassign_owned.sgml    |  3 ++-
 doc/src/sgml/ref/revoke.sgml            | 36 ++++++++++++++++++++-------------
 src/backend/catalog/aclchk.c            |  4 ++++
 src/backend/commands/user.c             | 10 +++++++--
 src/backend/nodes/equalfuncs.c          |  1 +
 src/backend/parser/Makefile             |  2 +-
 src/backend/parser/gram.y               | 22 +++++++++++++++++---
 src/include/nodes/parsenodes.h          |  4 ++++
 src/test/regress/expected/rolenames.out |  4 ++--
 14 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/doc/src/sgml/ref/alter_policy.sgml b/doc/src/sgml/ref/alter_policy.sgml
index 6d03db5..2e63206 100644
--- a/doc/src/sgml/ref/alter_policy.sgml
+++ b/doc/src/sgml/ref/alter_policy.sgml
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
     [ RENAME TO <replaceable class="PARAMETER">new_name</replaceable> ]
-    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC } [, ...] ]
+    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | 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_policy.sgml b/doc/src/sgml/ref/create_policy.sgml
index 868a6c1..7efb45e 100644
--- a/doc/src/sgml/ref/create_policy.sgml
+++ b/doc/src/sgml/ref/create_policy.sgml
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
     [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
-    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC } [, ...] ]
+    [ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | 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_tablespace.sgml b/doc/src/sgml/ref/create_tablespace.sgml
index 9072d07..5756c3e 100644
--- a/doc/src/sgml/ref/create_tablespace.sgml
+++ b/doc/src/sgml/ref/create_tablespace.sgml
@@ -22,7 +22,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 CREATE TABLESPACE <replaceable class="parameter">tablespace_name</replaceable>
-    [ OWNER <replaceable class="parameter">user_name</replaceable> ]
+    [ OWNER { <replaceable>new_owner</replaceable> | 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/drop_owned.sgml b/doc/src/sgml/ref/drop_owned.sgml
index 1cd8e60..64906ef 100644
--- a/doc/src/sgml/ref/drop_owned.sgml
+++ b/doc/src/sgml/ref/drop_owned.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-DROP OWNED BY <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ]
+DROP OWNED BY { <replaceable class="PARAMETER">name</replaceable> | CURRENT_USER | SESSION_USER } [, ...] [ CASCADE | RESTRICT ]
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index d9ac8d2..a984a74 100644
--- a/doc/src/sgml/ref/grant.sgml
+++ b/doc/src/sgml/ref/grant.sgml
@@ -79,6 +79,8 @@ GRANT { USAGE | ALL [ PRIVILEGES ] }
     ON TYPE <replaceable>type_name</replaceable> [, ...]
     TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ]
 
+GRANT <replaceable class="PARAMETER">role_specification</replaceable> [, ...] TO <replaceable class="PARAMETER">role_specification</replaceable> [, ...] [ WITH ADMIN OPTION ]
+
 <phrase>where <replaceable class="PARAMETER">role_specification</replaceable> can be:</phrase>
 
     [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable>
@@ -86,7 +88,6 @@ GRANT { USAGE | ALL [ PRIVILEGES ] }
   | CURRENT_USER
   | SESSION_USER
 
-GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replaceable class="PARAMETER">role_name</replaceable> [, ...] [ WITH ADMIN OPTION ]
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/reassign_owned.sgml b/doc/src/sgml/ref/reassign_owned.sgml
index d7d6abb..382cba3 100644
--- a/doc/src/sgml/ref/reassign_owned.sgml
+++ b/doc/src/sgml/ref/reassign_owned.sgml
@@ -21,7 +21,8 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REASSIGN OWNED BY <replaceable class="PARAMETER">old_role</replaceable> [, ...] TO <replaceable class="PARAMETER">new_role</replaceable>
+REASSIGN OWNED BY { <replaceable class="PARAMETER">old_role</replaceable> | CURRENT_USER | SESSION_USER } [, ...]
+               TO { <replaceable class="PARAMETER">new_role</replaceable> | CURRENT_USER | SESSION_USER }
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml
index 36c286b..24910f6 100644
--- a/doc/src/sgml/ref/revoke.sgml
+++ b/doc/src/sgml/ref/revoke.sgml
@@ -26,14 +26,14 @@ REVOKE [ GRANT OPTION FOR ]
     [, ...] | ALL [ PRIVILEGES ] }
     ON { [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
          | ALL TABLES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { { 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> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
@@ -41,73 +41,81 @@ REVOKE [ GRANT OPTION FOR ]
     [, ...] | ALL [ PRIVILEGES ] }
     ON { SEQUENCE <replaceable class="PARAMETER">sequence_name</replaceable> [, ...]
          | ALL SEQUENCES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
     ON DATABASE <replaceable>database_name</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON DOMAIN <replaceable>domain_name</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON FOREIGN DATA WRAPPER <replaceable>fdw_name</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON FOREIGN SERVER <replaceable>server_name</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { EXECUTE | ALL [ PRIVILEGES ] }
     ON { FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...]
          | ALL FUNCTIONS IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON LANGUAGE <replaceable>lang_name</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
     ON LARGE OBJECT <replaceable class="PARAMETER">loid</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
     ON SCHEMA <replaceable>schema_name</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { CREATE | ALL [ PRIVILEGES ] }
     ON TABLESPACE <replaceable>tablespace_name</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
     { USAGE | ALL [ PRIVILEGES ] }
     ON TYPE <replaceable>type_name</replaceable> [, ...]
-    FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+    FROM { [ GROUP ] <replaceable class="PARAMETER">role_specification</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ ADMIN OPTION FOR ]
-    <replaceable class="PARAMETER">role_name</replaceable> [, ...] FROM <replaceable class="PARAMETER">role_name</replaceable> [, ...]
+    <replaceable class="PARAMETER">role_specification</replaceable> [, ...] FROM <replaceable class="PARAMETER">role_specification</replaceable> [, ...]
     [ CASCADE | RESTRICT ]
+
+<phrase>where <replaceable class="PARAMETER">role_specification</replaceable> can be:</phrase>
+
+    [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable>
+  | PUBLIC
+  | CURRENT_USER
+  | SESSION_USER
+
 </synopsis>
  </refsynopsisdiv>
 
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 8e75c27..2c35645 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -533,6 +533,7 @@ ExecuteGrantStmt(GrantStmt *stmt)
 			 * If it's a column-level specification, we just set it aside in
 			 * col_privs for the moment; but insist it's for a relation.
 			 */
+			
 			if (privnode->cols)
 			{
 				if (stmt->objtype != ACL_OBJECT_RELATION)
@@ -543,6 +544,9 @@ ExecuteGrantStmt(GrantStmt *stmt)
 				continue;
 			}
 
+			if (privnode->rolespec) /* syntax error */
+				elog(ERROR, "\"%s\" cannot be specified as privilege", 
+					 privnode->rolespec->rolename);
 			if (privnode->priv_name == NULL)	/* parser mistake? */
 				elog(ERROR, "AccessPriv node must specify privilege or columns");
 			priv = string_to_privilege(privnode->priv_name);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 75f1b3c..66e7257 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1256,11 +1256,17 @@ GrantRole(GrantRoleStmt *stmt)
 	foreach(item, stmt->granted_roles)
 	{
 		AccessPriv *priv = (AccessPriv *) lfirst(item);
+		RoleSpec   *rolespec = priv->rolespec;
 		char	   *rolename = priv->priv_name;
 		Oid			roleid;
 
-		/* Must reject priv(columns) and ALL PRIVILEGES(columns) */
-		if (rolename == NULL || priv->cols != NIL)
+		/*
+		 * Must reject priv(columns) and ALL PRIVILEGES(columns) if priv is
+		 * not a rolespec
+		 */
+		if (rolespec)
+			rolename = get_rolespec_name(rolespec);
+		else if (rolename == NULL || priv->cols != NIL)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_GRANT_OPERATION),
 			errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index fcd58ad..eef3b95 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1026,6 +1026,7 @@ _equalAccessPriv(const AccessPriv *a, const AccessPriv *b)
 {
 	COMPARE_STRING_FIELD(priv_name);
 	COMPARE_NODE_FIELD(cols);
+	COMPARE_NODE_FIELD(rolespec);
 
 	return true;
 }
diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile
index 0395bd5..3c002a2 100644
--- a/src/backend/parser/Makefile
+++ b/src/backend/parser/Makefile
@@ -38,7 +38,7 @@ endif
 
 gram.h: gram.c ;
 
-gram.c: BISONFLAGS += -d
+gram.c: BISONFLAGS += -vd
 gram.c: BISON_CHECK_CMD = $(PERL) $(srcdir)/check_keywords.pl $< $(top_srcdir)/src/include/parser/kwlist.h
 
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index cf0d317..9d75a63 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -6201,9 +6201,25 @@ privilege:	SELECT opt_column_list
 				n->cols = $2;
 				$$ = n;
 			}
+		| CURRENT_USER
+			{
+				RoleSpec *rs =
+				  (RoleSpec *)makeRoleSpec(ROLESPEC_CURRENT_USER, @1);
+				AccessPriv *n = makeNode(AccessPriv);
+				n->rolespec = (Node*)rs;
+				rs->rolename = pstrdup($1);
+				$$ = n;
+			}
+		| SESSION_USER
+			{
+				RoleSpec *rs =
+				  (RoleSpec *)makeRoleSpec(ROLESPEC_SESSION_USER, @1);
+				AccessPriv *n = makeNode(AccessPriv);
+				n->rolespec = (Node*)rs;
+				rs->rolename = pstrdup($1);
+			}
 		;
 
-
 /* Don't bother trying to fold the first two rules into one using
  * opt_table.  You're going to get conflicts.
  */
@@ -13166,13 +13182,13 @@ RoleId:		RoleSpec
 						case ROLESPEC_SESSION_USER:
 							ereport(ERROR,
 									(errcode(ERRCODE_RESERVED_NAME),
-									 errmsg("%s cannot be used as a role name",
+									 errmsg("%s cannot be used as a role name here",
 											"SESSION_USER"),
 									 parser_errposition(@1)));
 						case ROLESPEC_CURRENT_USER:
 							ereport(ERROR,
 									(errcode(ERRCODE_RESERVED_NAME),
-									 errmsg("%s cannot be used as a role name",
+									 errmsg("%s cannot be used as a role name here",
 											"CURRENT_USER"),
 									 parser_errposition(@1)));
 					}
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 38ed661..4bdffef 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1480,12 +1480,16 @@ typedef struct FuncWithArgs
  * cols == NIL denotes "all columns"
  * Note that simple "ALL PRIVILEGES" is represented as a NIL list, not
  * an AccessPriv with both fields null.
+ *
+ * In some cases, AccessPriv conveys RoleSpec to allow special roles such as
+ * CURRENT_USER or SESSION_USER. rolespec is filled for the cases.
  */
 typedef struct AccessPriv
 {
 	NodeTag		type;
 	char	   *priv_name;		/* string name of privilege */
 	List	   *cols;			/* list of Value strings */
+	Node	   *rolespec;		/* filled if any rolespec specific info exists */
 } AccessPriv;
 
 /* ----------------------
diff --git a/src/test/regress/expected/rolenames.out b/src/test/regress/expected/rolenames.out
index 1879337..8f88c02 100644
--- a/src/test/regress/expected/rolenames.out
+++ b/src/test/regress/expected/rolenames.out
@@ -43,7 +43,7 @@ CREATE ROLE "current_user";
 CREATE ROLE "session_user";
 CREATE ROLE "user";
 CREATE ROLE current_user; -- error
-ERROR:  CURRENT_USER cannot be used as a role name
+ERROR:  CURRENT_USER cannot be used as a role name here
 LINE 1: CREATE ROLE current_user;
                     ^
 CREATE ROLE current_role; -- error
@@ -51,7 +51,7 @@ ERROR:  syntax error at or near "current_role"
 LINE 1: CREATE ROLE current_role;
                     ^
 CREATE ROLE session_user; -- error
-ERROR:  SESSION_USER cannot be used as a role name
+ERROR:  SESSION_USER cannot be used as a role name here
 LINE 1: CREATE ROLE session_user;
                     ^
 CREATE ROLE user; -- error
-- 
2.1.0.GIT

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to