]> granicus.if.org Git - postgresql/commitdiff
Add new to_reg* functions for error-free OID lookups.
authorRobert Haas <rhaas@postgresql.org>
Tue, 8 Apr 2014 14:27:56 +0000 (10:27 -0400)
committerRobert Haas <rhaas@postgresql.org>
Tue, 8 Apr 2014 14:27:56 +0000 (10:27 -0400)
These functions won't throw an error if the object doesn't exist,
or if (for functions and operators) there's more than one matching
object.

Yugo Nagata and Nozomi Anzai, reviewed by Amit Khandekar, Marti
Raudsepp, Amit Kapila, and me.

18 files changed:
doc/src/sgml/func.sgml
src/backend/catalog/namespace.c
src/backend/parser/parse_oper.c
src/backend/parser/parse_type.c
src/backend/utils/adt/regproc.c
src/include/catalog/catversion.h
src/include/catalog/namespace.h
src/include/catalog/pg_proc.h
src/include/parser/parse_type.h
src/include/utils/builtins.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_gram.y
src/pl/plpython/plpy_spi.c
src/pl/tcl/pltcl.c
src/test/regress/expected/regproc.out [new file with mode: 0644]
src/test/regress/parallel_schedule
src/test/regress/serial_schedule
src/test/regress/sql/regproc.sql [new file with mode: 0644]

index 6e2fbda6c23fa882091644ae65071f037594a3b4..33e093e2ab98faf544e2746b87270a5a3ca1a4aa 100644 (file)
@@ -15279,6 +15279,22 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
     <primary>collation for</primary>
    </indexterm>
 
+   <indexterm>
+    <primary>to_regclass</primary>
+   </indexterm>
+
+   <indexterm>
+    <primary>to_regproc</primary>
+   </indexterm>
+
+   <indexterm>
+    <primary>to_regoper</primary>
+   </indexterm>
+
+   <indexterm>
+    <primary>to_regtype</primary>
+   </indexterm>
+
   <para>
    <xref linkend="functions-info-catalog-table"> lists functions that
    extract information from the system catalogs.
@@ -15449,6 +15465,26 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <entry><type>text</type></entry>
        <entry>get the collation of the argument</entry>
       </row>
+      <row>
+       <entry><literal><function>to_regclass(<parameter>rel_name</parameter>)</function></literal></entry>
+       <entry><type>regclass</type></entry>
+       <entry>get the oid of the named relation</entry>
+      </row>
+      <row>
+       <entry><literal><function>to_regproc(<parameter>func_name</parameter>)</function></literal></entry>
+       <entry><type>regproc</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_regtype(<parameter>type_name</parameter>)</function></literal></entry>
+       <entry><type>regtype</type></entry>
+       <entry>get the oid of the named type</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -15614,6 +15650,18 @@ SELECT collation for ('foo' COLLATE "de_DE");
   is not of a collatable data type, then an error is raised.
   </para>
 
+  <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
+   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
+   the given name matches multiple objects).
+  </para>
+
    <indexterm>
     <primary>col_description</primary>
    </indexterm>
index 6c2a5d2af5aef659e2196210fab535c1324b18c6..5bf6d289d84a2fac8ba66aea24b4afa73bb83200 100644 (file)
@@ -1556,7 +1556,7 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
  * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
  */
 FuncCandidateList
-OpernameGetCandidates(List *names, char oprkind)
+OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
 {
        FuncCandidateList resultList = NULL;
        char       *resultSpace = NULL;
@@ -1573,7 +1573,9 @@ OpernameGetCandidates(List *names, char oprkind)
        if (schemaname)
        {
                /* use exact schema given */
-               namespaceId = LookupExplicitNamespace(schemaname, false);
+               namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
+               if (missing_schema_ok && !OidIsValid(namespaceId))
+                       return NULL;
        }
        else
        {
index 99dbd30d758b564b4de6ab255765d06bc49ece28..a2b712d516160b8f45946c6de1bc224141fc4543 100644 (file)
@@ -407,7 +407,7 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
                FuncCandidateList clist;
 
                /* Get binary operators of given name */
-               clist = OpernameGetCandidates(opname, 'b');
+               clist = OpernameGetCandidates(opname, 'b', false);
 
                /* No operators found? Then fail... */
                if (clist != NULL)
@@ -553,7 +553,7 @@ right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
                FuncCandidateList clist;
 
                /* Get postfix operators of given name */
-               clist = OpernameGetCandidates(op, 'r');
+               clist = OpernameGetCandidates(op, 'r', false);
 
                /* No operators found? Then fail... */
                if (clist != NULL)
@@ -631,7 +631,7 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
                FuncCandidateList clist;
 
                /* Get prefix operators of given name */
-               clist = OpernameGetCandidates(op, 'l');
+               clist = OpernameGetCandidates(op, 'l', false);
 
                /* No operators found? Then fail... */
                if (clist != NULL)
index b329dfb168493ccdb61636cb023c501ab9dd661e..b8c10e11c9f9e9deb2abfb28590c59feed017382 100644 (file)
@@ -706,9 +706,12 @@ pts_error_callback(void *arg)
  * Given a string that is supposed to be a SQL-compatible type declaration,
  * such as "int4" or "integer" or "character varying(32)", parse
  * the string and convert it to a type OID and type modifier.
+ * If missing_ok is true, InvalidOid is returned rather than raising an error
+ * when the type name is not found.
  */
 void
-parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
+parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p,
+                               bool missing_ok)
 {
        StringInfoData buf;
        List       *raw_parsetree_list;
@@ -717,6 +720,7 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
        TypeCast   *typecast;
        TypeName   *typeName;
        ErrorContextCallback ptserrcontext;
+       Type            tup;
 
        /* make sure we give useful error for empty input */
        if (strspn(str, " \t\n\r\f") == strlen(str))
@@ -782,7 +786,28 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
        if (typeName->setof)
                goto fail;
 
-       typenameTypeIdAndMod(NULL, typeName, typeid_p, typmod_p);
+       tup = LookupTypeName(NULL, typeName, typmod_p, missing_ok);
+       if (tup == NULL)
+       {
+               if (!missing_ok)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                       errmsg("type \"%s\" does not exist",
+                                                       TypeNameToString(typeName)),
+                                       parser_errposition(NULL, typeName->location)));
+               *typeid_p = InvalidOid;
+       }
+       else
+       {
+               if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                       errmsg("type \"%s\" is only a shell",
+                                                       TypeNameToString(typeName)),
+                                       parser_errposition(NULL, typeName->location)));
+               *typeid_p = HeapTupleGetOid(tup);
+               ReleaseSysCache(tup);
+       }
 
        pfree(buf.data);
 
index 5d73562a4fc324b9028de329fae59168eca845f5..ed2bdbfb097aed9e2a47473f506f39c7023c38cf 100644 (file)
@@ -152,6 +152,31 @@ regprocin(PG_FUNCTION_ARGS)
        PG_RETURN_OID(result);
 }
 
+/*
+ * to_regproc  - converts "proname" to proc OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regproc(PG_FUNCTION_ARGS)
+{
+       char       *pro_name = PG_GETARG_CSTRING(0);
+       List       *names;
+       FuncCandidateList clist;
+
+       /*
+        * Parse the name into components and see if it matches any pg_proc entries
+        * in the current search path.
+        */
+       names = stringToQualifiedNameList(pro_name);
+       clist = FuncnameGetCandidates(names, -1, NIL, false, false, true);
+
+       if (clist == NULL || clist->next != NULL)
+               PG_RETURN_NULL();
+
+       PG_RETURN_OID(clist->oid);
+}
+
 /*
  * regprocout          - converts proc OID to "pro_name"
  */
@@ -502,7 +527,7 @@ regoperin(PG_FUNCTION_ARGS)
         * pg_operator entries in the current search path.
         */
        names = stringToQualifiedNameList(opr_name_or_oid);
-       clist = OpernameGetCandidates(names, '\0');
+       clist = OpernameGetCandidates(names, '\0', false);
 
        if (clist == NULL)
                ereport(ERROR,
@@ -519,6 +544,31 @@ regoperin(PG_FUNCTION_ARGS)
        PG_RETURN_OID(result);
 }
 
+/*
+ * to_regoper          - converts "oprname" to operator OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regoper(PG_FUNCTION_ARGS)
+{
+       char       *opr_name = PG_GETARG_CSTRING(0);
+       List       *names;
+       FuncCandidateList clist;
+
+       /*
+        * Parse the name into components and see if it matches any pg_operator
+        * entries in the current search path.
+        */
+       names = stringToQualifiedNameList(opr_name);
+       clist = OpernameGetCandidates(names, '\0', true);
+
+       if (clist == NULL || clist->next != NULL)
+               PG_RETURN_NULL();
+
+       PG_RETURN_OID(clist->oid);
+}
+
 /*
  * regoperout          - converts operator OID to "opr_name"
  */
@@ -558,7 +608,7 @@ regoperout(PG_FUNCTION_ARGS)
                         * qualify it.
                         */
                        clist = OpernameGetCandidates(list_make1(makeString(oprname)),
-                                                                                 '\0');
+                                                                                 '\0', false);
                        if (clist != NULL && clist->next == NULL &&
                                clist->oid == oprid)
                                result = pstrdup(oprname);
@@ -872,6 +922,33 @@ regclassin(PG_FUNCTION_ARGS)
        PG_RETURN_OID(result);
 }
 
+/*
+ * to_regclass         - converts "classname" to class OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regclass(PG_FUNCTION_ARGS)
+{
+       char       *class_name = PG_GETARG_CSTRING(0);
+       Oid                     result;
+       List       *names;
+
+       /*
+        * Parse the name into components and see if it matches any pg_class entries
+        * in the current search path.
+        */
+       names = stringToQualifiedNameList(class_name);
+
+       /* We might not even have permissions on this relation; don't lock it. */
+       result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
+
+       if (OidIsValid(result))
+               PG_RETURN_OID(result);
+       else
+               PG_RETURN_NULL();
+}
+
 /*
  * regclassout         - converts class OID to "class_name"
  */
@@ -1028,11 +1105,34 @@ regtypein(PG_FUNCTION_ARGS)
         * Normal case: invoke the full parser to deal with special cases such as
         * array syntax.
         */
-       parseTypeString(typ_name_or_oid, &result, &typmod);
+       parseTypeString(typ_name_or_oid, &result, &typmod, false);
 
        PG_RETURN_OID(result);
 }
 
+/*
+ * to_regtype          - converts "typename" to type OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regtype(PG_FUNCTION_ARGS)
+{
+       char       *typ_name = PG_GETARG_CSTRING(0);
+       Oid                     result;
+       int32           typmod;
+
+       /*
+        * Invoke the full parser to deal with special cases such as array syntax.
+        */
+       parseTypeString(typ_name, &result, &typmod, true);
+
+       if (OidIsValid(result))
+               PG_RETURN_OID(result);
+       else
+               PG_RETURN_NULL();
+}
+
 /*
  * regtypeout          - converts type OID to "typ_name"
  */
@@ -1523,7 +1623,7 @@ parseNameAndArgTypes(const char *string, bool allowNone, List **names,
                else
                {
                        /* Use full parser to resolve the type name */
-                       parseTypeString(typename, &typeid, &typmod);
+                       parseTypeString(typename, &typeid, &typmod, false);
                }
                if (*nargs >= FUNC_MAX_ARGS)
                        ereport(ERROR,
index e1a04c88b20bf2a61b5d5a43a47e4dd9ee10ae75..4b3357ccd9710ba7f42a9e9afddcaac895fd6ca6 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201404031
+#define CATALOG_VERSION_NO     201404081
 
 #endif
index b30e5e8d02544c4afcfecfd97343951b0c6e3a91..2f9d391d28f884c3bf57bb88f161a904caf198c2 100644 (file)
@@ -76,7 +76,8 @@ extern FuncCandidateList FuncnameGetCandidates(List *names,
 extern bool FunctionIsVisible(Oid funcid);
 
 extern Oid     OpernameGetOprid(List *names, Oid oprleft, Oid oprright);
-extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind);
+extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind,
+                                         bool missing_schema_ok);
 extern bool OperatorIsVisible(Oid oprid);
 
 extern Oid     OpclassnameGetOpcid(Oid amid, const char *opcname);
index 334e6b8d15578e24f5a8a56f696394f031aafeb6..21c17a08ed4c324634fff79e3a53782f3e08c114 100644 (file)
@@ -173,6 +173,8 @@ DATA(insert OID =  44 (  regprocin             PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0
 DESCR("I/O");
 DATA(insert OID =  45 (  regprocout               PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "24" _null_ _null_ _null_ _null_ regprocout _null_ _null_ _null_ ));
 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 =  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_ ));
@@ -3304,6 +3306,8 @@ DATA(insert OID = 2214 (  regoperin                       PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2
 DESCR("I/O");
 DATA(insert OID = 2215 (  regoperout           PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "2203" _null_ _null_ _null_ _null_ regoperout _null_ _null_ _null_ ));
 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 = 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_ ));
@@ -3312,10 +3316,14 @@ DATA(insert OID = 2218 (  regclassin            PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2
 DESCR("I/O");
 DATA(insert OID = 2219 (  regclassout          PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "2205" _null_ _null_ _null_ _null_ regclassout _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 3495 (  to_regclass          PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2205 "2275" _null_ _null_ _null_ _null_ to_regclass _null_ _null_ _null_ ));
+DESCR("convert classname to regclass");
 DATA(insert OID = 2220 (  regtypein                    PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2206 "2275" _null_ _null_ _null_ _null_ regtypein _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2221 (  regtypeout           PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2275 "2206" _null_ _null_ _null_ _null_ regtypeout _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 3493 (  to_regtype           PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2206 "2275" _null_ _null_ _null_ _null_ to_regtype _null_ _null_ _null_ ));
+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");
 
index ab73148dcaadc32d231d6eb0c3d53b6288ec418e..fa9cc5989bd242381c17060b38f001d17e4e8ca9 100644 (file)
@@ -47,7 +47,7 @@ extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod);
 
 extern Oid     typeidTypeRelid(Oid type_id);
 
-extern void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p);
+extern void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok);
 
 #define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
 
index 031a43a7e78c7d75ba98b3d276e06001ecb94bfc..720c83180113e8642b0b2b66b408b6dd8827979b 100644 (file)
@@ -597,6 +597,7 @@ extern char *regexp_fixed_prefix(text *text_re, bool case_insensitive,
 /* regproc.c */
 extern Datum regprocin(PG_FUNCTION_ARGS);
 extern Datum regprocout(PG_FUNCTION_ARGS);
+extern Datum to_regproc(PG_FUNCTION_ARGS);
 extern Datum regprocrecv(PG_FUNCTION_ARGS);
 extern Datum regprocsend(PG_FUNCTION_ARGS);
 extern Datum regprocedurein(PG_FUNCTION_ARGS);
@@ -607,6 +608,7 @@ extern Datum regoperin(PG_FUNCTION_ARGS);
 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 regoperatorin(PG_FUNCTION_ARGS);
 extern Datum regoperatorout(PG_FUNCTION_ARGS);
 extern Datum regoperatorrecv(PG_FUNCTION_ARGS);
@@ -615,10 +617,12 @@ extern Datum regclassin(PG_FUNCTION_ARGS);
 extern Datum regclassout(PG_FUNCTION_ARGS);
 extern Datum regclassrecv(PG_FUNCTION_ARGS);
 extern Datum regclasssend(PG_FUNCTION_ARGS);
+extern Datum to_regclass(PG_FUNCTION_ARGS);
 extern Datum regtypein(PG_FUNCTION_ARGS);
 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 regconfigin(PG_FUNCTION_ARGS);
 extern Datum regconfigout(PG_FUNCTION_ARGS);
 extern Datum regconfigrecv(PG_FUNCTION_ARGS);
index 7bc29a6b3241d1179f2180fc3166914fbe70d27e..5fff63558f1272e452f12a5a8c8b6c2722bbd8f7 100644 (file)
@@ -3420,7 +3420,7 @@ plperl_spi_prepare(char *query, int argc, SV **argv)
                        char       *typstr;
 
                        typstr = sv2cstr(argv[i]);
-                       parseTypeString(typstr, &typId, &typmod);
+                       parseTypeString(typstr, &typId, &typmod, false);
                        pfree(typstr);
 
                        getTypeInputInfo(typId, &typInput, &typIOParam);
index 91186c6b9aefd47bb7b7059d460326ebc00eec1f..e3a992cf0ff57fc1e2cfc455fd4c2390f666ed1c 100644 (file)
@@ -3492,7 +3492,7 @@ parse_datatype(const char *string, int location)
        error_context_stack = &syntax_errcontext;
 
        /* Let the main parser try to parse it under standard SQL rules */
-       parseTypeString(string, &type_id, &typmod);
+       parseTypeString(string, &type_id, &typmod, false);
 
        /* Restore former ereport callback */
        error_context_stack = syntax_errcontext.previous;
index 982bf84e0e544661f41d98ca7a6eeeddda288036..060d514a80dccdcf6c4c8d4a345e862b0edbaa9c 100644 (file)
@@ -113,7 +113,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
                         *information for input conversion.
                         ********************************************************/
 
-                       parseTypeString(sptr, &typeId, &typmod);
+                       parseTypeString(sptr, &typeId, &typmod, false);
 
                        typeTup = SearchSysCache1(TYPEOID,
                                                                          ObjectIdGetDatum(typeId));
index b3bf65ec885e3cc25c8d911af02ecd4b1aa348ec..2d862a6b059560bb347ad6dac20629890413377f 100644 (file)
@@ -2165,7 +2165,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
                                                typIOParam;
                        int32           typmod;
 
-                       parseTypeString(args[i], &typId, &typmod);
+                       parseTypeString(args[i], &typId, &typmod, false);
 
                        getTypeInputInfo(typId, &typInput, &typIOParam);
 
diff --git a/src/test/regress/expected/regproc.out b/src/test/regress/expected/regproc.out
new file mode 100644 (file)
index 0000000..56ab245
--- /dev/null
@@ -0,0 +1,188 @@
+--
+-- regproc
+--
+/* If objects exist, return oids */
+-- without schemaname
+SELECT regoper('||/');
+ regoper 
+---------
+ ||/
+(1 row)
+
+SELECT regproc('now');
+ regproc 
+---------
+ now
+(1 row)
+
+SELECT regclass('pg_class');
+ regclass 
+----------
+ pg_class
+(1 row)
+
+SELECT regtype('int4');
+ regtype 
+---------
+ integer
+(1 row)
+
+SELECT to_regoper('||/');
+ to_regoper 
+------------
+ ||/
+(1 row)
+
+SELECT to_regproc('now');
+ to_regproc 
+------------
+ now
+(1 row)
+
+SELECT to_regclass('pg_class');
+ to_regclass 
+-------------
+ pg_class
+(1 row)
+
+SELECT to_regtype('int4');
+ to_regtype 
+------------
+ integer
+(1 row)
+
+-- with schemaname
+SELECT regoper('pg_catalog.||/');
+ regoper 
+---------
+ ||/
+(1 row)
+
+SELECT regproc('pg_catalog.now');
+ regproc 
+---------
+ now
+(1 row)
+
+SELECT regclass('pg_catalog.pg_class');
+ regclass 
+----------
+ pg_class
+(1 row)
+
+SELECT regtype('pg_catalog.int4');
+ regtype 
+---------
+ integer
+(1 row)
+
+SELECT to_regoper('pg_catalog.||/');
+ to_regoper 
+------------
+ ||/
+(1 row)
+
+SELECT to_regproc('pg_catalog.now');
+ to_regproc 
+------------
+ now
+(1 row)
+
+SELECT to_regclass('pg_catalog.pg_class');
+ to_regclass 
+-------------
+ pg_class
+(1 row)
+
+SELECT to_regtype('pg_catalog.int4');
+ to_regtype 
+------------
+ integer
+(1 row)
+
+/* If objects don't exist, raise errors. */
+-- without schemaname
+SELECT regoper('||//');
+ERROR:  operator does not exist: ||//
+LINE 3: SELECT regoper('||//');
+                       ^
+SELECT regproc('know');
+ERROR:  function "know" does not exist
+LINE 1: SELECT regproc('know');
+                       ^
+SELECT regclass('pg_classes');
+ERROR:  relation "pg_classes" does not exist
+LINE 1: SELECT regclass('pg_classes');
+                        ^
+SELECT regtype('int3');
+ERROR:  type "int3" does not exist
+LINE 1: SELECT regtype('int3');
+                       ^
+-- with schemaname
+SELECT regoper('ng_catalog.||/');
+ERROR:  schema "ng_catalog" does not exist
+LINE 1: SELECT regoper('ng_catalog.||/');
+                       ^
+SELECT regproc('ng_catalog.now');
+ERROR:  schema "ng_catalog" does not exist
+LINE 1: SELECT regproc('ng_catalog.now');
+                       ^
+SELECT regclass('ng_catalog.pg_class');
+ERROR:  schema "ng_catalog" does not exist
+LINE 1: SELECT regclass('ng_catalog.pg_class');
+                        ^
+SELECT regtype('ng_catalog.int4');
+ERROR:  schema "ng_catalog" does not exist
+LINE 1: SELECT regtype('ng_catalog.int4');
+                       ^
+/* If objects don't exist, return NULL with no error. */
+-- without schemaname
+SELECT to_regoper('||//');
+ to_regoper 
+------------
+(1 row)
+
+SELECT to_regproc('know');
+ to_regproc 
+------------
+(1 row)
+
+SELECT to_regclass('pg_classes');
+ to_regclass 
+-------------
+(1 row)
+
+SELECT to_regtype('int3');
+ to_regtype 
+------------
+(1 row)
+
+-- with schemaname
+SELECT to_regoper('ng_catalog.||/');
+ to_regoper 
+------------
+(1 row)
+
+SELECT to_regproc('ng_catalog.now');
+ to_regproc 
+------------
+(1 row)
+
+SELECT to_regclass('ng_catalog.pg_class');
+ to_regclass 
+-------------
+(1 row)
+
+SELECT to_regtype('ng_catalog.int4');
+ to_regtype 
+------------
+(1 row)
+
index c62be2a023e09a1ab8165a2841aad89510901328..c0416f4fb9d640fdbbe6233e72691f1bb05bcd81 100644 (file)
@@ -13,7 +13,7 @@ test: tablespace
 # ----------
 # The first group of parallel tests
 # ----------
-test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes pg_lsn
+test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes pg_lsn regproc
 
 # Depends on things setup during char, varchar and text
 test: strings
index 885ca9aa5ddae3086db57a57aa6dda8f7c681ff9..16a190507d556c2860ff70c6aa576847bb17da7c 100644 (file)
@@ -20,6 +20,7 @@ test: enum
 test: money
 test: rangetypes
 test: pg_lsn
+test: regproc
 test: strings
 test: numerology
 test: point
diff --git a/src/test/regress/sql/regproc.sql b/src/test/regress/sql/regproc.sql
new file mode 100644 (file)
index 0000000..1334cfb
--- /dev/null
@@ -0,0 +1,61 @@
+--
+-- regproc
+--
+
+/* If objects exist, return oids */
+
+-- without schemaname
+
+SELECT regoper('||/');
+SELECT regproc('now');
+SELECT regclass('pg_class');
+SELECT regtype('int4');
+
+SELECT to_regoper('||/');
+SELECT to_regproc('now');
+SELECT to_regclass('pg_class');
+SELECT to_regtype('int4');
+
+-- with schemaname
+
+SELECT regoper('pg_catalog.||/');
+SELECT regproc('pg_catalog.now');
+SELECT regclass('pg_catalog.pg_class');
+SELECT regtype('pg_catalog.int4');
+
+SELECT to_regoper('pg_catalog.||/');
+SELECT to_regproc('pg_catalog.now');
+SELECT to_regclass('pg_catalog.pg_class');
+SELECT to_regtype('pg_catalog.int4');
+
+/* If objects don't exist, raise errors. */
+
+-- without schemaname
+
+SELECT regoper('||//');
+SELECT regproc('know');
+SELECT regclass('pg_classes');
+SELECT regtype('int3');
+
+-- with schemaname
+
+SELECT regoper('ng_catalog.||/');
+SELECT regproc('ng_catalog.now');
+SELECT regclass('ng_catalog.pg_class');
+SELECT regtype('ng_catalog.int4');
+
+/* If objects don't exist, return NULL with no error. */
+
+-- without schemaname
+
+SELECT to_regoper('||//');
+SELECT to_regproc('know');
+SELECT to_regclass('pg_classes');
+SELECT to_regtype('int3');
+
+-- with schemaname
+
+SELECT to_regoper('ng_catalog.||/');
+SELECT to_regproc('ng_catalog.now');
+SELECT to_regclass('ng_catalog.pg_class');
+SELECT to_regtype('ng_catalog.int4');