diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index cdd5006..e4c9a4f 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -664,6 +664,39 @@ RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
 }
 
 /*
+ * RangeVarCheckNamespaceAccessNoError
+ * 		Returns true if given relation's namespace can be accessable by the
+ * 		current user. If no namespace is given in the relation, just returns
+ * 		true.
+ */
+bool
+RangeVarCheckNamespaceAccessNoError(RangeVar *relation)
+{
+	Oid namespaceId;
+	AclResult	aclresult;
+
+	if (relation->catalogname)
+	{
+		if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
+			/* Cross-database references is not allowed */
+			return false;
+	}
+	if (relation->schemaname)
+	{
+		namespaceId = get_namespace_oid(relation->schemaname, true);
+		if (!OidIsValid(namespaceId))
+			/* Namespace is invalid */
+			return false;
+		aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
+		if (aclresult != ACLCHECK_OK)
+			/* Namespace ACL is not ok */
+			return false;
+	}
+
+	return true;
+}
+
+/*
  * RelnameGetRelid
  *		Try to resolve an unqualified relation name.
  *		Returns OID if relation found in search path, else InvalidOid.
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 09cf0e1..6828633 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -128,6 +128,8 @@ to_regproc(PG_FUNCTION_ARGS)
 	 * entries in the current search path.
 	 */
 	names = stringToQualifiedNameList(pro_name);
+	if (!RangeVarCheckNamespaceAccessNoError(makeRangeVarFromNameList(names)))
+		PG_RETURN_NULL();
 	clist = FuncnameGetCandidates(names, -1, NIL, false, false, true);
 
 	if (clist == NULL || clist->next != NULL)
@@ -301,6 +303,8 @@ to_regprocedure(PG_FUNCTION_ARGS)
 	 * given argument types.    (There will not be more than one match.)
 	 */
 	parseNameAndArgTypes(pro_name, false, &names, &nargs, argtypes);
+	if (!RangeVarCheckNamespaceAccessNoError(makeRangeVarFromNameList(names)))
+		PG_RETURN_NULL();
 
 	clist = FuncnameGetCandidates(names, nargs, NIL, false, false, true);
 
@@ -546,6 +550,8 @@ to_regoper(PG_FUNCTION_ARGS)
 	 * entries in the current search path.
 	 */
 	names = stringToQualifiedNameList(opr_name);
+	if (!RangeVarCheckNamespaceAccessNoError(makeRangeVarFromNameList(names)))
+		PG_RETURN_NULL();
 	clist = OpernameGetCandidates(names, '\0', true);
 
 	if (clist == NULL || clist->next != NULL)
@@ -736,6 +742,8 @@ to_regoperator(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
 				 errmsg("too many arguments"),
 				 errhint("Provide two argument types for operator.")));
+	if (!RangeVarCheckNamespaceAccessNoError(makeRangeVarFromNameList(names)))
+		PG_RETURN_NULL();
 
 	result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
 
@@ -948,16 +956,18 @@ to_regclass(PG_FUNCTION_ARGS)
 {
 	char	   *class_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	Oid			result;
-	List	   *names;
+	RangeVar	*names;
 
 	/*
 	 * Parse the name into components and see if it matches any pg_class
 	 * entries in the current search path.
 	 */
-	names = stringToQualifiedNameList(class_name);
+	names = makeRangeVarFromNameList(stringToQualifiedNameList(class_name));
+	if (!RangeVarCheckNamespaceAccessNoError(names))
+		PG_RETURN_NULL();
 
 	/* We might not even have permissions on this relation; don't lock it. */
-	result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
+	result = RangeVarGetRelid(names, NoLock, true);
 
 	if (OidIsValid(result))
 		PG_RETURN_OID(result);
@@ -1104,10 +1114,14 @@ to_regtype(PG_FUNCTION_ARGS)
 	char	   *typ_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	Oid			result;
 	int32		typmod;
+	List	   *names;
 
 	/*
 	 * Invoke the full parser to deal with special cases such as array syntax.
 	 */
+	names = stringToQualifiedNameList(typ_name);
+	if (!RangeVarCheckNamespaceAccessNoError(makeRangeVarFromNameList(names)))
+		PG_RETURN_NULL();
 	parseTypeString(typ_name, &result, &typmod, true);
 
 	if (OidIsValid(result))
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index 6741834..ff3b065 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -73,6 +73,7 @@ extern Oid RangeVarGetAndCheckCreationNamespace(RangeVar *newRelation,
 									 LOCKMODE lockmode,
 									 Oid *existing_relation_id);
 extern void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid);
+extern bool RangeVarCheckNamespaceAccessNoError(RangeVar *relation);
 extern Oid	RelnameGetRelid(const char *relname);
 extern bool RelationIsVisible(Oid relid);
 
diff --git a/src/test/regress/expected/regproc.out b/src/test/regress/expected/regproc.out
index ee4fcda..ccadae4 100644
--- a/src/test/regress/expected/regproc.out
+++ b/src/test/regress/expected/regproc.out
@@ -395,3 +395,65 @@ SELECT to_regnamespace('"Nonexistent"');
 
 SELECT to_regnamespace('foo.bar');
 ERROR:  invalid name syntax
+/* If objects exist, and user don't have USAGE privilege, return NULL with no error. */
+SELECT current_user AS username
+\gset
+CREATE USER test_usr;
+CREATE SCHEMA test_schema;
+REVOKE ALL ON SCHEMA test_schema FROM test_usr;
+CREATE OPERATOR  test_schema.+ (
+	leftarg = int8,
+	rightarg = int8,
+	procedure = int8pl
+);
+CREATE OR REPLACE FUNCTION test_schema.test_func(int)
+RETURNS INTEGER AS
+	'SELECT 1;'
+LANGUAGE sql;
+CREATE TABLE test_schema.test_tbl(id int);
+CREATE TYPE test_schema.test_type AS (a1 int,a2 int);
+\connect - test_usr
+SELECT to_regoper('test_schema.+');
+ to_regoper 
+------------
+ 
+(1 row)
+
+SELECT to_regoperator('test_schema.+(int8,int8)');
+ to_regoperator 
+----------------
+ 
+(1 row)
+
+SELECT to_regproc('test_schema.test_func');
+ to_regproc 
+------------
+ 
+(1 row)
+
+SELECT to_regprocedure('test_schema.test_func(int)');
+ to_regprocedure 
+-----------------
+ 
+(1 row)
+
+SELECT to_regclass('test_schema.test_tbl');
+ to_regclass 
+-------------
+ 
+(1 row)
+
+SELECT to_regtype('test_schema.test_type');
+ to_regtype 
+------------
+ 
+(1 row)
+
+\connect - :username
+DROP SCHEMA test_schema CASCADE;
+NOTICE:  drop cascades to 4 other objects
+DETAIL:  drop cascades to operator test_schema.+(bigint,bigint)
+drop cascades to function test_schema.test_func(integer)
+drop cascades to table test_schema.test_tbl
+drop cascades to type test_schema.test_type
+DROP ROLE test_usr;
diff --git a/src/test/regress/sql/regproc.sql b/src/test/regress/sql/regproc.sql
index a60bc28..897f181 100644
--- a/src/test/regress/sql/regproc.sql
+++ b/src/test/regress/sql/regproc.sql
@@ -113,3 +113,37 @@ SELECT to_regrole('foo.bar');
 SELECT to_regnamespace('Nonexistent');
 SELECT to_regnamespace('"Nonexistent"');
 SELECT to_regnamespace('foo.bar');
+
+/* If objects exist, and user don't have USAGE privilege, return NULL with no error. */
+
+SELECT current_user AS username
+\gset
+
+CREATE USER test_usr;
+CREATE SCHEMA test_schema;
+REVOKE ALL ON SCHEMA test_schema FROM test_usr;
+
+CREATE OPERATOR  test_schema.+ (
+	leftarg = int8,
+	rightarg = int8,
+	procedure = int8pl
+);
+CREATE OR REPLACE FUNCTION test_schema.test_func(int)
+RETURNS INTEGER AS
+	'SELECT 1;'
+LANGUAGE sql;
+CREATE TABLE test_schema.test_tbl(id int);
+CREATE TYPE test_schema.test_type AS (a1 int,a2 int);
+
+\connect - test_usr
+
+SELECT to_regoper('test_schema.+');
+SELECT to_regoperator('test_schema.+(int8,int8)');
+SELECT to_regproc('test_schema.test_func');
+SELECT to_regprocedure('test_schema.test_func(int)');
+SELECT to_regclass('test_schema.test_tbl');
+SELECT to_regtype('test_schema.test_type');
+
+\connect - :username
+DROP SCHEMA test_schema CASCADE;
+DROP ROLE test_usr;
