Add to_regprocedure() and to_regoperator().
authorRobert Haas <rhaas@postgresql.org>
Wed, 16 Apr 2014 16:21:43 +0000 (12:21 -0400)
committerRobert Haas <rhaas@postgresql.org>
Wed, 16 Apr 2014 16:21:43 +0000 (12:21 -0400)
These are natural complements to the functions added by commit
0886fc6a5c75b294544263ea979b9cf6195407d9, but they weren't included
in the original patch for some reason.  Add them.

Patch by me, per a complaint by Tom Lane.  Review by Tatsuo
Ishii.

doc/src/sgml/func.sgml
src/backend/utils/adt/regproc.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h
src/test/regress/expected/regproc.out
src/test/regress/sql/regproc.sql

index 1759c8876c40840780d5a3e30c37829f2b17cb4c..148f0bc23789b470a71a728a35fd683d87f4f83a 100644 (file)
@@ -15293,10 +15293,18 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
     <primary>to_regproc</primary>
    </indexterm>
 
+   <indexterm>
+    <primary>to_regprocedure</primary>
+   </indexterm>
+
    <indexterm>
     <primary>to_regoper</primary>
    </indexterm>
 
+   <indexterm>
+    <primary>to_regoperator</primary>
+   </indexterm>
+
    <indexterm>
     <primary>to_regtype</primary>
    </indexterm>
@@ -15481,11 +15489,21 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <entry><type>regproc</type></entry>
        <entry>get the oid of the named function</entry>
       </row>
+      <row>
+       <entry><literal><function>to_regprocedure(<parameter>func_name</parameter>)</function></literal></entry>
+       <entry><type>regprocedure</type></entry>
+       <entry>get the oid of the named function</entry>
+      </row>
       <row>
        <entry><literal><function>to_regoper(<parameter>operator_name</parameter>)</function></literal></entry>
        <entry><type>regoper</type></entry>
        <entry>get the oid of the named operator</entry>
       </row>
+      <row>
+       <entry><literal><function>to_regoperator(<parameter>operator_name</parameter>)</function></literal></entry>
+       <entry><type>regoperator</type></entry>
+       <entry>get the oid of the named operator</entry>
+      </row>
       <row>
        <entry><literal><function>to_regtype(<parameter>type_name</parameter>)</function></literal></entry>
        <entry><type>regtype</type></entry>
@@ -15658,10 +15676,12 @@ SELECT collation for ('foo' COLLATE "de_DE");
 
   <para>
    The <function>to_regclass</function>, <function>to_regproc</function>,
-   <function>to_regoper</function> and <function>to_regtype</function>
-   translate relation, function, operator, and type names to objects of
-   type <type>regclass</>, <type>regproc</>, <type>regoper</> and
-   <type>regtype</>, respectively.  These functions differ from a cast from
+   <function>to_regprocedure</function>, <function>to_regoper</function>,
+   <function>to_regoperator</function>, and <function>to_regtype</function>
+   functions translate relation, function, operator, and type names to objects
+   of type <type>regclass</>, <type>regproc</>, <type>regprocedure</type>,
+   <type>regoper</>, <type>regoperator</type>, and <type>regtype</>,
+   respectively.  These functions differ from a cast from
    text in that they don't accept a numeric OID, and that they return null
    rather than throwing an error if the name is not found (or, for
    <function>to_regproc</function> and <function>to_regoper</function>, if
index ed2bdbfb097aed9e2a47473f506f39c7023c38cf..6210f45a195bf948f74d25cf6f9db2ebe510dec0 100644 (file)
@@ -322,6 +322,38 @@ regprocedurein(PG_FUNCTION_ARGS)
    PG_RETURN_OID(result);
 }
 
+/*
+ * to_regprocedure - converts "proname(args)" to proc OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regprocedure(PG_FUNCTION_ARGS)
+{
+   char       *pro_name = PG_GETARG_CSTRING(0);
+   List       *names;
+   int         nargs;
+   Oid         argtypes[FUNC_MAX_ARGS];
+   FuncCandidateList clist;
+
+   /*
+    * Parse the name and arguments, look up potential matches in the current
+    * namespace search list, and scan to see which one exactly matches the
+    * given argument types.    (There will not be more than one match.)
+    */
+   parseNameAndArgTypes(pro_name, false, &names, &nargs, argtypes);
+
+   clist = FuncnameGetCandidates(names, nargs, NIL, false, false, true);
+
+   for (; clist; clist = clist->next)
+   {
+       if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
+           PG_RETURN_OID(clist->oid);
+   }
+
+   PG_RETURN_NULL();
+}
+
 /*
  * format_procedure        - converts proc OID to "pro_name(args)"
  *
@@ -721,6 +753,45 @@ regoperatorin(PG_FUNCTION_ARGS)
    PG_RETURN_OID(result);
 }
 
+/*
+ * to_regoperator  - converts "oprname(args)" to operator OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regoperator(PG_FUNCTION_ARGS)
+{
+   char       *opr_name_or_oid = PG_GETARG_CSTRING(0);
+   Oid         result;
+   List       *names;
+   int         nargs;
+   Oid         argtypes[FUNC_MAX_ARGS];
+
+   /*
+    * Parse the name and arguments, look up potential matches in the current
+    * namespace search list, and scan to see which one exactly matches the
+    * given argument types.    (There will not be more than one match.)
+    */
+   parseNameAndArgTypes(opr_name_or_oid, true, &names, &nargs, argtypes);
+   if (nargs == 1)
+       ereport(ERROR,
+               (errcode(ERRCODE_UNDEFINED_PARAMETER),
+                errmsg("missing argument"),
+                errhint("Use NONE to denote the missing argument of a unary operator.")));
+   if (nargs != 2)
+       ereport(ERROR,
+               (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+                errmsg("too many arguments"),
+                errhint("Provide two argument types for operator.")));
+
+   result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
+
+   if (!OidIsValid(result))
+       PG_RETURN_NULL();
+
+   PG_RETURN_OID(result);
+}
+
 /*
  * format_operator     - converts operator OID to "opr_name(args)"
  *
index 74c6bff86d7dc4e188641a05d236465d8b74298d..c96fb61ec5d60f111f0ef5a65c6fa21b35d73941 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 201404123
+#define CATALOG_VERSION_NO 201404161
 
 #endif
index 643408d250c2ab59e7b9c8b2517a4623812686da..c77c03615f10bdb189732bcb3dba211f71d12775 100644 (file)
@@ -175,6 +175,8 @@ DATA(insert OID =  45 (  regprocout        PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0
 DESCR("I/O");
 DATA(insert OID = 3494 (  to_regproc       PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 24 "2275" _null_ _null_ _null_ _null_ to_regproc _null_ _null_ _null_ ));
 DESCR("convert proname to regproc");
+DATA(insert OID = 3479 (  to_regprocedure  PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2202 "2275" _null_ _null_ _null_ _null_ to_regprocedure _null_ _null_ _null_ ));
+DESCR("convert proname to regprocedure");
 DATA(insert OID =  46 (  textin               PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "2275" _null_ _null_ _null_ _null_ textin _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID =  47 (  textout          PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "25" _null_ _null_ _null_ _null_ textout _null_ _null_ _null_ ));
@@ -3351,6 +3353,8 @@ DATA(insert OID = 2215 (  regoperout      PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2
 DESCR("I/O");
 DATA(insert OID = 3492 (  to_regoper       PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2203 "2275" _null_ _null_ _null_ _null_ to_regoper _null_ _null_ _null_ ));
 DESCR("convert operator name to regoper");
+DATA(insert OID = 3476 (  to_regoperator   PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2204 "2275" _null_ _null_ _null_ _null_ to_regoperator _null_ _null_ _null_ ));
+DESCR("convert operator name to regoperator");
 DATA(insert OID = 2216 (  regoperatorin        PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2204 "2275" _null_ _null_ _null_ _null_ regoperatorin _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2217 (  regoperatorout   PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "2204" _null_ _null_ _null_ _null_ regoperatorout _null_ _null_ _null_ ));
index 11ff4fdef0caf820ca1a112db6d9cf3698eb8063..33b6dca1919ed405d4a739ec42324239c217f69a 100644 (file)
@@ -602,6 +602,7 @@ extern char *regexp_fixed_prefix(text *text_re, bool case_insensitive,
 extern Datum regprocin(PG_FUNCTION_ARGS);
 extern Datum regprocout(PG_FUNCTION_ARGS);
 extern Datum to_regproc(PG_FUNCTION_ARGS);
+extern Datum to_regprocedure(PG_FUNCTION_ARGS);
 extern Datum regprocrecv(PG_FUNCTION_ARGS);
 extern Datum regprocsend(PG_FUNCTION_ARGS);
 extern Datum regprocedurein(PG_FUNCTION_ARGS);
@@ -613,6 +614,7 @@ extern Datum regoperout(PG_FUNCTION_ARGS);
 extern Datum regoperrecv(PG_FUNCTION_ARGS);
 extern Datum regopersend(PG_FUNCTION_ARGS);
 extern Datum to_regoper(PG_FUNCTION_ARGS);
+extern Datum to_regoperator(PG_FUNCTION_ARGS);
 extern Datum regoperatorin(PG_FUNCTION_ARGS);
 extern Datum regoperatorout(PG_FUNCTION_ARGS);
 extern Datum regoperatorrecv(PG_FUNCTION_ARGS);
index 56ab24522343979df8489781433c95cca1e58809..33421292fd17dc1cef38423442b13142fe1af051 100644 (file)
@@ -9,12 +9,24 @@ SELECT regoper('||/');
  ||/
 (1 row)
 
+SELECT regoperator('+(int4,int4)');
+    regoperator     
+--------------------
+ +(integer,integer)
+(1 row)
+
 SELECT regproc('now');
  regproc 
 ---------
  now
 (1 row)
 
+SELECT regprocedure('abs(numeric)');
+ regprocedure 
+--------------
+ abs(numeric)
+(1 row)
+
 SELECT regclass('pg_class');
  regclass 
 ----------
@@ -33,12 +45,24 @@ SELECT to_regoper('||/');
  ||/
 (1 row)
 
+SELECT to_regoperator('+(int4,int4)');
+   to_regoperator   
+--------------------
+ +(integer,integer)
+(1 row)
+
 SELECT to_regproc('now');
  to_regproc 
 ------------
  now
 (1 row)
 
+SELECT to_regprocedure('abs(numeric)');
+ to_regprocedure 
+-----------------
+ abs(numeric)
+(1 row)
+
 SELECT to_regclass('pg_class');
  to_regclass 
 -------------
@@ -58,12 +82,24 @@ SELECT regoper('pg_catalog.||/');
  ||/
 (1 row)
 
+SELECT regoperator('pg_catalog.+(int4,int4)');
+    regoperator     
+--------------------
+ +(integer,integer)
+(1 row)
+
 SELECT regproc('pg_catalog.now');
  regproc 
 ---------
  now
 (1 row)
 
+SELECT regprocedure('pg_catalog.abs(numeric)');
+ regprocedure 
+--------------
+ abs(numeric)
+(1 row)
+
 SELECT regclass('pg_catalog.pg_class');
  regclass 
 ----------
@@ -88,6 +124,12 @@ SELECT to_regproc('pg_catalog.now');
  now
 (1 row)
 
+SELECT to_regprocedure('pg_catalog.abs(numeric)');
+ to_regprocedure 
+-----------------
+ abs(numeric)
+(1 row)
+
 SELECT to_regclass('pg_catalog.pg_class');
  to_regclass 
 -------------
@@ -106,10 +148,18 @@ SELECT regoper('||//');
 ERROR:  operator does not exist: ||//
 LINE 3: SELECT regoper('||//');
                        ^
+SELECT regoperator('++(int4,int4)');
+ERROR:  operator does not exist: ++(int4,int4)
+LINE 1: SELECT regoperator('++(int4,int4)');
+                           ^
 SELECT regproc('know');
 ERROR:  function "know" does not exist
 LINE 1: SELECT regproc('know');
                        ^
+SELECT regprocedure('absinthe(numeric)');
+ERROR:  function "absinthe(numeric)" does not exist
+LINE 1: SELECT regprocedure('absinthe(numeric)');
+                            ^
 SELECT regclass('pg_classes');
 ERROR:  relation "pg_classes" does not exist
 LINE 1: SELECT regclass('pg_classes');
@@ -123,10 +173,18 @@ SELECT regoper('ng_catalog.||/');
 ERROR:  schema "ng_catalog" does not exist
 LINE 1: SELECT regoper('ng_catalog.||/');
                        ^
+SELECT regoperator('ng_catalog.+(int4,int4)');
+ERROR:  operator does not exist: ng_catalog.+(int4,int4)
+LINE 1: SELECT regoperator('ng_catalog.+(int4,int4)');
+                           ^
 SELECT regproc('ng_catalog.now');
 ERROR:  schema "ng_catalog" does not exist
 LINE 1: SELECT regproc('ng_catalog.now');
                        ^
+SELECT regprocedure('ng_catalog.abs(numeric)');
+ERROR:  schema "ng_catalog" does not exist
+LINE 1: SELECT regprocedure('ng_catalog.abs(numeric)');
+                            ^
 SELECT regclass('ng_catalog.pg_class');
 ERROR:  schema "ng_catalog" does not exist
 LINE 1: SELECT regclass('ng_catalog.pg_class');
@@ -143,12 +201,24 @@ SELECT to_regoper('||//');
  
 (1 row)
 
+SELECT to_regoperator('++(int4,int4)');
+ to_regoperator 
+----------------
+(1 row)
+
 SELECT to_regproc('know');
  to_regproc 
 ------------
  
 (1 row)
 
+SELECT to_regprocedure('absinthe(numeric)');
+ to_regprocedure 
+-----------------
+(1 row)
+
 SELECT to_regclass('pg_classes');
  to_regclass 
 -------------
@@ -168,12 +238,24 @@ SELECT to_regoper('ng_catalog.||/');
  
 (1 row)
 
+SELECT to_regoperator('ng_catalog.+(int4,int4)');
+ to_regoperator 
+----------------
+(1 row)
+
 SELECT to_regproc('ng_catalog.now');
  to_regproc 
 ------------
  
 (1 row)
 
+SELECT to_regprocedure('ng_catalog.abs(numeric)');
+ to_regprocedure 
+-----------------
+(1 row)
+
 SELECT to_regclass('ng_catalog.pg_class');
  to_regclass 
 -------------
index 1334cfb7aabc538646e67a385ef513b707657fd9..cc90838bea247fc1bd25a7cdfe5166387de0185f 100644 (file)
@@ -7,24 +7,31 @@
 -- without schemaname
 
 SELECT regoper('||/');
+SELECT regoperator('+(int4,int4)');
 SELECT regproc('now');
+SELECT regprocedure('abs(numeric)');
 SELECT regclass('pg_class');
 SELECT regtype('int4');
 
 SELECT to_regoper('||/');
+SELECT to_regoperator('+(int4,int4)');
 SELECT to_regproc('now');
+SELECT to_regprocedure('abs(numeric)');
 SELECT to_regclass('pg_class');
 SELECT to_regtype('int4');
 
 -- with schemaname
 
 SELECT regoper('pg_catalog.||/');
+SELECT regoperator('pg_catalog.+(int4,int4)');
 SELECT regproc('pg_catalog.now');
+SELECT regprocedure('pg_catalog.abs(numeric)');
 SELECT regclass('pg_catalog.pg_class');
 SELECT regtype('pg_catalog.int4');
 
 SELECT to_regoper('pg_catalog.||/');
 SELECT to_regproc('pg_catalog.now');
+SELECT to_regprocedure('pg_catalog.abs(numeric)');
 SELECT to_regclass('pg_catalog.pg_class');
 SELECT to_regtype('pg_catalog.int4');
 
@@ -33,14 +40,18 @@ SELECT to_regtype('pg_catalog.int4');
 -- without schemaname
 
 SELECT regoper('||//');
+SELECT regoperator('++(int4,int4)');
 SELECT regproc('know');
+SELECT regprocedure('absinthe(numeric)');
 SELECT regclass('pg_classes');
 SELECT regtype('int3');
 
 -- with schemaname
 
 SELECT regoper('ng_catalog.||/');
+SELECT regoperator('ng_catalog.+(int4,int4)');
 SELECT regproc('ng_catalog.now');
+SELECT regprocedure('ng_catalog.abs(numeric)');
 SELECT regclass('ng_catalog.pg_class');
 SELECT regtype('ng_catalog.int4');
 
@@ -49,13 +60,17 @@ SELECT regtype('ng_catalog.int4');
 -- without schemaname
 
 SELECT to_regoper('||//');
+SELECT to_regoperator('++(int4,int4)');
 SELECT to_regproc('know');
+SELECT to_regprocedure('absinthe(numeric)');
 SELECT to_regclass('pg_classes');
 SELECT to_regtype('int3');
 
 -- with schemaname
 
 SELECT to_regoper('ng_catalog.||/');
+SELECT to_regoperator('ng_catalog.+(int4,int4)');
 SELECT to_regproc('ng_catalog.now');
+SELECT to_regprocedure('ng_catalog.abs(numeric)');
 SELECT to_regclass('ng_catalog.pg_class');
 SELECT to_regtype('ng_catalog.int4');