diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
new file mode 100644
index 4434dd6..b32f2e4
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -909,7 +909,7 @@ TypeIsVisible(Oid typid)
  */
 FuncCandidateList
 FuncnameGetCandidates(List *names, int nargs, List *argnames,
-					  bool expand_variadic, bool expand_defaults)
+					  bool expand_variadic, bool expand_defaults, bool noError)
 {
 	FuncCandidateList resultList = NULL;
 	bool		any_special = false;
@@ -928,7 +928,9 @@ FuncnameGetCandidates(List *names, int n
 	if (schemaname)
 	{
 		/* use exact schema given */
-		namespaceId = LookupExplicitNamespace(schemaname, false);
+		namespaceId = LookupExplicitNamespace(schemaname, noError);
+		if (!OidIsValid(namespaceId))
+			return NULL;
 	}
 	else
 	{
@@ -1414,7 +1416,7 @@ FunctionIsVisible(Oid funcid)
 		visible = false;
 
 		clist = FuncnameGetCandidates(list_make1(makeString(proname)),
-									  nargs, NIL, false, false);
+									  nargs, NIL, false, false, false);
 
 		for (; clist; clist = clist->next)
 		{
@@ -1446,7 +1448,7 @@ FunctionIsVisible(Oid funcid)
  * namespace search path.
  */
 Oid
-OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
+OpernameGetOprid(List *names, Oid oprleft, Oid oprright, bool noError)
 {
 	char	   *schemaname;
 	char	   *opername;
@@ -1462,18 +1464,21 @@ OpernameGetOprid(List *names, Oid oprlef
 		Oid			namespaceId;
 		HeapTuple	opertup;
 
-		namespaceId = LookupExplicitNamespace(schemaname, false);
-		opertup = SearchSysCache4(OPERNAMENSP,
-								  CStringGetDatum(opername),
-								  ObjectIdGetDatum(oprleft),
-								  ObjectIdGetDatum(oprright),
-								  ObjectIdGetDatum(namespaceId));
-		if (HeapTupleIsValid(opertup))
+		namespaceId = LookupExplicitNamespace(schemaname, noError);
+		if (OidIsValid(namespaceId))
 		{
-			Oid			result = HeapTupleGetOid(opertup);
+			opertup = SearchSysCache4(OPERNAMENSP,
+									  CStringGetDatum(opername),
+									  ObjectIdGetDatum(oprleft),
+									  ObjectIdGetDatum(oprright),
+									  ObjectIdGetDatum(namespaceId));
+			if (HeapTupleIsValid(opertup))
+			{
+				Oid			result = HeapTupleGetOid(opertup);
 
-			ReleaseSysCache(opertup);
-			return result;
+				ReleaseSysCache(opertup);
+				return result;
+			}
 		}
 		return InvalidOid;
 	}
@@ -1734,7 +1739,8 @@ OperatorIsVisible(Oid oprid)
 		char	   *oprname = NameStr(oprform->oprname);
 
 		visible = (OpernameGetOprid(list_make1(makeString(oprname)),
-									oprform->oprleft, oprform->oprright)
+									oprform->oprleft, oprform->oprright,
+											   false)
 				   == oprid);
 	}
 
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
new file mode 100644
index 9011190..6a851fa
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -580,8 +580,8 @@ get_object_address(ObjectType objtype, L
 				{
 					TypeName   *sourcetype = (TypeName *) linitial(objname);
 					TypeName   *targettype = (TypeName *) linitial(objargs);
-					Oid			sourcetypeid = typenameTypeId(NULL, sourcetype);
-					Oid			targettypeid = typenameTypeId(NULL, targettype);
+					Oid	 sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
+					Oid	 targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
 
 					address.classId = CastRelationId;
 					address.objectId =
@@ -942,26 +942,30 @@ get_object_address_relobject(ObjectType
 
 		/* Extract relation name and open relation. */
 		relname = list_truncate(list_copy(objname), nnames - 1);
-		relation = heap_openrv(makeRangeVarFromNameList(relname),
-							   AccessShareLock);
-		reloid = RelationGetRelid(relation);
+		relation = heap_openrv_extended(makeRangeVarFromNameList(relname),
+							   AccessShareLock,
+							   missing_ok);
+
+		reloid = (relation != NULL) ? RelationGetRelid(relation) : InvalidOid;
 
 		switch (objtype)
 		{
 			case OBJECT_RULE:
 				address.classId = RewriteRelationId;
-				address.objectId = get_rewrite_oid(reloid, depname, missing_ok);
+				address.objectId = OidIsValid(reloid) ?
+					get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
 				address.objectSubId = 0;
 				break;
 			case OBJECT_TRIGGER:
 				address.classId = TriggerRelationId;
-				address.objectId = get_trigger_oid(reloid, depname, missing_ok);
+				address.objectId = OidIsValid(reloid) ?
+					get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
 				address.objectSubId = 0;
 				break;
 			case OBJECT_CONSTRAINT:
 				address.classId = ConstraintRelationId;
-				address.objectId =
-					get_relation_constraint_oid(reloid, depname, missing_ok);
+				address.objectId = OidIsValid(reloid) ?
+					get_relation_constraint_oid(reloid, depname, missing_ok) : InvalidOid;
 				address.objectSubId = 0;
 				break;
 			default:
@@ -975,7 +979,9 @@ get_object_address_relobject(ObjectType
 		/* Avoid relcache leak when object not found. */
 		if (!OidIsValid(address.objectId))
 		{
-			heap_close(relation, AccessShareLock);
+			if (relation != NULL)
+				heap_close(relation, AccessShareLock);
+
 			relation = NULL;	/* department of accident prevention */
 			return address;
 		}
@@ -1052,7 +1058,7 @@ get_object_address_type(ObjectType objty
 	address.objectId = InvalidOid;
 	address.objectSubId = 0;
 
-	tup = LookupTypeName(NULL, typename, NULL);
+	tup = LookupTypeName(NULL, typename, NULL, missing_ok);
 	if (!HeapTupleIsValid(tup))
 	{
 		if (!missing_ok)
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
new file mode 100644
index b32ad3a..d7a0f82
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -32,6 +32,15 @@
 static void does_not_exist_skipping(ObjectType objtype,
 						List *objname, List *objargs);
 
+static bool parent_does_not_exist_skipping(List *objname,
+							   const char **msg,
+							   char **name);
+
+static bool schema_does_not_exist_skipping(List *objname,
+							   const char **msg,
+							   char **name);
+
+
 /*
  * Drop one or more objects.
  *
@@ -125,6 +134,63 @@ RemoveObjects(DropStmt *stmt)
 }
 
 /*
+ * For triggers and rules, test if the parent relation exists.  If it does not,
+ * report it as missing rather than reporting the trigger or rule as missing.
+ * This is used for DROP RULE/TRIGGER IF EXISTS.
+ */
+static bool
+parent_does_not_exist_skipping(List *objname,
+							   const char **msg,
+							   char **name)
+{
+	List	   *parent_objname;
+	RangeVar   *parent_rel;
+
+	parent_objname = list_truncate(list_copy(objname),
+								   list_length(objname) - 1);
+
+	if (schema_does_not_exist_skipping(parent_objname, msg, name))
+		return true;
+
+	parent_rel = makeRangeVarFromNameList(parent_objname);
+
+	if (!OidIsValid(RangeVarGetRelid(parent_rel, NoLock, true)))
+	{
+		*msg = gettext_noop("relation \"%s\" does not exist, skipping");
+		*name = NameListToString(parent_objname);
+
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * If a schema was explicitly specified, test if it exists.  If it does not,
+ * report the schema as missing rather than the child object.
+ */
+static bool
+schema_does_not_exist_skipping(List *objname,
+							   const char **msg,
+							   char **name)
+{
+	RangeVar	*rel;
+
+	rel = makeRangeVarFromNameList(objname);
+
+	if (rel->schemaname != NULL &&
+		!OidIsValid(LookupNamespaceNoError(rel->schemaname)))
+	{
+		*msg = gettext_noop("schema \"%s\" does not exist, skipping");
+		*name = rel->schemaname;
+
+		return true;
+	}
+
+	return false;
+}
+
+/*
  * Generate a NOTICE stating that the named object was not found, and is
  * being skipped.  This is only relevant when "IF EXISTS" is used; otherwise,
  * get_object_address() will throw an ERROR.
@@ -140,81 +206,126 @@ does_not_exist_skipping(ObjectType objty
 	{
 		case OBJECT_TYPE:
 		case OBJECT_DOMAIN:
-			msg = gettext_noop("type \"%s\" does not exist, skipping");
-			name = TypeNameToString(makeTypeNameFromNameList(objname));
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("type \"%s\" does not exist, skipping");
+				name = TypeNameToString(makeTypeNameFromNameList(objname));
+			}
 			break;
 		case OBJECT_COLLATION:
-			msg = gettext_noop("collation \"%s\" does not exist, skipping");
-			name = NameListToString(objname);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("collation \"%s\" does not exist, skipping");
+				name = NameListToString(objname);
+			}
 			break;
 		case OBJECT_CONVERSION:
-			msg = gettext_noop("conversion \"%s\" does not exist, skipping");
-			name = NameListToString(objname);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("conversion \"%s\" does not exist, skipping");
+				name = NameListToString(objname);
+			}
 			break;
 		case OBJECT_SCHEMA:
 			msg = gettext_noop("schema \"%s\" does not exist, skipping");
 			name = NameListToString(objname);
 			break;
 		case OBJECT_TSPARSER:
-			msg = gettext_noop("text search parser \"%s\" does not exist, skipping");
-			name = NameListToString(objname);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("text search parser \"%s\" does not exist, skipping");
+				name = NameListToString(objname);
+			}
 			break;
 		case OBJECT_TSDICTIONARY:
-			msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping");
-			name = NameListToString(objname);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping");
+				name = NameListToString(objname);
+			}
 			break;
 		case OBJECT_TSTEMPLATE:
-			msg = gettext_noop("text search template \"%s\" does not exist, skipping");
-			name = NameListToString(objname);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("text search template \"%s\" does not exist, skipping");
+				name = NameListToString(objname);
+			}
 			break;
 		case OBJECT_TSCONFIGURATION:
-			msg = gettext_noop("text search configuration \"%s\" does not exist, skipping");
-			name = NameListToString(objname);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("text search configuration \"%s\" does not exist, skipping");
+				name = NameListToString(objname);
+			}
 			break;
 		case OBJECT_EXTENSION:
 			msg = gettext_noop("extension \"%s\" does not exist, skipping");
 			name = NameListToString(objname);
 			break;
 		case OBJECT_FUNCTION:
-			msg = gettext_noop("function %s(%s) does not exist, skipping");
-			name = NameListToString(objname);
-			args = TypeNameListToString(objargs);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("function %s(%s) does not exist, skipping");
+				name = NameListToString(objname);
+				args = TypeNameListToString(objargs);
+			}
 			break;
 		case OBJECT_AGGREGATE:
-			msg = gettext_noop("aggregate %s(%s) does not exist, skipping");
-			name = NameListToString(objname);
-			args = TypeNameListToString(objargs);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("aggregate %s(%s) does not exist, skipping");
+				name = NameListToString(objname);
+				args = TypeNameListToString(objargs);
+			}
 			break;
 		case OBJECT_OPERATOR:
-			msg = gettext_noop("operator %s does not exist, skipping");
-			name = NameListToString(objname);
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("operator %s does not exist, skipping");
+				name = NameListToString(objname);
+			}
 			break;
 		case OBJECT_LANGUAGE:
 			msg = gettext_noop("language \"%s\" does not exist, skipping");
 			name = NameListToString(objname);
 			break;
 		case OBJECT_CAST:
-			msg = gettext_noop("cast from type %s to type %s does not exist, skipping");
-			name = format_type_be(typenameTypeId(NULL,
-											(TypeName *) linitial(objname)));
-			args = format_type_be(typenameTypeId(NULL,
-											(TypeName *) linitial(objargs)));
+			{
+				TypeName *tobjname = (TypeName *) linitial(objname);
+				TypeName *targname = (TypeName *) linitial(objargs);
+
+				if (!schema_does_not_exist_skipping(tobjname->names,
+													&msg, &name) &&
+					!schema_does_not_exist_skipping(targname->names,
+													&msg, &name))
+				{
+					msg = gettext_noop("cast from type %s to type %s does not exist, skipping");
+					name = TypeNameToString(tobjname);
+					args = TypeNameToString(targname);
+				}
+			}
 			break;
 		case OBJECT_TRIGGER:
-			msg = gettext_noop("trigger \"%s\" for table \"%s\" does not exist, skipping");
-			name = strVal(llast(objname));
-			args = NameListToString(list_truncate(list_copy(objname),
-												  list_length(objname) - 1));
+			if (!parent_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("trigger \"%s\" for relation \"%s\" does not exist, skipping");
+				name = strVal(llast(objname));
+				args = NameListToString(list_truncate(list_copy(objname),
+													  list_length(objname) - 1));
+			}
 			break;
 		case OBJECT_EVENT_TRIGGER:
 			msg = gettext_noop("event trigger \"%s\" does not exist, skipping");
 			name = NameListToString(objname);
 			break;
 		case OBJECT_RULE:
-			msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping");
-			name = strVal(llast(objname));
-			args = NameListToString(list_truncate(list_copy(objname),
-												  list_length(objname) - 1));
+			if (!parent_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping");
+				name = strVal(llast(objname));
+				args = NameListToString(list_truncate(list_copy(objname),
+													  list_length(objname) - 1));
+			}
 			break;
 		case OBJECT_FDW:
 			msg = gettext_noop("foreign-data wrapper \"%s\" does not exist, skipping");
@@ -225,14 +336,20 @@ does_not_exist_skipping(ObjectType objty
 			name = NameListToString(objname);
 			break;
 		case OBJECT_OPCLASS:
-			msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping");
-			name = NameListToString(objname);
-			args = strVal(linitial(objargs));
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping");
+				name = NameListToString(objname);
+				args = strVal(linitial(objargs));
+			}
 			break;
 		case OBJECT_OPFAMILY:
-			msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping");
-			name = NameListToString(objname);
-			args = strVal(linitial(objargs));
+			if (!schema_does_not_exist_skipping(objname, &msg, &name))
+			{
+				msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping");
+				name = NameListToString(objname);
+				args = strVal(linitial(objargs));
+			}
 			break;
 		default:
 			elog(ERROR, "unexpected object type (%d)", (int) objtype);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
new file mode 100644
index ca754b4..348b901
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -86,7 +86,7 @@ compute_return_type(TypeName *returnType
 	Type		typtup;
 	AclResult	aclresult;
 
-	typtup = LookupTypeName(NULL, returnType, NULL);
+	typtup = LookupTypeName(NULL, returnType, NULL, false);
 
 	if (typtup)
 	{
@@ -220,7 +220,7 @@ interpret_function_parameter_list(List *
 		Type		typtup;
 		AclResult	aclresult;
 
-		typtup = LookupTypeName(NULL, t, NULL);
+		typtup = LookupTypeName(NULL, t, NULL, false);
 		if (typtup)
 		{
 			if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
new file mode 100644
index 3140b37..576f7b1
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -103,11 +103,14 @@ OpFamilyCacheLookup(Oid amID, List *opfa
 		/* Look in specific schema only */
 		Oid			namespaceId;
 
-		namespaceId = LookupExplicitNamespace(schemaname, false);
-		htup = SearchSysCache3(OPFAMILYAMNAMENSP,
-							   ObjectIdGetDatum(amID),
-							   PointerGetDatum(opfname),
-							   ObjectIdGetDatum(namespaceId));
+		namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+		if (!OidIsValid(namespaceId))
+			htup = NULL;
+		else
+			htup = SearchSysCache3(OPFAMILYAMNAMENSP,
+								   ObjectIdGetDatum(amID),
+								   PointerGetDatum(opfname),
+								   ObjectIdGetDatum(namespaceId));
 	}
 	else
 	{
@@ -179,11 +182,14 @@ OpClassCacheLookup(Oid amID, List *opcla
 		/* Look in specific schema only */
 		Oid			namespaceId;
 
-		namespaceId = LookupExplicitNamespace(schemaname, false);
-		htup = SearchSysCache3(CLAAMNAMENSP,
-							   ObjectIdGetDatum(amID),
-							   PointerGetDatum(opcname),
-							   ObjectIdGetDatum(namespaceId));
+		namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+		if (!OidIsValid(namespaceId))
+			htup = NULL;
+		else
+			htup = SearchSysCache3(CLAAMNAMENSP,
+								   ObjectIdGetDatum(amID),
+								   PointerGetDatum(opcname),
+								   ObjectIdGetDatum(namespaceId));
 	}
 	else
 	{
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
new file mode 100644
index 1aa1ad9..f2789d0
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -690,10 +690,28 @@ DefineRelation(CreateStmt *stmt, char re
  * non-existent relation
  */
 static void
-DropErrorMsgNonExistent(const char *relname, char rightkind, bool missing_ok)
+DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
 {
 	const struct dropmsgstrings *rentry;
 
+	if (rel->schemaname != NULL &&
+		!OidIsValid(LookupNamespaceNoError(rel->schemaname)))
+	{
+		if (!missing_ok)
+		{
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_SCHEMA),
+					 errmsg("schema \"%s\" does not exist", rel->schemaname)));
+		}
+		else
+		{
+			ereport(NOTICE,
+					(errmsg("schema \"%s\" does not exist, skipping",
+							rel->schemaname)));
+		}
+		return;
+	}
+
 	for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
 	{
 		if (rentry->kind == rightkind)
@@ -702,11 +720,11 @@ DropErrorMsgNonExistent(const char *reln
 			{
 				ereport(ERROR,
 						(errcode(rentry->nonexistent_code),
-						 errmsg(rentry->nonexistent_msg, relname)));
+						 errmsg(rentry->nonexistent_msg, rel->relname)));
 			}
 			else
 			{
-				ereport(NOTICE, (errmsg(rentry->skipping_msg, relname)));
+				ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
 				break;
 			}
 		}
@@ -845,7 +863,7 @@ RemoveRelations(DropStmt *drop)
 		/* Not there? */
 		if (!OidIsValid(relOid))
 		{
-			DropErrorMsgNonExistent(rel->relname, relkind, drop->missing_ok);
+			DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
 			continue;
 		}
 
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
new file mode 100644
index d4a14ca..4805f2b
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -3245,7 +3245,7 @@ AlterTypeOwner(List *names, Oid newOwner
 	typename = makeTypeNameFromNameList(names);
 
 	/* Use LookupTypeName here so that shell types can be processed */
-	tup = LookupTypeName(NULL, typename, NULL);
+	tup = LookupTypeName(NULL, typename, NULL, false);
 	if (tup == NULL)
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
new file mode 100644
index ede36d1..f560b48
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -1062,7 +1062,8 @@ func_get_detail(List *funcname,
 
 	/* Get list of possible candidates from namespace search */
 	raw_candidates = FuncnameGetCandidates(funcname, nargs, fargnames,
-										   expand_variadic, expand_defaults);
+										   expand_variadic, expand_defaults,
+													   false);
 
 	/*
 	 * Quickly check if there is an exact match to the input datatypes (there
@@ -1422,7 +1423,7 @@ FuncNameAsType(List *funcname)
 	Oid			result;
 	Type		typtup;
 
-	typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL);
+	typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL, false);
 	if (typtup == NULL)
 		return InvalidOid;
 
@@ -1581,7 +1582,7 @@ LookupFuncName(List *funcname, int nargs
 {
 	FuncCandidateList clist;
 
-	clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false);
+	clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false, noError);
 
 	while (clist)
 	{
@@ -1601,27 +1602,6 @@ LookupFuncName(List *funcname, int nargs
 }
 
 /*
- * LookupTypeNameOid
- *		Convenience routine to look up a type, silently accepting shell types
- */
-static Oid
-LookupTypeNameOid(const TypeName *typename)
-{
-	Oid			result;
-	Type		typtup;
-
-	typtup = LookupTypeName(NULL, typename, NULL);
-	if (typtup == NULL)
-		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("type \"%s\" does not exist",
-						TypeNameToString(typename))));
-	result = typeTypeId(typtup);
-	ReleaseSysCache(typtup);
-	return result;
-}
-
-/*
  * LookupFuncNameTypeNames
  *		Like LookupFuncName, but the argument types are specified by a
  *		list of TypeName nodes.
@@ -1648,7 +1628,7 @@ LookupFuncNameTypeNames(List *funcname,
 	{
 		TypeName   *t = (TypeName *) lfirst(args_item);
 
-		argoids[i] = LookupTypeNameOid(t);
+		argoids[i] = LookupTypeNameOid(NULL, t, noError);
 		args_item = lnext(args_item);
 	}
 
@@ -1688,7 +1668,7 @@ LookupAggNameTypeNames(List *aggname, Li
 	{
 		TypeName   *t = (TypeName *) lfirst(lc);
 
-		argoids[i] = LookupTypeNameOid(t);
+		argoids[i] = LookupTypeNameOid(NULL, t, noError);
 		i++;
 	}
 
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
new file mode 100644
index dd80fa9..9595f10
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -103,7 +103,7 @@ LookupOperName(ParseState *pstate, List
 {
 	Oid			result;
 
-	result = OpernameGetOprid(opername, oprleft, oprright);
+	result = OpernameGetOprid(opername, oprleft, oprright, noError);
 	if (OidIsValid(result))
 		return result;
 
@@ -148,12 +148,12 @@ LookupOperNameTypeNames(ParseState *psta
 	if (oprleft == NULL)
 		leftoid = InvalidOid;
 	else
-		leftoid = typenameTypeId(pstate, oprleft);
+		leftoid = LookupTypeNameOid(pstate, oprleft, noError);
 
 	if (oprright == NULL)
 		rightoid = InvalidOid;
 	else
-		rightoid = typenameTypeId(pstate, oprright);
+		rightoid = LookupTypeNameOid(pstate, oprright, noError);
 
 	return LookupOperName(pstate, opername, leftoid, rightoid,
 						  noError, location);
@@ -280,7 +280,7 @@ binary_oper_exact(List *opname, Oid arg1
 		was_unknown = true;
 	}
 
-	result = OpernameGetOprid(opname, arg1, arg2);
+	result = OpernameGetOprid(opname, arg1, arg2, false);
 	if (OidIsValid(result))
 		return result;
 
@@ -291,7 +291,7 @@ binary_oper_exact(List *opname, Oid arg1
 
 		if (basetype != arg1)
 		{
-			result = OpernameGetOprid(opname, basetype, basetype);
+			result = OpernameGetOprid(opname, basetype, basetype, false);
 			if (OidIsValid(result))
 				return result;
 		}
@@ -544,7 +544,7 @@ right_oper(ParseState *pstate, List *op,
 	/*
 	 * First try for an "exact" match.
 	 */
-	operOid = OpernameGetOprid(op, arg, InvalidOid);
+	operOid = OpernameGetOprid(op, arg, InvalidOid, noError);
 	if (!OidIsValid(operOid))
 	{
 		/*
@@ -622,7 +622,7 @@ left_oper(ParseState *pstate, List *op,
 	/*
 	 * First try for an "exact" match.
 	 */
-	operOid = OpernameGetOprid(op, InvalidOid, arg);
+	operOid = OpernameGetOprid(op, InvalidOid, arg, noError);
 	if (!OidIsValid(operOid))
 	{
 		/*
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
new file mode 100644
index ee6802a..c72fc8d
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -56,7 +56,8 @@ static int32 typenameTypeMod(ParseState
  */
 Type
 LookupTypeName(ParseState *pstate, const TypeName *typeName,
-			   int32 *typmod_p)
+			   int32 *typmod_p,
+					bool missing_ok)
 {
 	Oid			typoid;
 	HeapTuple	tup;
@@ -116,15 +117,21 @@ LookupTypeName(ParseState *pstate, const
 		 * concurrent DDL.	But taking a lock would carry a performance
 		 * penalty and would also require a permissions check.
 		 */
-		relid = RangeVarGetRelid(rel, NoLock, false);
-		attnum = get_attnum(relid, field);
-		if (attnum == InvalidAttrNumber)
-			ereport(ERROR,
-					(errcode(ERRCODE_UNDEFINED_COLUMN),
-					 errmsg("column \"%s\" of relation \"%s\" does not exist",
-							field, rel->relname),
-					 parser_errposition(pstate, typeName->location)));
-		typoid = get_atttype(relid, attnum);
+		typoid = InvalidOid;
+		relid = RangeVarGetRelid(rel, NoLock, missing_ok);
+
+		if (OidIsValid(relid))
+		{
+			attnum = get_attnum(relid, field);
+			if (attnum != InvalidAttrNumber)
+				typoid = get_atttype(relid, attnum);
+			else if (!missing_ok)
+				ereport(ERROR,
+						(errcode(ERRCODE_UNDEFINED_COLUMN),
+						 errmsg("column \"%s\" of relation \"%s\" does not exist",
+								field, rel->relname),
+						 parser_errposition(pstate, typeName->location)));
+		}
 
 		/* this construct should never have an array indicator */
 		Assert(typeName->arrayBounds == NIL);
@@ -149,10 +156,13 @@ LookupTypeName(ParseState *pstate, const
 			/* Look in specific schema only */
 			Oid			namespaceId;
 
-			namespaceId = LookupExplicitNamespace(schemaname, false);
-			typoid = GetSysCacheOid2(TYPENAMENSP,
+			namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+			if (OidIsValid(namespaceId))
+				typoid = GetSysCacheOid2(TYPENAMENSP,
 									 PointerGetDatum(typname),
 									 ObjectIdGetDatum(namespaceId));
+			else
+				typoid = InvalidOid;
 		}
 		else
 		{
@@ -196,7 +206,7 @@ typenameType(ParseState *pstate, const T
 {
 	Type		tup;
 
-	tup = LookupTypeName(pstate, typeName, typmod_p);
+	tup = LookupTypeName(pstate, typeName, typmod_p, false);
 	if (tup == NULL)
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -228,6 +238,35 @@ typenameTypeId(ParseState *pstate, const
 	typoid = HeapTupleGetOid(tup);
 	ReleaseSysCache(tup);
 
+	return typoid;
+}
+
+/*
+ * returns oid of type
+ *		Convenience routine to look up a type, silently accepting shell types
+ */
+Oid
+LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
+{
+	Oid			typoid;
+	Type		tup;
+
+	tup = LookupTypeName(pstate, typeName, NULL, missing_ok);
+	if (tup == NULL)
+	{
+		if (!missing_ok)
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("type \"%s\" does not exist",
+							TypeNameToString(typeName)),
+					 parser_errposition(pstate, typeName->location)));
+
+		return InvalidOid;
+	}
+
+	typoid = HeapTupleGetOid(tup);
+	ReleaseSysCache(tup);
+
 	return typoid;
 }
 
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
new file mode 100644
index c24a2c1..28c1e7f
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -135,7 +135,7 @@ regprocin(PG_FUNCTION_ARGS)
 	 * pg_proc entries in the current search path.
 	 */
 	names = stringToQualifiedNameList(pro_name_or_oid);
-	clist = FuncnameGetCandidates(names, -1, NIL, false, false);
+	clist = FuncnameGetCandidates(names, -1, NIL, false, false, false);
 
 	if (clist == NULL)
 		ereport(ERROR,
@@ -192,7 +192,7 @@ regprocout(PG_FUNCTION_ARGS)
 			 * qualify it.
 			 */
 			clist = FuncnameGetCandidates(list_make1(makeString(proname)),
-										  -1, NIL, false, false);
+										  -1, NIL, false, false, false);
 			if (clist != NULL && clist->next == NULL &&
 				clist->oid == proid)
 				nspname = NULL;
@@ -279,7 +279,7 @@ regprocedurein(PG_FUNCTION_ARGS)
 	 */
 	parseNameAndArgTypes(pro_name_or_oid, false, &names, &nargs, argtypes);
 
-	clist = FuncnameGetCandidates(names, nargs, NIL, false, false);
+	clist = FuncnameGetCandidates(names, nargs, NIL, false, false, false);
 
 	for (; clist; clist = clist->next)
 	{
@@ -661,7 +661,7 @@ regoperatorin(PG_FUNCTION_ARGS)
 				 errmsg("too many arguments"),
 				 errhint("Provide two argument types for operator.")));
 
-	result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
+	result = OpernameGetOprid(names, argtypes[0], argtypes[1], false);
 
 	if (!OidIsValid(result))
 		ereport(ERROR,
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
new file mode 100644
index 4fadc74..05c035b
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -71,10 +71,11 @@ extern bool TypeIsVisible(Oid typid);
 extern FuncCandidateList FuncnameGetCandidates(List *names,
 					  int nargs, List *argnames,
 					  bool expand_variadic,
-					  bool expand_defaults);
+					  bool expand_defaults,
+					  bool noError);
 extern bool FunctionIsVisible(Oid funcid);
 
-extern Oid	OpernameGetOprid(List *names, Oid oprleft, Oid oprright);
+extern Oid	OpernameGetOprid(List *names, Oid oprleft, Oid oprright, bool noError);
 extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind);
 extern bool OperatorIsVisible(Oid oprid);
 
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
new file mode 100644
index 340121a..51da025
--- a/src/include/parser/parse_type.h
+++ b/src/include/parser/parse_type.h
@@ -20,7 +20,9 @@
 typedef HeapTuple Type;
 
 extern Type LookupTypeName(ParseState *pstate, const TypeName *typeName,
-			   int32 *typmod_p);
+			   int32 *typmod_p, bool missing_ok);
+extern Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName,
+				 bool missing_ok);
 extern Type typenameType(ParseState *pstate, const TypeName *typeName,
 			 int32 *typmod_p);
 extern Oid	typenameTypeId(ParseState *pstate, const TypeName *typeName);
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
new file mode 100644
index 426aeb5..692bba4
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -1665,7 +1665,7 @@ plpgsql_parse_wordtype(char *ident)
 	 * Word wasn't found in the namespace stack. Try to find a data type with
 	 * that name, but ignore shell types and complex types.
 	 */
-	typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL);
+	typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL, false);
 	if (typeTup)
 	{
 		Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
diff --git a/src/test/regress/expected/drop_if_exists.out b/src/test/regress/expected/drop_if_exists.out
new file mode 100644
index 8599401..66dcb00
--- a/src/test/regress/expected/drop_if_exists.out
+++ b/src/test/regress/expected/drop_if_exists.out
@@ -169,11 +169,15 @@ NOTICE:  cast from type text to type tex
 DROP TRIGGER test_trigger_exists ON test_exists;
 ERROR:  trigger "test_trigger_exists" for table "test_exists" does not exist
 DROP TRIGGER IF EXISTS test_trigger_exists ON test_exists;
-NOTICE:  trigger "test_trigger_exists" for table "test_exists" does not exist, skipping
+NOTICE:  trigger "test_trigger_exists" for relation "test_exists" does not exist, skipping
 DROP TRIGGER test_trigger_exists ON no_such_table;
 ERROR:  relation "no_such_table" does not exist
 DROP TRIGGER IF EXISTS test_trigger_exists ON no_such_table;
-ERROR:  relation "no_such_table" does not exist
+NOTICE:  relation "no_such_table" does not exist, skipping
+DROP TRIGGER test_trigger_exists ON no_such_schema.no_such_table;
+ERROR:  schema "no_such_schema" does not exist
+DROP TRIGGER IF EXISTS test_trigger_exists ON no_such_schema.no_such_table;
+NOTICE:  schema "no_such_schema" does not exist, skipping
 CREATE TRIGGER test_trigger_exists
     BEFORE UPDATE ON test_exists
     FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
@@ -186,7 +190,11 @@ NOTICE:  rule "test_rule_exists" for rel
 DROP RULE test_rule_exists ON no_such_table;
 ERROR:  relation "no_such_table" does not exist
 DROP RULE IF EXISTS test_rule_exists ON no_such_table;
-ERROR:  relation "no_such_table" does not exist
+NOTICE:  relation "no_such_table" does not exist, skipping
+DROP RULE test_rule_exists ON no_such_schema.no_such_table;
+ERROR:  schema "no_such_schema" does not exist
+DROP RULE IF EXISTS test_rule_exists ON no_such_schema.no_such_table;
+NOTICE:  schema "no_such_schema" does not exist, skipping
 CREATE RULE test_rule_exists AS ON INSERT TO test_exists
     DO INSTEAD
     INSERT INTO test_exists VALUES (NEW.a, NEW.b || NEW.a::text);
@@ -223,3 +231,48 @@ ERROR:  access method "no_such_am" does
 DROP TABLE IF EXISTS test_exists;
 DROP TABLE test_exists;
 ERROR:  table "test_exists" does not exist
+-- be toleralnt with not existing schema
+DROP AGGREGATE IF EXISTS no_such_schema.foo(int);
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP CAST IF EXISTS (no_such_schema.foo AS no_such_schema.bar);
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP COLLATION IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP CONVERSION IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP DOMAIN IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP FOREIGN TABLE IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP FUNCTION IF EXISTS no_such_schema.foo();
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP INDEX IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP MATERIALIZED VIEW IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP OPERATOR IF EXISTS no_such_schema.+ (int, int);
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP OPERATOR CLASS IF EXISTS no_such_schema.widget_ops USING btree;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP OPERATOR FAMILY IF EXISTS no_such_schema.float_ops USING btree;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP RULE IF EXISTS foo ON no_such_schema.bar;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP SEQUENCE IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP TABLE IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP TEXT SEARCH CONFIGURATION IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP TEXT SEARCH DICTIONARY IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP TEXT SEARCH PARSER IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP TEXT SEARCH TEMPLATE IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP TRIGGER IF EXISTS foo ON no_such_schema.bar;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP TYPE IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
+DROP VIEW IF EXISTS no_such_schema.foo;
+NOTICE:  schema "no_such_schema" does not exist, skipping
diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out
new file mode 100644
index 656d47f..d4723b2
--- a/src/test/regress/expected/event_trigger.out
+++ b/src/test/regress/expected/event_trigger.out
@@ -280,7 +280,7 @@ SELECT * FROM dropped_objects WHERE sche
 (23 rows)
 
 DROP OWNED BY regression_bob;
-NOTICE:  table "audit_tbls_schema_one_table_two" does not exist, skipping
+NOTICE:  schema "audit_tbls" does not exist, skipping
 CONTEXT:  SQL statement "DROP TABLE IF EXISTS audit_tbls.audit_tbls_schema_one_table_two"
 PL/pgSQL function test_evtrig_dropped_objects() line 8 at EXECUTE statement
 SELECT * FROM dropped_objects WHERE type = 'schema';
diff --git a/src/test/regress/sql/drop_if_exists.sql b/src/test/regress/sql/drop_if_exists.sql
new file mode 100644
index 6330566..a2f265d
--- a/src/test/regress/sql/drop_if_exists.sql
+++ b/src/test/regress/sql/drop_if_exists.sql
@@ -182,6 +182,9 @@ DROP TRIGGER IF EXISTS test_trigger_exis
 DROP TRIGGER test_trigger_exists ON no_such_table;
 DROP TRIGGER IF EXISTS test_trigger_exists ON no_such_table;
 
+DROP TRIGGER test_trigger_exists ON no_such_schema.no_such_table;
+DROP TRIGGER IF EXISTS test_trigger_exists ON no_such_schema.no_such_table;
+
 CREATE TRIGGER test_trigger_exists
     BEFORE UPDATE ON test_exists
     FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
@@ -194,6 +197,9 @@ DROP RULE IF EXISTS test_rule_exists ON
 DROP RULE test_rule_exists ON no_such_table;
 DROP RULE IF EXISTS test_rule_exists ON no_such_table;
 
+DROP RULE test_rule_exists ON no_such_schema.no_such_table;
+DROP RULE IF EXISTS test_rule_exists ON no_such_schema.no_such_table;
+
 CREATE RULE test_rule_exists AS ON INSERT TO test_exists
     DO INSTEAD
     INSERT INTO test_exists VALUES (NEW.a, NEW.b || NEW.a::text);
@@ -226,3 +232,28 @@ DROP OPERATOR FAMILY IF EXISTS test_oper
 DROP TABLE IF EXISTS test_exists;
 
 DROP TABLE test_exists;
+
+-- be toleralnt with not existing schema
+
+DROP AGGREGATE IF EXISTS no_such_schema.foo(int);
+DROP CAST IF EXISTS (no_such_schema.foo AS no_such_schema.bar);
+DROP COLLATION IF EXISTS no_such_schema.foo;
+DROP CONVERSION IF EXISTS no_such_schema.foo;
+DROP DOMAIN IF EXISTS no_such_schema.foo;
+DROP FOREIGN TABLE IF EXISTS no_such_schema.foo;
+DROP FUNCTION IF EXISTS no_such_schema.foo();
+DROP INDEX IF EXISTS no_such_schema.foo;
+DROP MATERIALIZED VIEW IF EXISTS no_such_schema.foo;
+DROP OPERATOR IF EXISTS no_such_schema.+ (int, int);
+DROP OPERATOR CLASS IF EXISTS no_such_schema.widget_ops USING btree;
+DROP OPERATOR FAMILY IF EXISTS no_such_schema.float_ops USING btree;
+DROP RULE IF EXISTS foo ON no_such_schema.bar;
+DROP SEQUENCE IF EXISTS no_such_schema.foo;
+DROP TABLE IF EXISTS no_such_schema.foo;
+DROP TEXT SEARCH CONFIGURATION IF EXISTS no_such_schema.foo;
+DROP TEXT SEARCH DICTIONARY IF EXISTS no_such_schema.foo;
+DROP TEXT SEARCH PARSER IF EXISTS no_such_schema.foo;
+DROP TEXT SEARCH TEMPLATE IF EXISTS no_such_schema.foo;
+DROP TRIGGER IF EXISTS foo ON no_such_schema.bar;
+DROP TYPE IF EXISTS no_such_schema.foo;
+DROP VIEW IF EXISTS no_such_schema.foo;
