mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Make DROP IF EXISTS more consistently not fail
Some cases were still reporting errors and aborting, instead of a NOTICE that the object was being skipped. This makes it more difficult to cleanly handle pg_dump --clean, so change that to instead skip missing objects properly. Per bug #7873 reported by Dave Rolsky; apparently this affects a large number of users. Authors: Pavel Stehule and Dean Rasheed. Some tweaks by Álvaro Herrera
This commit is contained in:
		
							parent
							
								
									9f80f4835a
								
							
						
					
					
						commit
						b152c6cd0d
					
				| @ -906,10 +906,15 @@ TypeIsVisible(Oid typid) | ||||
|  * with oid = 0 that represents a set of such conflicting candidates. | ||||
|  * The caller might end up discarding such an entry anyway, but if it selects | ||||
|  * such an entry it should react as though the call were ambiguous. | ||||
|  * | ||||
|  * If missing_ok is true, an empty list (NULL) is returned if the name was | ||||
|  * schema- qualified with a schema that does not exist.  Likewise if no | ||||
|  * candidate is found for other reasons. | ||||
|  */ | ||||
| FuncCandidateList | ||||
| FuncnameGetCandidates(List *names, int nargs, List *argnames, | ||||
| 					  bool expand_variadic, bool expand_defaults) | ||||
| 					  bool expand_variadic, bool expand_defaults, | ||||
| 					  bool missing_ok) | ||||
| { | ||||
| 	FuncCandidateList resultList = NULL; | ||||
| 	bool		any_special = false; | ||||
| @ -928,7 +933,9 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames, | ||||
| 	if (schemaname) | ||||
| 	{ | ||||
| 		/* use exact schema given */ | ||||
| 		namespaceId = LookupExplicitNamespace(schemaname, false); | ||||
| 		namespaceId = LookupExplicitNamespace(schemaname, missing_ok); | ||||
| 		if (!OidIsValid(namespaceId)) | ||||
| 			return NULL; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @ -1414,7 +1421,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) | ||||
| 		{ | ||||
| @ -1443,7 +1450,8 @@ FunctionIsVisible(Oid funcid) | ||||
|  * a postfix op. | ||||
|  * | ||||
|  * If the operator name is not schema-qualified, it is sought in the current | ||||
|  * namespace search path. | ||||
|  * namespace search path.  If the name is schema-qualified and the given | ||||
|  * schema does not exist, InvalidOid is returned. | ||||
|  */ | ||||
| Oid | ||||
| OpernameGetOprid(List *names, Oid oprleft, Oid oprright) | ||||
| @ -1460,21 +1468,26 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright) | ||||
| 	{ | ||||
| 		/* search only in exact schema given */ | ||||
| 		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, true); | ||||
| 		if (OidIsValid(namespaceId)) | ||||
| 		{ | ||||
| 			Oid			result = HeapTupleGetOid(opertup); | ||||
| 			HeapTuple	opertup; | ||||
| 
 | ||||
| 			ReleaseSysCache(opertup); | ||||
| 			return result; | ||||
| 			opertup = SearchSysCache4(OPERNAMENSP, | ||||
| 									  CStringGetDatum(opername), | ||||
| 									  ObjectIdGetDatum(oprleft), | ||||
| 									  ObjectIdGetDatum(oprright), | ||||
| 									  ObjectIdGetDatum(namespaceId)); | ||||
| 			if (HeapTupleIsValid(opertup)) | ||||
| 			{ | ||||
| 				Oid			result = HeapTupleGetOid(opertup); | ||||
| 
 | ||||
| 				ReleaseSysCache(opertup); | ||||
| 				return result; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return InvalidOid; | ||||
| 	} | ||||
| 
 | ||||
| @ -1729,7 +1742,7 @@ OperatorIsVisible(Oid oprid) | ||||
| 		 * If it is in the path, it might still not be visible; it could be | ||||
| 		 * hidden by another operator of the same name and arguments earlier | ||||
| 		 * in the path.  So we must do a slow check to see if this is the same | ||||
| 		 * operator that would be found by OpernameGetOprId. | ||||
| 		 * operator that would be found by OpernameGetOprid. | ||||
| 		 */ | ||||
| 		char	   *oprname = NameStr(oprform->oprname); | ||||
| 
 | ||||
|  | ||||
| @ -450,7 +450,7 @@ static void getRelationIdentity(StringInfo buffer, Oid relid); | ||||
|  * sub-object is looked up, the parent object will be locked instead. | ||||
|  * | ||||
|  * If the object is a relation or a child object of a relation (e.g. an | ||||
|  * attribute or contraint), the relation is also opened and *relp receives | ||||
|  * attribute or constraint), the relation is also opened and *relp receives | ||||
|  * the open relcache entry pointer; otherwise, *relp is set to NULL.  This | ||||
|  * is a bit grotty but it makes life simpler, since the caller will | ||||
|  * typically need the relcache entry too.  Caller must close the relcache | ||||
| @ -458,9 +458,20 @@ static void getRelationIdentity(StringInfo buffer, Oid relid); | ||||
|  * if the target object is the relation itself or an attribute, but for other | ||||
|  * child objects, only AccessShareLock is acquired on the relation. | ||||
|  * | ||||
|  * If the object is not found, an error is thrown, unless missing_ok is | ||||
|  * true.  In this case, no lock is acquired, relp is set to NULL, and the | ||||
|  * returned address has objectId set to InvalidOid. | ||||
|  * | ||||
|  * We don't currently provide a function to release the locks acquired here; | ||||
|  * typically, the lock must be held until commit to guard against a concurrent | ||||
|  * drop operation. | ||||
|  * | ||||
|  * Note: If the object is not found, we don't give any indication of the | ||||
|  * reason.	(It might have been a missing schema if the name was qualified, or | ||||
|  * an inexistant type name in case of a cast, function or operator; etc). | ||||
|  * Currently there is only one caller that might be interested in such info, so | ||||
|  * we don't spend much effort here.  If more callers start to care, it might be | ||||
|  * better to add some support for that in this function. | ||||
|  */ | ||||
| ObjectAddress | ||||
| get_object_address(ObjectType objtype, List *objname, List *objargs, | ||||
| @ -580,9 +591,11 @@ get_object_address(ObjectType objtype, List *objname, List *objargs, | ||||
| 				{ | ||||
| 					TypeName   *sourcetype = (TypeName *) linitial(objname); | ||||
| 					TypeName   *targettype = (TypeName *) linitial(objargs); | ||||
| 					Oid			sourcetypeid = typenameTypeId(NULL, sourcetype); | ||||
| 					Oid			targettypeid = typenameTypeId(NULL, targettype); | ||||
| 					Oid			sourcetypeid; | ||||
| 					Oid			targettypeid; | ||||
| 
 | ||||
| 					sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok); | ||||
| 					targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok); | ||||
| 					address.classId = CastRelationId; | ||||
| 					address.objectId = | ||||
| 						get_cast_oid(sourcetypeid, targettypeid, missing_ok); | ||||
| @ -942,26 +955,31 @@ get_object_address_relobject(ObjectType objtype, List *objname, | ||||
| 
 | ||||
| 		/* 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 ? RelationGetRelid(relation) : InvalidOid; | ||||
| 
 | ||||
| 		switch (objtype) | ||||
| 		{ | ||||
| 			case OBJECT_RULE: | ||||
| 				address.classId = RewriteRelationId; | ||||
| 				address.objectId = get_rewrite_oid(reloid, depname, missing_ok); | ||||
| 				address.objectId = relation ? | ||||
| 					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 = relation ? | ||||
| 					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 = relation ? | ||||
| 					get_relation_constraint_oid(reloid, depname, missing_ok) : | ||||
| 					InvalidOid; | ||||
| 				address.objectSubId = 0; | ||||
| 				break; | ||||
| 			default: | ||||
| @ -975,7 +993,9 @@ get_object_address_relobject(ObjectType objtype, List *objname, | ||||
| 		/* 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; | ||||
| 		} | ||||
| @ -1008,6 +1028,7 @@ get_object_address_attribute(ObjectType objtype, List *objname, | ||||
| 				 errmsg("column name must be qualified"))); | ||||
| 	attname = strVal(lfirst(list_tail(objname))); | ||||
| 	relname = list_truncate(list_copy(objname), list_length(objname) - 1); | ||||
| 	/* XXX no missing_ok support here */ | ||||
| 	relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode); | ||||
| 	reloid = RelationGetRelid(relation); | ||||
| 
 | ||||
| @ -1053,7 +1074,7 @@ get_object_address_type(ObjectType objtype, | ||||
| 	address.objectId = InvalidOid; | ||||
| 	address.objectSubId = 0; | ||||
| 
 | ||||
| 	tup = LookupTypeName(NULL, typename, NULL); | ||||
| 	tup = LookupTypeName(NULL, typename, NULL, missing_ok); | ||||
| 	if (!HeapTupleIsValid(tup)) | ||||
| 	{ | ||||
| 		if (!missing_ok) | ||||
| @ -1090,6 +1111,7 @@ get_object_address_opcf(ObjectType objtype, | ||||
| 	ObjectAddress address; | ||||
| 
 | ||||
| 	Assert(list_length(objargs) == 1); | ||||
| 	/* XXX no missing_ok support here */ | ||||
| 	amoid = get_am_oid(strVal(linitial(objargs)), false); | ||||
| 
 | ||||
| 	switch (objtype) | ||||
|  | ||||
| @ -12,7 +12,6 @@ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| 
 | ||||
| #include "postgres.h" | ||||
| 
 | ||||
| #include "access/heapam.h" | ||||
| @ -29,8 +28,16 @@ | ||||
| #include "utils/builtins.h" | ||||
| #include "utils/syscache.h" | ||||
| 
 | ||||
| 
 | ||||
| static void does_not_exist_skipping(ObjectType objtype, | ||||
| 						List *objname, List *objargs); | ||||
| static bool owningrel_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); | ||||
| static bool type_in_list_does_not_exist_skipping(List *typenames, | ||||
| 									 const char **msg, char **name); | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Drop one or more objects. | ||||
| @ -73,9 +80,14 @@ RemoveObjects(DropStmt *stmt) | ||||
| 									 AccessExclusiveLock, | ||||
| 									 stmt->missing_ok); | ||||
| 
 | ||||
| 		/* Issue NOTICE if supplied object was not found. */ | ||||
| 		/*
 | ||||
| 		 * Issue NOTICE if supplied object was not found.  Note this is only | ||||
| 		 * relevant in the missing_ok case, because otherwise | ||||
| 		 * get_object_address would have thrown an error. | ||||
| 		 */ | ||||
| 		if (!OidIsValid(address.objectId)) | ||||
| 		{ | ||||
| 			Assert(stmt->missing_ok); | ||||
| 			does_not_exist_skipping(stmt->removeType, objname, objargs); | ||||
| 			continue; | ||||
| 		} | ||||
| @ -125,9 +137,121 @@ RemoveObjects(DropStmt *stmt) | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * owningrel_does_not_exist_skipping | ||||
|  *		Subroutine for RemoveObjects | ||||
|  * | ||||
|  * After determining that a specification for a rule or trigger returns that | ||||
|  * the specified object does not exist, test whether its owning relation, and | ||||
|  * its schema, exist or not; if they do, return false --- the trigger or rule | ||||
|  * itself is missing instead.  If the owning relation or its schema do not | ||||
|  * exist, fill the error message format string and name, and return true. | ||||
|  */ | ||||
| static bool | ||||
| owningrel_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; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * schema_does_not_exist_skipping | ||||
|  *		Subroutine for RemoveObjects | ||||
|  * | ||||
|  * After determining that a specification for a schema-qualifiable object | ||||
|  * refers to an object that does not exist, test whether the specified schema | ||||
|  * exists or not.  If no schema was specified, or if the schema does exist, | ||||
|  * return false -- the object itself is missing instead.  If the specified | ||||
|  * schema does not exist, fill the error message format string and the | ||||
|  * specified schema name, and return true. | ||||
|  */ | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * type_in_list_does_not_exist_skipping | ||||
|  *		Subroutine for RemoveObjects | ||||
|  * | ||||
|  * After determining that a specification for a function, cast, aggregate or | ||||
|  * operator returns that the specified object does not exist, test whether the | ||||
|  * involved datatypes, and their schemas, exist or not; if they do, return | ||||
|  * false --- the original object itself is missing instead.  If the datatypes | ||||
|  * or schemas do not exist, fill the error message format string and the | ||||
|  * missing name, and return true. | ||||
|  * | ||||
|  * First parameter is a list of TypeNames. | ||||
|  */ | ||||
| static bool | ||||
| type_in_list_does_not_exist_skipping(List *typenames, const char **msg, | ||||
| 									 char **name) | ||||
| { | ||||
| 	ListCell   *l; | ||||
| 
 | ||||
| 	foreach(l, typenames) | ||||
| 	{ | ||||
| 		TypeName   *typeName = (TypeName *) lfirst(l); | ||||
| 
 | ||||
| 		if (typeName != NULL) | ||||
| 		{ | ||||
| 			Assert(IsA(typeName, TypeName)); | ||||
| 
 | ||||
| 			if (!OidIsValid(LookupTypeNameOid(NULL, typeName, true))) | ||||
| 			{ | ||||
| 				/* type doesn't exist, try to find why */ | ||||
| 				if (schema_does_not_exist_skipping(typeName->names, msg, name)) | ||||
| 					return true; | ||||
| 
 | ||||
| 				*msg = gettext_noop("type \"%s\" does not exist, skipping"); | ||||
| 				*name = TypeNameToString(typeName); | ||||
| 
 | ||||
| 				return true; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * does_not_exist_skipping | ||||
|  *		Subroutine for RemoveObjects | ||||
|  * | ||||
|  * 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. | ||||
|  * get_object_address() in RemoveObjects would have thrown an ERROR. | ||||
|  */ | ||||
| static void | ||||
| does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs) | ||||
| @ -140,81 +264,125 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs) | ||||
| 	{ | ||||
| 		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) && | ||||
| 				!type_in_list_does_not_exist_skipping(objargs, &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) && | ||||
| 				!type_in_list_does_not_exist_skipping(objargs, &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) && | ||||
| 				!type_in_list_does_not_exist_skipping(objargs, &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))); | ||||
| 			{ | ||||
| 				if (!type_in_list_does_not_exist_skipping(objname, &msg, &name) && | ||||
| 				 !type_in_list_does_not_exist_skipping(objargs, &msg, &name)) | ||||
| 				{ | ||||
| 					/* XXX quote or no quote? */ | ||||
| 					msg = gettext_noop("cast from type %s to type %s does not exist, skipping"); | ||||
| 					name = TypeNameToString((TypeName *) linitial(objname)); | ||||
| 					args = TypeNameToString((TypeName *) linitial(objargs)); | ||||
| 				} | ||||
| 			} | ||||
| 			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), | ||||
| 			if (!owningrel_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), | ||||
| 			if (!owningrel_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 +393,20 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs) | ||||
| 			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); | ||||
|  | ||||
| @ -86,7 +86,7 @@ compute_return_type(TypeName *returnType, Oid languageOid, | ||||
| 	Type		typtup; | ||||
| 	AclResult	aclresult; | ||||
| 
 | ||||
| 	typtup = LookupTypeName(NULL, returnType, NULL); | ||||
| 	typtup = LookupTypeName(NULL, returnType, NULL, false); | ||||
| 
 | ||||
| 	if (typtup) | ||||
| 	{ | ||||
| @ -224,7 +224,7 @@ interpret_function_parameter_list(List *parameters, | ||||
| 		Type		typtup; | ||||
| 		AclResult	aclresult; | ||||
| 
 | ||||
| 		typtup = LookupTypeName(NULL, t, NULL); | ||||
| 		typtup = LookupTypeName(NULL, t, NULL, false); | ||||
| 		if (typtup) | ||||
| 		{ | ||||
| 			if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined) | ||||
|  | ||||
| @ -103,11 +103,14 @@ OpFamilyCacheLookup(Oid amID, List *opfamilyname, bool missing_ok) | ||||
| 		/* 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 *opclassname, bool missing_ok) | ||||
| 		/* 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 | ||||
| 	{ | ||||
|  | ||||
| @ -690,10 +690,28 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) | ||||
|  * 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 *relname, char rightkind, bool missing_ok) | ||||
| 			{ | ||||
| 				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; | ||||
| 		} | ||||
| 
 | ||||
|  | ||||
| @ -3246,7 +3246,7 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype) | ||||
| 	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), | ||||
|  | ||||
| @ -1259,7 +1259,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 | ||||
| @ -1714,7 +1715,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; | ||||
| 
 | ||||
| @ -1873,7 +1874,7 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError) | ||||
| { | ||||
| 	FuncCandidateList clist; | ||||
| 
 | ||||
| 	clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false); | ||||
| 	clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false, noError); | ||||
| 
 | ||||
| 	while (clist) | ||||
| 	{ | ||||
| @ -1892,27 +1893,6 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError) | ||||
| 	return InvalidOid; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
| @ -1940,7 +1920,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) | ||||
| 	{ | ||||
| 		TypeName   *t = (TypeName *) lfirst(args_item); | ||||
| 
 | ||||
| 		argoids[i] = LookupTypeNameOid(t); | ||||
| 		argoids[i] = LookupTypeNameOid(NULL, t, noError); | ||||
| 		args_item = lnext(args_item); | ||||
| 	} | ||||
| 
 | ||||
| @ -1980,7 +1960,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError) | ||||
| 	{ | ||||
| 		TypeName   *t = (TypeName *) lfirst(lc); | ||||
| 
 | ||||
| 		argoids[i] = LookupTypeNameOid(t); | ||||
| 		argoids[i] = LookupTypeNameOid(NULL, t, noError); | ||||
| 		i++; | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -148,12 +148,12 @@ LookupOperNameTypeNames(ParseState *pstate, List *opername, | ||||
| 	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); | ||||
|  | ||||
| @ -56,7 +56,7 @@ static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName, | ||||
|  */ | ||||
| Type | ||||
| LookupTypeName(ParseState *pstate, const TypeName *typeName, | ||||
| 			   int32 *typmod_p) | ||||
| 			   int32 *typmod_p, bool missing_ok) | ||||
| { | ||||
| 	Oid			typoid; | ||||
| 	HeapTuple	tup; | ||||
| @ -116,24 +116,32 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, | ||||
| 		 * concurrent DDL.	But taking a lock would carry a performance | ||||
| 		 * penalty and would also require a permissions check. | ||||
| 		 */ | ||||
| 		relid = RangeVarGetRelid(rel, NoLock, false); | ||||
| 		relid = RangeVarGetRelid(rel, NoLock, missing_ok); | ||||
| 		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); | ||||
| 		{ | ||||
| 			if (missing_ok) | ||||
| 				typoid = InvalidOid; | ||||
| 			else | ||||
| 				ereport(ERROR, | ||||
| 						(errcode(ERRCODE_UNDEFINED_COLUMN), | ||||
| 					errmsg("column \"%s\" of relation \"%s\" does not exist", | ||||
| 						   field, rel->relname), | ||||
| 						 parser_errposition(pstate, typeName->location))); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			typoid = get_atttype(relid, attnum); | ||||
| 
 | ||||
| 		/* this construct should never have an array indicator */ | ||||
| 		Assert(typeName->arrayBounds == NIL); | ||||
| 			/* this construct should never have an array indicator */ | ||||
| 			Assert(typeName->arrayBounds == NIL); | ||||
| 
 | ||||
| 		/* emit nuisance notice (intentionally not errposition'd) */ | ||||
| 		ereport(NOTICE, | ||||
| 				(errmsg("type reference %s converted to %s", | ||||
| 						TypeNameToString(typeName), | ||||
| 						format_type_be(typoid)))); | ||||
| 			/* emit nuisance notice (intentionally not errposition'd) */ | ||||
| 			ereport(NOTICE, | ||||
| 					(errmsg("type reference %s converted to %s", | ||||
| 							TypeNameToString(typeName), | ||||
| 							format_type_be(typoid)))); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @ -149,10 +157,13 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, | ||||
| 			/* Look in specific schema only */ | ||||
| 			Oid			namespaceId; | ||||
| 
 | ||||
| 			namespaceId = LookupExplicitNamespace(schemaname, false); | ||||
| 			typoid = GetSysCacheOid2(TYPENAMENSP, | ||||
| 									 PointerGetDatum(typname), | ||||
| 									 ObjectIdGetDatum(namespaceId)); | ||||
| 			namespaceId = LookupExplicitNamespace(schemaname, missing_ok); | ||||
| 			if (OidIsValid(namespaceId)) | ||||
| 				typoid = GetSysCacheOid2(TYPENAMENSP, | ||||
| 										 PointerGetDatum(typname), | ||||
| 										 ObjectIdGetDatum(namespaceId)); | ||||
| 			else | ||||
| 				typoid = InvalidOid; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @ -184,6 +195,43 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, | ||||
| 	return (Type) tup; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * LookupTypeNameOid | ||||
|  *		Given a TypeName object, lookup the pg_type syscache entry of the type. | ||||
|  *		Returns InvalidOid if no such type can be found.  If the type is found, | ||||
|  *		return its Oid. | ||||
|  * | ||||
|  * NB: direct callers of this function need to be aware that the type OID | ||||
|  * returned may correspond to a shell type.  Most code should go through | ||||
|  * typenameTypeId instead. | ||||
|  * | ||||
|  * pstate is only used for error location info, and may be NULL. | ||||
|  */ | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * typenameType - given a TypeName, return a Type structure and typmod | ||||
|  * | ||||
| @ -196,7 +244,7 @@ typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p) | ||||
| { | ||||
| 	Type		tup; | ||||
| 
 | ||||
| 	tup = LookupTypeName(pstate, typeName, typmod_p); | ||||
| 	tup = LookupTypeName(pstate, typeName, typmod_p, false); | ||||
| 	if (tup == NULL) | ||||
| 		ereport(ERROR, | ||||
| 				(errcode(ERRCODE_UNDEFINED_OBJECT), | ||||
|  | ||||
| @ -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) | ||||
| 	{ | ||||
|  | ||||
| @ -71,7 +71,8 @@ extern bool TypeIsVisible(Oid typid); | ||||
| extern FuncCandidateList FuncnameGetCandidates(List *names, | ||||
| 					  int nargs, List *argnames, | ||||
| 					  bool expand_variadic, | ||||
| 					  bool expand_defaults); | ||||
| 					  bool expand_defaults, | ||||
| 					  bool missing_ok); | ||||
| extern bool FunctionIsVisible(Oid funcid); | ||||
| 
 | ||||
| extern Oid	OpernameGetOprid(List *names, Oid oprleft, Oid oprright); | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -169,11 +169,15 @@ NOTICE:  cast from type text to type text does not exist, skipping | ||||
| 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 relation "test_exists" does not exist, skip | ||||
| 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,68 @@ ERROR:  access method "no_such_am" does not exist | ||||
| DROP TABLE IF EXISTS test_exists; | ||||
| DROP TABLE test_exists; | ||||
| ERROR:  table "test_exists" does not exist | ||||
| -- be tolerant with missing schemas, types, etc | ||||
| DROP AGGREGATE IF EXISTS no_such_schema.foo(int); | ||||
| NOTICE:  schema "no_such_schema" does not exist, skipping | ||||
| DROP AGGREGATE IF EXISTS foo(no_such_type); | ||||
| NOTICE:  type "no_such_type" does not exist, skipping | ||||
| DROP AGGREGATE IF EXISTS foo(no_such_schema.no_such_type); | ||||
| NOTICE:  schema "no_such_schema" does not exist, skipping | ||||
| DROP CAST IF EXISTS (INTEGER AS no_such_type2); | ||||
| NOTICE:  type "no_such_type2" does not exist, skipping | ||||
| DROP CAST IF EXISTS (no_such_type1 AS INTEGER); | ||||
| NOTICE:  type "no_such_type1" does not exist, skipping | ||||
| DROP CAST IF EXISTS (INTEGER AS no_such_schema.bar); | ||||
| NOTICE:  schema "no_such_schema" does not exist, skipping | ||||
| DROP CAST IF EXISTS (no_such_schema.foo AS INTEGER); | ||||
| 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 FUNCTION IF EXISTS foo(no_such_type); | ||||
| NOTICE:  type "no_such_type" does not exist, skipping | ||||
| DROP FUNCTION IF EXISTS foo(no_such_schema.no_such_type); | ||||
| 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 IF EXISTS + (no_such_type, no_such_type); | ||||
| NOTICE:  type "no_such_type" does not exist, skipping | ||||
| DROP OPERATOR IF EXISTS + (no_such_schema.no_such_type, no_such_schema.no_such_type); | ||||
| NOTICE:  schema "no_such_schema" does not exist, skipping | ||||
| DROP OPERATOR IF EXISTS # (NONE, no_such_schema.no_such_type); | ||||
| 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 | ||||
|  | ||||
| @ -280,7 +280,7 @@ SELECT * FROM dropped_objects WHERE schema IS NULL OR schema <> 'pg_toast'; | ||||
| (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'; | ||||
|  | ||||
| @ -182,6 +182,9 @@ DROP TRIGGER IF EXISTS test_trigger_exists ON test_exists; | ||||
| 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 test_exists; | ||||
| 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,38 @@ DROP OPERATOR FAMILY IF EXISTS test_operator_family USING no_such_am; | ||||
| DROP TABLE IF EXISTS test_exists; | ||||
| 
 | ||||
| DROP TABLE test_exists; | ||||
| 
 | ||||
| -- be tolerant with missing schemas, types, etc | ||||
| 
 | ||||
| DROP AGGREGATE IF EXISTS no_such_schema.foo(int); | ||||
| DROP AGGREGATE IF EXISTS foo(no_such_type); | ||||
| DROP AGGREGATE IF EXISTS foo(no_such_schema.no_such_type); | ||||
| DROP CAST IF EXISTS (INTEGER AS no_such_type2); | ||||
| DROP CAST IF EXISTS (no_such_type1 AS INTEGER); | ||||
| DROP CAST IF EXISTS (INTEGER AS no_such_schema.bar); | ||||
| DROP CAST IF EXISTS (no_such_schema.foo AS INTEGER); | ||||
| 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 FUNCTION IF EXISTS foo(no_such_type); | ||||
| DROP FUNCTION IF EXISTS foo(no_such_schema.no_such_type); | ||||
| 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 IF EXISTS + (no_such_type, no_such_type); | ||||
| DROP OPERATOR IF EXISTS + (no_such_schema.no_such_type, no_such_schema.no_such_type); | ||||
| DROP OPERATOR IF EXISTS # (NONE, no_such_schema.no_such_type); | ||||
| 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; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user