>From 9be0ca6f7961ccadf665867c52233079a1024737 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Tue, 9 Sep 2014 19:26:24 +0900
Subject: [PATCH 1/2] ALTER ROLE CURRENT_USER

---
 src/backend/commands/user.c |   48 ++++++++++++++++++++++++++++++++----------
 src/backend/parser/gram.y   |   27 +++++++++++++++++------
 2 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 1a73fd8..8630323 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -649,13 +649,25 @@ AlterRole(AlterRoleStmt *stmt)
 	pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);
 	pg_authid_dsc = RelationGetDescr(pg_authid_rel);
 
-	tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
-	if (!HeapTupleIsValid(tuple))
-		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("role \"%s\" does not exist", stmt->role)));
+	if (strcmp(stmt->role, "current_user") == 0)
+	{
+		roleid = GetUserId();
+		tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
+		if (!HeapTupleIsValid(tuple))
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("roleid %d does not exist", roleid)));
+	}
+	else
+	{
+		tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
+		if (!HeapTupleIsValid(tuple))
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("role \"%s\" does not exist", stmt->role)));
 
-	roleid = HeapTupleGetOid(tuple);
+		roleid = HeapTupleGetOid(tuple);
+	}
 
 	/*
 	 * To mess with a superuser you gotta be superuser; else you need
@@ -870,14 +882,26 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
 
 	if (stmt->role)
 	{
-		roletuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
+		if (strcmp(stmt->role, "current_user") == 0)
+		{
+			roleid = GetUserId();
+			roletuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
+			if (!HeapTupleIsValid(roletuple))
+				ereport(ERROR,
+						(errcode(ERRCODE_UNDEFINED_OBJECT),
+						 errmsg("roleid %d does not exist", roleid)));
+		}
+		else
+		{
+			roletuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
 
-		if (!HeapTupleIsValid(roletuple))
-			ereport(ERROR,
-					(errcode(ERRCODE_UNDEFINED_OBJECT),
-					 errmsg("role \"%s\" does not exist", stmt->role)));
+			if (!HeapTupleIsValid(roletuple))
+				ereport(ERROR,
+						(errcode(ERRCODE_UNDEFINED_OBJECT),
+						 errmsg("role \"%s\" does not exist", stmt->role)));
 
-		roleid = HeapTupleGetOid(roletuple);
+			roleid = HeapTupleGetOid(roletuple);
+		}
 
 		/*
 		 * Obtain a lock on the role and make sure it didn't go away in the
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c98c27a..f007aea 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -474,7 +474,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 %type <ival>	Iconst SignedIconst
 %type <str>		Sconst comment_text notify_payload
-%type <str>		RoleId opt_granted_by opt_boolean_or_string
+%type <str>		RoleId RoleId_or_curruser
+%type <str>		opt_granted_by opt_boolean_or_string
 %type <list>	var_list
 %type <str>		ColId ColLabel var_name type_function_name param_name
 %type <str>		NonReservedWord NonReservedWord_or_Sconst
@@ -1036,7 +1037,7 @@ CreateUserStmt:
  *****************************************************************************/
 
 AlterRoleStmt:
-			ALTER ROLE RoleId opt_with AlterOptRoleList
+			ALTER ROLE RoleId_or_curruser opt_with AlterOptRoleList
 				 {
 					AlterRoleStmt *n = makeNode(AlterRoleStmt);
 					n->role = $3;
@@ -1052,7 +1053,7 @@ opt_in_database:
 		;
 
 AlterRoleSetStmt:
-			ALTER ROLE RoleId opt_in_database SetResetClause
+			ALTER ROLE RoleId_or_curruser opt_in_database SetResetClause
 				{
 					AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
 					n->role = $3;
@@ -1078,7 +1079,7 @@ AlterRoleSetStmt:
  *****************************************************************************/
 
 AlterUserStmt:
-			ALTER USER RoleId opt_with AlterOptRoleList
+			ALTER USER RoleId_or_curruser opt_with AlterOptRoleList
 				 {
 					AlterRoleStmt *n = makeNode(AlterRoleStmt);
 					n->role = $3;
@@ -1090,12 +1091,20 @@ AlterUserStmt:
 
 
 AlterUserSetStmt:
-			ALTER USER RoleId SetResetClause
+			ALTER USER RoleId_or_curruser opt_in_database SetResetClause
 				{
 					AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
 					n->role = $3;
-					n->database = NULL;
-					n->setstmt = $4;
+					n->database = $4;
+					n->setstmt = $5;
+					$$ = (Node *)n;
+				}
+			| ALTER USER ALL opt_in_database SetResetClause
+				{
+					AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
+					n->role = NULL;
+					n->database = $4;
+					n->setstmt = $5;
 					$$ = (Node *)n;
 				}
 			;
@@ -12958,6 +12967,10 @@ Iconst:		ICONST									{ $$ = $1; };
 Sconst:		SCONST									{ $$ = $1; };
 RoleId:		NonReservedWord							{ $$ = $1; };
 
+RoleId_or_curruser: RoleId							{ $$ = $1; }
+			| CURRENT_USER							{ $$ = "current_user"; };
+			| CURRENT_ROLE							{ $$ = "current_user"; };
+
 role_list:	RoleId
 					{ $$ = list_make1(makeString($1)); }
 			| role_list ',' RoleId
-- 
1.7.1

