diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
new file mode 100644
index 6e2fbda..bd97460
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
*************** SELECT pg_type_is_visible('myschema.widg
*** 15279,15284 ****
--- 15279,15300 ----
      <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.
*************** SELECT pg_type_is_visible('myschema.widg
*** 15449,15454 ****
--- 15465,15490 ----
         <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>
*************** SELECT collation for ('foo' COLLATE "de_
*** 15614,15619 ****
--- 15650,15667 ----
    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>
+    work like casts to <type>regclass</>, <type>regproc</>, <type>regoper</> and
+    <type>regtype</>, respectively, except that they return NULL when no
+    object by that name is found, or in the case of
+    <function>to_regproc</function> and <function>to_regoper</function>
+    when more than one object with that name is found, rather than raising
+    an error. In addition, these don't accept a numeric OID; the input must be
+    an existing object name.
+   </para>
+ 
     <indexterm>
      <primary>col_description</primary>
     </indexterm>
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
new file mode 100644
index 6c2a5d2..5bf6d28
*** a/src/backend/catalog/namespace.c
--- b/src/backend/catalog/namespace.c
*************** OpernameGetOprid(List *names, Oid oprlef
*** 1556,1562 ****
   * will be InvalidOid for a prefix or postfix oprkind.	nargs is 2, too.
   */
  FuncCandidateList
! OpernameGetCandidates(List *names, char oprkind)
  {
  	FuncCandidateList resultList = NULL;
  	char	   *resultSpace = NULL;
--- 1556,1562 ----
   * will be InvalidOid for a prefix or postfix oprkind.	nargs is 2, too.
   */
  FuncCandidateList
! OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
  {
  	FuncCandidateList resultList = NULL;
  	char	   *resultSpace = NULL;
*************** OpernameGetCandidates(List *names, char 
*** 1573,1579 ****
  	if (schemaname)
  	{
  		/* use exact schema given */
! 		namespaceId = LookupExplicitNamespace(schemaname, false);
  	}
  	else
  	{
--- 1573,1581 ----
  	if (schemaname)
  	{
  		/* use exact schema given */
! 		namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
! 		if (missing_schema_ok && !OidIsValid(namespaceId))
! 			return NULL;
  	}
  	else
  	{
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
new file mode 100644
index 99dbd30..a2b712d
*** a/src/backend/parser/parse_oper.c
--- b/src/backend/parser/parse_oper.c
*************** oper(ParseState *pstate, List *opname, O
*** 407,413 ****
  		FuncCandidateList clist;
  
  		/* Get binary operators of given name */
! 		clist = OpernameGetCandidates(opname, 'b');
  
  		/* No operators found? Then fail... */
  		if (clist != NULL)
--- 407,413 ----
  		FuncCandidateList clist;
  
  		/* Get binary operators of given name */
! 		clist = OpernameGetCandidates(opname, 'b', false);
  
  		/* No operators found? Then fail... */
  		if (clist != NULL)
*************** right_oper(ParseState *pstate, List *op,
*** 553,559 ****
  		FuncCandidateList clist;
  
  		/* Get postfix operators of given name */
! 		clist = OpernameGetCandidates(op, 'r');
  
  		/* No operators found? Then fail... */
  		if (clist != NULL)
--- 553,559 ----
  		FuncCandidateList clist;
  
  		/* Get postfix operators of given name */
! 		clist = OpernameGetCandidates(op, 'r', false);
  
  		/* No operators found? Then fail... */
  		if (clist != NULL)
*************** left_oper(ParseState *pstate, List *op, 
*** 631,637 ****
  		FuncCandidateList clist;
  
  		/* Get prefix operators of given name */
! 		clist = OpernameGetCandidates(op, 'l');
  
  		/* No operators found? Then fail... */
  		if (clist != NULL)
--- 631,637 ----
  		FuncCandidateList clist;
  
  		/* Get prefix operators of given name */
! 		clist = OpernameGetCandidates(op, 'l', false);
  
  		/* No operators found? Then fail... */
  		if (clist != NULL)
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
new file mode 100644
index b329dfb..b8c10e1
*** a/src/backend/parser/parse_type.c
--- b/src/backend/parser/parse_type.c
*************** pts_error_callback(void *arg)
*** 706,714 ****
   * 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.
   */
  void
! parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
  {
  	StringInfoData buf;
  	List	   *raw_parsetree_list;
--- 706,717 ----
   * 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,
! 				bool missing_ok)
  {
  	StringInfoData buf;
  	List	   *raw_parsetree_list;
*************** parseTypeString(const char *str, Oid *ty
*** 717,722 ****
--- 720,726 ----
  	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))
*************** parseTypeString(const char *str, Oid *ty
*** 782,788 ****
  	if (typeName->setof)
  		goto fail;
  
! 	typenameTypeIdAndMod(NULL, typeName, typeid_p, typmod_p);
  
  	pfree(buf.data);
  
--- 786,813 ----
  	if (typeName->setof)
  		goto fail;
  
! 	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);
  
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
new file mode 100644
index 5d73562..eeb8ee8
*** a/src/backend/utils/adt/regproc.c
--- b/src/backend/utils/adt/regproc.c
*************** regprocin(PG_FUNCTION_ARGS)
*** 153,158 ****
--- 153,189 ----
  }
  
  /*
+  * to_regproc	- converts "proname" to proc OID
+  *
+  * This function differs from regprocin only in returning NULL and not raising
+  * an error when the proname is not found or more than one proname is found.
+  * In addition, this doesn't accept a numeric OID or '-' that signifies unknown
+  * (OID 0). Note that this is not an I/O function.
+  *
+  * This function is not needed in bootstrap mode, so we don't worry about
+  * making it work then.
+  */
+ 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"
   */
  Datum
*************** regoperin(PG_FUNCTION_ARGS)
*** 502,508 ****
  	 * pg_operator entries in the current search path.
  	 */
  	names = stringToQualifiedNameList(opr_name_or_oid);
! 	clist = OpernameGetCandidates(names, '\0');
  
  	if (clist == NULL)
  		ereport(ERROR,
--- 533,539 ----
  	 * pg_operator entries in the current search path.
  	 */
  	names = stringToQualifiedNameList(opr_name_or_oid);
! 	clist = OpernameGetCandidates(names, '\0', false);
  
  	if (clist == NULL)
  		ereport(ERROR,
*************** regoperin(PG_FUNCTION_ARGS)
*** 520,525 ****
--- 551,587 ----
  }
  
  /*
+  * to_regoper		- converts "oprname" to operator OID
+  *
+  * This function differs from regoperin only in returning NULL and not raising
+  * an error when the opername is not found or more than one opername is found.
+  * In addition, this doesn't accept a numeric OID. Note that this is not an I/O
+  * function.
+  *
+  * This function is not needed in bootstrap mode, so we don't worry about
+  * making it work then.
+  */
+ 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"
   */
  Datum
*************** regoperout(PG_FUNCTION_ARGS)
*** 558,564 ****
  			 * qualify it.
  			 */
  			clist = OpernameGetCandidates(list_make1(makeString(oprname)),
! 										  '\0');
  			if (clist != NULL && clist->next == NULL &&
  				clist->oid == oprid)
  				result = pstrdup(oprname);
--- 620,626 ----
  			 * qualify it.
  			 */
  			clist = OpernameGetCandidates(list_make1(makeString(oprname)),
! 										  '\0', false);
  			if (clist != NULL && clist->next == NULL &&
  				clist->oid == oprid)
  				result = pstrdup(oprname);
*************** regclassin(PG_FUNCTION_ARGS)
*** 873,878 ****
--- 935,973 ----
  }
  
  /*
+  * to_regclass		- converts "classname" to class OID
+  *
+  * This function differs from regclassin only in returning NULL and not raising
+  * an error when the classname is not found. In addition, this doesn't accept a
+  * numeric OID or '-' that signifies unknown (OID 0). Note that this is not an
+  * I/O function.
+  *
+  * This function is not needed in bootstrap mode, so we don't worry about
+  * making it work then.
+  */
+ 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"
   */
  Datum
*************** regtypein(PG_FUNCTION_ARGS)
*** 1028,1039 ****
  	 * Normal case: invoke the full parser to deal with special cases such as
  	 * array syntax.
  	 */
! 	parseTypeString(typ_name_or_oid, &result, &typmod);
  
  	PG_RETURN_OID(result);
  }
  
  /*
   * regtypeout		- converts type OID to "typ_name"
   */
  Datum
--- 1123,1163 ----
  	 * Normal case: invoke the full parser to deal with special cases such as
  	 * array syntax.
  	 */
! 	parseTypeString(typ_name_or_oid, &result, &typmod, false);
  
  	PG_RETURN_OID(result);
  }
  
  /*
+  * to_regtype		- converts "typename" to type OID
+  *
+  * This function differs from regtypein only in returning NULL and not raising
+  * an error when the typename is not found. Note that this is not an I/O
+  * function. In addition, this doesn't accept a numeric OID or '-' that
+  * signifies unknown (OID 0). Note that this is not an I/O function.
+  *
+  * This function is not needed in bootstrap mode, so we don't worry about
+  * making it work then.
+  */
+ 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"
   */
  Datum
*************** parseNameAndArgTypes(const char *string,
*** 1523,1529 ****
  		else
  		{
  			/* Use full parser to resolve the type name */
! 			parseTypeString(typename, &typeid, &typmod);
  		}
  		if (*nargs >= FUNC_MAX_ARGS)
  			ereport(ERROR,
--- 1647,1653 ----
  		else
  		{
  			/* Use full parser to resolve the type name */
! 			parseTypeString(typename, &typeid, &typmod, false);
  		}
  		if (*nargs >= FUNC_MAX_ARGS)
  			ereport(ERROR,
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
new file mode 100644
index b30e5e8..2f9d391
*** a/src/include/catalog/namespace.h
--- b/src/include/catalog/namespace.h
*************** extern FuncCandidateList FuncnameGetCand
*** 76,82 ****
  extern bool FunctionIsVisible(Oid funcid);
  
  extern Oid	OpernameGetOprid(List *names, Oid oprleft, Oid oprright);
! extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind);
  extern bool OperatorIsVisible(Oid oprid);
  
  extern Oid	OpclassnameGetOpcid(Oid amid, const char *opcname);
--- 76,83 ----
  extern bool FunctionIsVisible(Oid funcid);
  
  extern Oid	OpernameGetOprid(List *names, Oid oprleft, Oid oprright);
! extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind,
! 					  bool missing_schema_ok);
  extern bool OperatorIsVisible(Oid oprid);
  
  extern Oid	OpclassnameGetOpcid(Oid amid, const char *opcname);
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index 334e6b8..21c17a0
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DATA(insert OID =  44 (  regprocin		   P
*** 173,178 ****
--- 173,180 ----
  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_ ));
*************** DATA(insert OID = 2214 (  regoperin			PG
*** 3304,3309 ****
--- 3306,3313 ----
  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_ ));
*************** DATA(insert OID = 2218 (  regclassin		PG
*** 3312,3321 ****
--- 3316,3329 ----
  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");
  
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
new file mode 100644
index ab73148..fa9cc59
*** a/src/include/parser/parse_type.h
--- b/src/include/parser/parse_type.h
*************** extern Datum stringTypeDatum(Type tp, ch
*** 47,53 ****
  
  extern Oid	typeidTypeRelid(Oid type_id);
  
! extern void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p);
  
  #define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
  
--- 47,53 ----
  
  extern Oid	typeidTypeRelid(Oid type_id);
  
! extern void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok);
  
  #define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
  
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
new file mode 100644
index 031a43a..720c831
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
*************** extern char *regexp_fixed_prefix(text *t
*** 597,602 ****
--- 597,603 ----
  /* 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);
*************** extern Datum regoperin(PG_FUNCTION_ARGS)
*** 607,612 ****
--- 608,614 ----
  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);
*************** extern Datum regclassin(PG_FUNCTION_ARGS
*** 615,624 ****
--- 617,628 ----
  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);
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
new file mode 100644
index 7bc29a6..5fff635
*** a/src/pl/plperl/plperl.c
--- b/src/pl/plperl/plperl.c
*************** plperl_spi_prepare(char *query, int argc
*** 3420,3426 ****
  			char	   *typstr;
  
  			typstr = sv2cstr(argv[i]);
! 			parseTypeString(typstr, &typId, &typmod);
  			pfree(typstr);
  
  			getTypeInputInfo(typId, &typInput, &typIOParam);
--- 3420,3426 ----
  			char	   *typstr;
  
  			typstr = sv2cstr(argv[i]);
! 			parseTypeString(typstr, &typId, &typmod, false);
  			pfree(typstr);
  
  			getTypeInputInfo(typId, &typInput, &typIOParam);
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
new file mode 100644
index 91186c6..e3a992c
*** a/src/pl/plpgsql/src/pl_gram.y
--- b/src/pl/plpgsql/src/pl_gram.y
*************** parse_datatype(const char *string, int l
*** 3492,3498 ****
  	error_context_stack = &syntax_errcontext;
  
  	/* Let the main parser try to parse it under standard SQL rules */
! 	parseTypeString(string, &type_id, &typmod);
  
  	/* Restore former ereport callback */
  	error_context_stack = syntax_errcontext.previous;
--- 3492,3498 ----
  	error_context_stack = &syntax_errcontext;
  
  	/* Let the main parser try to parse it under standard SQL rules */
! 	parseTypeString(string, &type_id, &typmod, false);
  
  	/* Restore former ereport callback */
  	error_context_stack = syntax_errcontext.previous;
diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c
new file mode 100644
index 982bf84..060d514
*** a/src/pl/plpython/plpy_spi.c
--- b/src/pl/plpython/plpy_spi.c
*************** PLy_spi_prepare(PyObject *self, PyObject
*** 113,119 ****
  			 *information for input conversion.
  			 ********************************************************/
  
! 			parseTypeString(sptr, &typeId, &typmod);
  
  			typeTup = SearchSysCache1(TYPEOID,
  									  ObjectIdGetDatum(typeId));
--- 113,119 ----
  			 *information for input conversion.
  			 ********************************************************/
  
! 			parseTypeString(sptr, &typeId, &typmod, false);
  
  			typeTup = SearchSysCache1(TYPEOID,
  									  ObjectIdGetDatum(typeId));
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
new file mode 100644
index b3bf65e..2d862a6
*** a/src/pl/tcl/pltcl.c
--- b/src/pl/tcl/pltcl.c
*************** pltcl_SPI_prepare(ClientData cdata, Tcl_
*** 2165,2171 ****
  						typIOParam;
  			int32		typmod;
  
! 			parseTypeString(args[i], &typId, &typmod);
  
  			getTypeInputInfo(typId, &typInput, &typIOParam);
  
--- 2165,2171 ----
  						typIOParam;
  			int32		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
index ...56ab245
*** a/src/test/regress/expected/regproc.out
--- b/src/test/regress/expected/regproc.out
***************
*** 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)
+ 
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
new file mode 100644
index c62be2a..c0416f4
*** a/src/test/regress/parallel_schedule
--- b/src/test/regress/parallel_schedule
*************** test: tablespace
*** 13,19 ****
  # ----------
  # 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
  
  # Depends on things setup during char, varchar and text
  test: strings
--- 13,19 ----
  # ----------
  # 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 regproc
  
  # Depends on things setup during char, varchar and text
  test: strings
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
new file mode 100644
index 885ca9a..16a1905
*** a/src/test/regress/serial_schedule
--- b/src/test/regress/serial_schedule
*************** test: enum
*** 20,25 ****
--- 20,26 ----
  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
index ...1334cfb
*** a/src/test/regress/sql/regproc.sql
--- b/src/test/regress/sql/regproc.sql
***************
*** 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');
