>From 8c817e8de4ce7f8a97e9e3298b72e05bea1ba1ea Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Wed, 21 Jan 2015 13:22:12 +0900
Subject: [PATCH 2/2] Add regrole.

---
 doc/src/sgml/datatype.sgml            |  19 +++++--
 src/backend/utils/adt/regproc.c       | 101 ++++++++++++++++++++++++++++++++++
 src/include/catalog/pg_cast.h         |   7 +++
 src/include/catalog/pg_proc.h         |  11 +++-
 src/include/catalog/pg_type.h         |   5 ++
 src/include/utils/builtins.h          |   5 ++
 src/test/regress/expected/regproc.out |  26 ++++++++-
 src/test/regress/sql/regproc.sql      |   7 +++
 8 files changed, 173 insertions(+), 8 deletions(-)

diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 9799e18..411771e 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -4448,17 +4448,24 @@ SELECT * FROM pg_attribute
         <entry>text search dictionary</entry>
         <entry><literal>simple</></entry>
        </row>
+
+       <row>
+        <entry><type>regrole</></entry>
+        <entry><structname>pg_role</></entry>
+        <entry>role name</entry>
+        <entry><literal>user1</></entry>
+       </row>
       </tbody>
      </tgroup>
     </table>
 
    <para>
-    All of the OID alias types except regnamespace accept schema-qualified
-    names, and will display schema-qualified names on output if the object
-    would not be found in the current search path without being qualified.
-    The <type>regproc</> and <type>regoper</> alias types will only accept
-    input names that are unique (not overloaded), so they are of limited use;
-    for most uses <type>regprocedure</> or
+    All of the OID alias types except regnamespace and regrole accept
+    schema-qualified names, and will display schema-qualified names on output
+    if the object would not be found in the current search path without being
+    qualified.  The <type>regproc</> and <type>regoper</> alias types will
+    only accept input names that are unique (not overloaded), so they are of
+    limited use; for most uses <type>regprocedure</> or
     <type>regoperator</> are more appropriate.  For <type>regoperator</>,
     unary operators are identified by writing <literal>NONE</> for the unused
     operand.
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index b09aa2a..6155e4f 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -40,6 +40,7 @@
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 #include "utils/tqual.h"
+#include "utils/acl.h"
 
 static char *format_operator_internal(Oid operator_oid, bool force_qualify);
 static char *format_procedure_internal(Oid procedure_oid, bool force_qualify);
@@ -1650,6 +1651,106 @@ regdictionarysend(PG_FUNCTION_ARGS)
 	return oidsend(fcinfo);
 }
 
+/*
+ * regrolein	- converts "regrole" to role OID
+ *
+ * We also accept a numeric OID, for symmetry with the output routine.
+ *
+ * '-' signifies unknown (OID 0).  In all other cases, the input must
+ * match an existing pg_ts_dict entry.
+ *
+ * This function is not needed in bootstrap mode, so we don't worry about
+ * making it work then.
+ */
+Datum
+regrolein(PG_FUNCTION_ARGS)
+{
+	char	   *role_or_oid = PG_GETARG_CSTRING(0);
+	Oid			result;
+
+	/* '-' ? */
+	if (strcmp(role_or_oid, "-") == 0)
+		PG_RETURN_OID(InvalidOid);
+
+	/* Numeric OID? */
+	if (role_or_oid[0] >= '0' &&
+		role_or_oid[0] <= '9' &&
+		strspn(role_or_oid, "0123456789") == strlen(role_or_oid))
+	{
+		result = DatumGetObjectId(DirectFunctionCall1(oidin,
+										 CStringGetDatum(role_or_oid)));
+		PG_RETURN_OID(result);
+	}
+
+	/*
+	 * Normal case: parse the name into components and see if it matches any
+	 * pg_role entries in the current search path.
+	 */
+	result = get_role_oid(role_or_oid, false);
+
+	PG_RETURN_OID(result);
+}
+
+/*
+ * to_regrole		- converts "role name" to role OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regrole(PG_FUNCTION_ARGS)
+{
+	char	   *role_name = PG_GETARG_CSTRING(0);
+	Oid			result;
+
+	result = get_role_oid(role_name, true);
+	
+	if (OidIsValid(result))
+		PG_RETURN_OID(result);
+	else
+		PG_RETURN_NULL();
+}
+
+/*
+ * regroleout		- converts role OID to "role_name"
+ */
+Datum
+regroleout(PG_FUNCTION_ARGS)
+{
+	Oid			roleoid = PG_GETARG_OID(0);
+	char	   *result;
+
+
+	if (roleoid == InvalidOid)
+	{
+		result = pstrdup("-");
+		PG_RETURN_CSTRING(result);
+	}
+
+	result = GetUserNameFromId(roleoid);
+	PG_RETURN_CSTRING(result);
+}
+
+/*
+ *		regrolerecv	- converts external binary format to regrole
+ */
+Datum
+regrolerecv(PG_FUNCTION_ARGS)
+{
+	/* Exactly the same as oidrecv, so share code */
+	return oidrecv(fcinfo);
+}
+
+/*
+ *		regrolesend	- converts regrole to binary format
+ */
+Datum
+regrolesend(PG_FUNCTION_ARGS)
+{
+	/* Exactly the same as oidsend, so share code */
+	return oidsend(fcinfo);
+}
+
+
 
 /*
  * text_regclass: convert text to regclass
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index e4b24e3..fad168f 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -217,6 +217,13 @@ DATA(insert (	21 4089  313 i f ));
 DATA(insert (	23 4089    0 i b ));
 DATA(insert ( 4089	 20 1288 a f ));
 DATA(insert ( 4089	 23    0 a b ));
+DATA(insert (	26 4096    0 i b ));
+DATA(insert ( 4096	 26    0 i b ));
+DATA(insert (	20 4096 1287 i f ));
+DATA(insert (	21 4096  313 i f ));
+DATA(insert (	23 4096    0 i b ));
+DATA(insert ( 4096	 20 1288 a f ));
+DATA(insert ( 4096	 23    0 a b ));
 
 /*
  * String category
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index cd6dbcf..9787d33 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3437,11 +3437,16 @@ DATA(insert OID = 1079 (  regclass			PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 22
 DESCR("convert text to regclass");
 DATA(insert OID = 4084 (  regnamespacein	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 4089 "2275" _null_ _null_ _null_ _null_ regnamespacein _null_ _null_ _null_ ));
 DESCR("I/O");
-
 DATA(insert OID = 4085 (  regnamespaceout	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "4089" _null_ _null_ _null_ _null_ regnamespaceout _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 4086 (  to_regnamespace	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 4089 "2275" _null_ _null_ _null_ _null_ to_regnamespace _null_ _null_ _null_ ));
 DESCR("convert namespace name to regnamespace");
+DATA(insert OID = 4091 (  regrolein			PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 4096 "2275" _null_ _null_ _null_ _null_ regrolein _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 4092 (  regroleout		PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "4096" _null_ _null_ _null_ _null_ regroleout _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 4093 (  to_regrole		PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 4096 "2275" _null_ _null_ _null_ _null_ to_regrole _null_ _null_ _null_ ));
+DESCR("convert role name to regrole");
 DATA(insert OID = 2246 ( fmgr_internal_validator PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2278 "26" _null_ _null_ _null_ _null_ fmgr_internal_validator _null_ _null_ _null_ ));
 DESCR("(internal)");
 DATA(insert OID = 2247 ( fmgr_c_validator	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2278 "26" _null_ _null_ _null_ _null_ fmgr_c_validator _null_ _null_ _null_ ));
@@ -3841,6 +3846,10 @@ DATA(insert OID = 4087 (  regnamespacerecv	   PGNSP PGUID 12 1 0 0 0 f f f f t f
 DESCR("I/O");
 DATA(insert OID = 4088 (  regnamespacesend	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "4089" _null_ _null_ _null_ _null_	regnamespacesend _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 4094 (  regrolerecv	  	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 4096 "2281" _null_ _null_ _null_ _null_ regrolerecv _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 4095 (  regrolesend	       PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "4096" _null_ _null_ _null_ _null_	regrolesend _null_ _null_ _null_ ));
+DESCR("I/O");
 DATA(insert OID = 2456 (  bit_recv			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1560 "2281 26 23" _null_ _null_ _null_ _null_  bit_recv _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2457 (  bit_send			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "1560" _null_ _null_ _null_ _null_	bit_send _null_ _null_ _null_ ));
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 4aae8b6..0bd3fbd 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -568,6 +568,10 @@ DATA(insert OID = 4089 ( regnamespace  PGNSP PGUID	4 t b N f t \054 0	 0 4090 re
 DESCR("registered namespace");
 #define REGNAMESPACEOID		4089
 
+DATA(insert OID = 4096 ( regrole       PGNSP PGUID	4 t b N f t \054 0	 0 4097 regrolein regroleout regrolerecv regrolesend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DESCR("registered role");
+#define REGROLEOID		4096
+
 DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b A f t \054 0 2202 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 2208 ( _regoper	   PGNSP PGUID -1 f b A f t \054 0 2203 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 DATA(insert OID = 2209 ( _regoperator  PGNSP PGUID -1 f b A f t \054 0 2204 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
@@ -575,6 +579,7 @@ DATA(insert OID = 2210 ( _regclass	   PGNSP PGUID -1 f b A f t \054 0 2205 0 arr
 DATA(insert OID = 2211 ( _regtype	   PGNSP PGUID -1 f b A f t \054 0 2206 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 #define REGTYPEARRAYOID 2211
 DATA(insert OID = 4090 ( _regnamespace PGNSP PGUID -1 f b A f t \054 0 4089 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 4097 ( _regrole      PGNSP PGUID -1 f b A f t \054 0 4096 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 
 /* uuid */
 DATA(insert OID = 2950 ( uuid			PGNSP PGUID 16 f b U f t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 0 _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 14b1896..a95ed23 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -635,6 +635,11 @@ extern Datum regnamespaceout(PG_FUNCTION_ARGS);
 extern Datum regnamespacerecv(PG_FUNCTION_ARGS);
 extern Datum regnamespacesend(PG_FUNCTION_ARGS);
 extern Datum to_regnamespace(PG_FUNCTION_ARGS);
+extern Datum regrolein(PG_FUNCTION_ARGS);
+extern Datum regroleout(PG_FUNCTION_ARGS);
+extern Datum regrolerecv(PG_FUNCTION_ARGS);
+extern Datum regrolesend(PG_FUNCTION_ARGS);
+extern Datum to_regrole(PG_FUNCTION_ARGS);
 extern Datum regconfigin(PG_FUNCTION_ARGS);
 extern Datum regconfigout(PG_FUNCTION_ARGS);
 extern Datum regconfigrecv(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/regproc.out b/src/test/regress/expected/regproc.out
index 44166a2..479a964 100644
--- a/src/test/regress/expected/regproc.out
+++ b/src/test/regress/expected/regproc.out
@@ -2,6 +2,7 @@
 -- regproc
 --
 /* If objects exist, return oids */
+CREATE ROLE regtestrole;
 -- without schemaname
 SELECT regoper('||/');
  regoper 
@@ -45,6 +46,12 @@ SELECT regnamespace('pg_catalog');
  pg_catalog
 (1 row)
 
+SELECT regrole('regtestrole');
+   regrole   
+-------------
+ regtestrole
+(1 row)
+
 SELECT to_regoper('||/');
  to_regoper 
 ------------
@@ -87,6 +94,12 @@ SELECT to_regnamespace('pg_catalog');
  pg_catalog
 (1 row)
 
+SELECT to_regrole('regtestrole');
+ to_regrole  
+-------------
+ regtestrole
+(1 row)
+
 -- with schemaname
 SELECT regoper('pg_catalog.||/');
  regoper 
@@ -155,10 +168,11 @@ SELECT to_regtype('pg_catalog.int4');
 (1 row)
 
 /* If objects don't exist, raise errors. */
+DROP ROLE regtestrole;
 -- without schemaname
 SELECT regoper('||//');
 ERROR:  operator does not exist: ||//
-LINE 3: SELECT regoper('||//');
+LINE 1: SELECT regoper('||//');
                        ^
 SELECT regoperator('++(int4,int4)');
 ERROR:  operator does not exist: ++(int4,int4)
@@ -184,6 +198,10 @@ SELECT regnamespace('nonexistent');
 ERROR:  schema "nonexistent" does not exist
 LINE 1: SELECT regnamespace('nonexistent');
                             ^
+SELECT regrole('regtestrole');
+ERROR:  role "regtestrole" does not exist
+LINE 1: SELECT regrole('regtestrole');
+                       ^
 -- with schemaname
 SELECT regoper('ng_catalog.||/');
 ERROR:  schema "ng_catalog" does not exist
@@ -253,6 +271,12 @@ SELECT to_regnamespace('nonexistent');
  
 (1 row)
 
+SELECT to_regrole('regtestrole');
+ to_regrole 
+------------
+ 
+(1 row)
+
 -- with schemaname
 SELECT to_regoper('ng_catalog.||/');
  to_regoper 
diff --git a/src/test/regress/sql/regproc.sql b/src/test/regress/sql/regproc.sql
index 04eed63..9a9a44d 100644
--- a/src/test/regress/sql/regproc.sql
+++ b/src/test/regress/sql/regproc.sql
@@ -4,6 +4,7 @@
 
 /* If objects exist, return oids */
 
+CREATE ROLE regtestrole;
 -- without schemaname
 
 SELECT regoper('||/');
@@ -13,6 +14,7 @@ SELECT regprocedure('abs(numeric)');
 SELECT regclass('pg_class');
 SELECT regtype('int4');
 SELECT regnamespace('pg_catalog');
+SELECT regrole('regtestrole');
 
 SELECT to_regoper('||/');
 SELECT to_regoperator('+(int4,int4)');
@@ -21,6 +23,7 @@ SELECT to_regprocedure('abs(numeric)');
 SELECT to_regclass('pg_class');
 SELECT to_regtype('int4');
 SELECT to_regnamespace('pg_catalog');
+SELECT to_regrole('regtestrole');
 
 -- with schemaname
 
@@ -39,6 +42,8 @@ SELECT to_regtype('pg_catalog.int4');
 
 /* If objects don't exist, raise errors. */
 
+DROP ROLE regtestrole;
+
 -- without schemaname
 
 SELECT regoper('||//');
@@ -48,6 +53,7 @@ SELECT regprocedure('absinthe(numeric)');
 SELECT regclass('pg_classes');
 SELECT regtype('int3');
 SELECT regnamespace('nonexistent');
+SELECT regrole('regtestrole');
 
 -- with schemaname
 
@@ -69,6 +75,7 @@ SELECT to_regprocedure('absinthe(numeric)');
 SELECT to_regclass('pg_classes');
 SELECT to_regtype('int3');
 SELECT to_regnamespace('nonexistent');
+SELECT to_regrole('regtestrole');
 
 -- with schemaname
 
-- 
2.1.0.GIT

