>From cd1137f940aa63c3597e76fd740b05778654d3bb Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Wed, 21 Jan 2015 11:38:21 +0900
Subject: [PATCH 1/2] Add regnamespace.

---
 doc/src/sgml/datatype.sgml            | 19 ++++---
 src/backend/utils/adt/regproc.c       | 97 +++++++++++++++++++++++++++++++++++
 src/include/catalog/pg_cast.h         |  7 +++
 src/include/catalog/pg_proc.h         | 10 ++++
 src/include/catalog/pg_type.h         |  5 ++
 src/include/utils/builtins.h          |  5 ++
 src/test/regress/expected/regproc.out | 22 ++++++++
 src/test/regress/sql/regproc.sql      |  4 ++
 8 files changed, 163 insertions(+), 6 deletions(-)

diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index edf636b..9799e18 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -4422,6 +4422,13 @@ SELECT * FROM pg_attribute
        </row>
 
        <row>
+        <entry><type>regnamespace</></entry>
+        <entry><structname>pg_namespace</></entry>
+        <entry>namespace(schema) name</entry>
+        <entry><literal>pg_catalog</></entry>
+       </row>
+
+       <row>
         <entry><type>regtype</></entry>
         <entry><structname>pg_type</></entry>
         <entry>data type name</entry>
@@ -4446,12 +4453,12 @@ SELECT * FROM pg_attribute
     </table>
 
    <para>
-    All of the OID alias types 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 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 3d1bb32..b09aa2a 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -1159,6 +1159,103 @@ regclasssend(PG_FUNCTION_ARGS)
 
 
 /*
+ * regnamespacein		- converts "classname" to class 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_class entry.
+ */
+Datum
+regnamespacein(PG_FUNCTION_ARGS)
+{
+	char	   *nsp_name_or_oid = PG_GETARG_CSTRING(0);
+	Oid			result = InvalidOid;
+
+	/* '-' ? */
+	if (strcmp(nsp_name_or_oid, "-") == 0)
+		PG_RETURN_OID(InvalidOid);
+
+	/* Numeric OID? */
+	if (nsp_name_or_oid[0] >= '0' &&
+		nsp_name_or_oid[0] <= '9' &&
+		strspn(nsp_name_or_oid, "0123456789") == strlen(nsp_name_or_oid))
+	{
+		result = DatumGetObjectId(DirectFunctionCall1(oidin,
+										CStringGetDatum(nsp_name_or_oid)));
+		PG_RETURN_OID(result);
+	}
+
+	/* Else it's a name */
+
+	result = get_namespace_oid(nsp_name_or_oid, false);
+
+	PG_RETURN_OID(result);
+}
+
+/*
+ * to_regnamespace		- converts "nspname" to namespace OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regnamespace(PG_FUNCTION_ARGS)
+{
+	char	   *nsp_name = PG_GETARG_CSTRING(0);
+	Oid			result;
+
+	result = get_namespace_oid(nsp_name, true);
+
+	if (OidIsValid(result))
+		PG_RETURN_OID(result);
+	else
+		PG_RETURN_NULL();
+}
+
+/*
+ * regnamespaceout		- converts namespace OID to "nspname"
+ */
+Datum
+regnamespaceout(PG_FUNCTION_ARGS)
+{
+	Oid			nspid = PG_GETARG_OID(0);
+	char	   *result;
+
+	if (nspid == InvalidOid)
+	{
+		result = pstrdup("-");
+		PG_RETURN_CSTRING(result);
+	}
+
+	result = get_namespace_name(nspid);
+	if (result)
+		PG_RETURN_CSTRING(result);
+	else
+		PG_RETURN_NULL();
+}
+
+/*
+ *		regnamespacerecv	- converts external binary format to regnamespace
+ */
+Datum
+regnamespacerecv(PG_FUNCTION_ARGS)
+{
+	/* Exactly the same as oidrecv, so share code */
+	return oidrecv(fcinfo);
+}
+
+/*
+ *		regnamespacesend		- converts regnamespace to binary format
+ */
+Datum
+regnamespacesend(PG_FUNCTION_ARGS)
+{
+	/* Exactly the same as oidsend, so share code */
+	return oidsend(fcinfo);
+}
+
+
+/*
  * regtypein		- converts "typename" to type OID
  *
  * We also accept a numeric OID, for symmetry with the output routine.
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index b314369..e4b24e3 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -210,6 +210,13 @@ DATA(insert ( 3769	 20 1288 a f ));
 DATA(insert ( 3769	 23    0 a b ));
 DATA(insert (	25 2205 1079 i f ));
 DATA(insert ( 1043 2205 1079 i f ));
+DATA(insert (	26 4089    0 i b ));
+DATA(insert ( 4089	 26    0 i b ));
+DATA(insert (	20 4089 1287 i f ));
+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 ));
 
 /*
  * String category
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 9edfdb8..cd6dbcf 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3435,7 +3435,13 @@ DATA(insert OID = 3493 (  to_regtype		PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2
 DESCR("convert type name to regtype");
 DATA(insert OID = 1079 (  regclass			PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2205 "25" _null_ _null_ _null_ _null_	text_regclass _null_ _null_ _null_ ));
 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 = 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_ ));
@@ -3831,6 +3837,10 @@ DATA(insert OID = 2454 (  regtyperecv		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1
 DESCR("I/O");
 DATA(insert OID = 2455 (  regtypesend		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "2206" _null_ _null_ _null_ _null_	regtypesend _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 4087 (  regnamespacerecv	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 4089 "2281" _null_ _null_ _null_ _null_ regnamespacerecv _null_ _null_ _null_ ));
+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 = 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 0a900dd..4aae8b6 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -564,12 +564,17 @@ DATA(insert OID = 2206 ( regtype	   PGNSP PGUID	4 t b N f t \054 0	 0 2211 regty
 DESCR("registered type");
 #define REGTYPEOID		2206
 
+DATA(insert OID = 4089 ( regnamespace  PGNSP PGUID	4 t b N f t \054 0	 0 4090 regnamespacein regnamespaceout regnamespacerecv regnamespacesend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DESCR("registered namespace");
+#define REGNAMESPACEOID		4089
+
 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_ ));
 DATA(insert OID = 2210 ( _regclass	   PGNSP PGUID -1 f b A f t \054 0 2205 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
 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_ ));
 
 /* 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 bc4517d..14b1896 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -630,6 +630,11 @@ extern Datum regtypeout(PG_FUNCTION_ARGS);
 extern Datum regtyperecv(PG_FUNCTION_ARGS);
 extern Datum regtypesend(PG_FUNCTION_ARGS);
 extern Datum to_regtype(PG_FUNCTION_ARGS);
+extern Datum regnamespacein(PG_FUNCTION_ARGS);
+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 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 3342129..44166a2 100644
--- a/src/test/regress/expected/regproc.out
+++ b/src/test/regress/expected/regproc.out
@@ -39,6 +39,12 @@ SELECT regtype('int4');
  integer
 (1 row)
 
+SELECT regnamespace('pg_catalog');
+ regnamespace 
+--------------
+ pg_catalog
+(1 row)
+
 SELECT to_regoper('||/');
  to_regoper 
 ------------
@@ -75,6 +81,12 @@ SELECT to_regtype('int4');
  integer
 (1 row)
 
+SELECT to_regnamespace('pg_catalog');
+ to_regnamespace 
+-----------------
+ pg_catalog
+(1 row)
+
 -- with schemaname
 SELECT regoper('pg_catalog.||/');
  regoper 
@@ -168,6 +180,10 @@ SELECT regtype('int3');
 ERROR:  type "int3" does not exist
 LINE 1: SELECT regtype('int3');
                        ^
+SELECT regnamespace('nonexistent');
+ERROR:  schema "nonexistent" does not exist
+LINE 1: SELECT regnamespace('nonexistent');
+                            ^
 -- with schemaname
 SELECT regoper('ng_catalog.||/');
 ERROR:  schema "ng_catalog" does not exist
@@ -231,6 +247,12 @@ SELECT to_regtype('int3');
  
 (1 row)
 
+SELECT to_regnamespace('nonexistent');
+ to_regnamespace 
+-----------------
+ 
+(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 cc90838..04eed63 100644
--- a/src/test/regress/sql/regproc.sql
+++ b/src/test/regress/sql/regproc.sql
@@ -12,6 +12,7 @@ SELECT regproc('now');
 SELECT regprocedure('abs(numeric)');
 SELECT regclass('pg_class');
 SELECT regtype('int4');
+SELECT regnamespace('pg_catalog');
 
 SELECT to_regoper('||/');
 SELECT to_regoperator('+(int4,int4)');
@@ -19,6 +20,7 @@ SELECT to_regproc('now');
 SELECT to_regprocedure('abs(numeric)');
 SELECT to_regclass('pg_class');
 SELECT to_regtype('int4');
+SELECT to_regnamespace('pg_catalog');
 
 -- with schemaname
 
@@ -45,6 +47,7 @@ SELECT regproc('know');
 SELECT regprocedure('absinthe(numeric)');
 SELECT regclass('pg_classes');
 SELECT regtype('int3');
+SELECT regnamespace('nonexistent');
 
 -- with schemaname
 
@@ -65,6 +68,7 @@ SELECT to_regproc('know');
 SELECT to_regprocedure('absinthe(numeric)');
 SELECT to_regclass('pg_classes');
 SELECT to_regtype('int3');
+SELECT to_regnamespace('nonexistent');
 
 -- with schemaname
 
-- 
2.1.0.GIT

