diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 6e2fbda6c23fa882091644ae65071f037594a3b4..33e093e2ab98faf544e2746b87270a5a3ca1a4aa 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -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>
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 6c2a5d2af5aef659e2196210fab535c1324b18c6..5bf6d289d84a2fac8ba66aea24b4afa73bb83200 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -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
 	{
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 99dbd30d758b564b4de6ab255765d06bc49ece28..a2b712d516160b8f45946c6de1bc224141fc4543 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -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)
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index b329dfb168493ccdb61636cb023c501ab9dd661e..b8c10e11c9f9e9deb2abfb28590c59feed017382 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -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);
 
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 5d73562a4fc324b9028de329fae59168eca845f5..ed2bdbfb097aed9e2a47473f506f39c7023c38cf 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -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,
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index e1a04c88b20bf2a61b5d5a43a47e4dd9ee10ae75..4b3357ccd9710ba7f42a9e9afddcaac895fd6ca6 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	201404031
+#define CATALOG_VERSION_NO	201404081
 
 #endif
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index b30e5e8d02544c4afcfecfd97343951b0c6e3a91..2f9d391d28f884c3bf57bb88f161a904caf198c2 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -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);
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 334e6b8d15578e24f5a8a56f696394f031aafeb6..21c17a08ed4c324634fff79e3a53782f3e08c114 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -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");
 
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
index ab73148dcaadc32d231d6eb0c3d53b6288ec418e..fa9cc5989bd242381c17060b38f001d17e4e8ca9 100644
--- a/src/include/parser/parse_type.h
+++ b/src/include/parser/parse_type.h
@@ -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)
 
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 031a43a7e78c7d75ba98b3d276e06001ecb94bfc..720c83180113e8642b0b2b66b408b6dd8827979b 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -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);
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 7bc29a6b3241d1179f2180fc3166914fbe70d27e..5fff63558f1272e452f12a5a8c8b6c2722bbd8f7 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -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);
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 91186c6b9aefd47bb7b7059d460326ebc00eec1f..e3a992cf0ff57fc1e2cfc455fd4c2390f666ed1c 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -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;
diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c
index 982bf84e0e544661f41d98ca7a6eeeddda288036..060d514a80dccdcf6c4c8d4a345e862b0edbaa9c 100644
--- a/src/pl/plpython/plpy_spi.c
+++ b/src/pl/plpython/plpy_spi.c
@@ -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));
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index b3bf65ec885e3cc25c8d911af02ecd4b1aa348ec..2d862a6b059560bb347ad6dac20629890413377f 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -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
index 0000000000000000000000000000000000000000..56ab24522343979df8489781433c95cca1e58809
--- /dev/null
+++ b/src/test/regress/expected/regproc.out
@@ -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)
+
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index c62be2a023e09a1ab8165a2841aad89510901328..c0416f4fb9d640fdbbe6233e72691f1bb05bcd81 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -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
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 885ca9aa5ddae3086db57a57aa6dda8f7c681ff9..16a190507d556c2860ff70c6aa576847bb17da7c 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -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
index 0000000000000000000000000000000000000000..1334cfb7aabc538646e67a385ef513b707657fd9
--- /dev/null
+++ b/src/test/regress/sql/regproc.sql
@@ -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');