Commit b152c6cd authored by Alvaro Herrera's avatar Alvaro Herrera

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
parent 9f80f483
...@@ -906,10 +906,15 @@ TypeIsVisible(Oid typid) ...@@ -906,10 +906,15 @@ TypeIsVisible(Oid typid)
* with oid = 0 that represents a set of such conflicting candidates. * 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 * 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. * 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 FuncCandidateList
FuncnameGetCandidates(List *names, int nargs, List *argnames, 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; FuncCandidateList resultList = NULL;
bool any_special = false; bool any_special = false;
...@@ -928,7 +933,9 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames, ...@@ -928,7 +933,9 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
if (schemaname) if (schemaname)
{ {
/* use exact schema given */ /* use exact schema given */
namespaceId = LookupExplicitNamespace(schemaname, false); namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
if (!OidIsValid(namespaceId))
return NULL;
} }
else else
{ {
...@@ -1414,7 +1421,7 @@ FunctionIsVisible(Oid funcid) ...@@ -1414,7 +1421,7 @@ FunctionIsVisible(Oid funcid)
visible = false; visible = false;
clist = FuncnameGetCandidates(list_make1(makeString(proname)), clist = FuncnameGetCandidates(list_make1(makeString(proname)),
nargs, NIL, false, false); nargs, NIL, false, false, false);
for (; clist; clist = clist->next) for (; clist; clist = clist->next)
{ {
...@@ -1443,7 +1450,8 @@ FunctionIsVisible(Oid funcid) ...@@ -1443,7 +1450,8 @@ FunctionIsVisible(Oid funcid)
* a postfix op. * a postfix op.
* *
* If the operator name is not schema-qualified, it is sought in the current * 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 Oid
OpernameGetOprid(List *names, Oid oprleft, Oid oprright) OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
...@@ -1460,9 +1468,12 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright) ...@@ -1460,9 +1468,12 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
{ {
/* search only in exact schema given */ /* search only in exact schema given */
Oid namespaceId; Oid namespaceId;
namespaceId = LookupExplicitNamespace(schemaname, true);
if (OidIsValid(namespaceId))
{
HeapTuple opertup; HeapTuple opertup;
namespaceId = LookupExplicitNamespace(schemaname, false);
opertup = SearchSysCache4(OPERNAMENSP, opertup = SearchSysCache4(OPERNAMENSP,
CStringGetDatum(opername), CStringGetDatum(opername),
ObjectIdGetDatum(oprleft), ObjectIdGetDatum(oprleft),
...@@ -1475,6 +1486,8 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright) ...@@ -1475,6 +1486,8 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
ReleaseSysCache(opertup); ReleaseSysCache(opertup);
return result; return result;
} }
}
return InvalidOid; return InvalidOid;
} }
...@@ -1729,7 +1742,7 @@ OperatorIsVisible(Oid oprid) ...@@ -1729,7 +1742,7 @@ OperatorIsVisible(Oid oprid)
* If it is in the path, it might still not be visible; it could be * 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 * 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 * 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); char *oprname = NameStr(oprform->oprname);
......
...@@ -450,7 +450,7 @@ static void getRelationIdentity(StringInfo buffer, Oid relid); ...@@ -450,7 +450,7 @@ static void getRelationIdentity(StringInfo buffer, Oid relid);
* sub-object is looked up, the parent object will be locked instead. * 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 * 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 * 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 * is a bit grotty but it makes life simpler, since the caller will
* typically need the relcache entry too. Caller must close the relcache * typically need the relcache entry too. Caller must close the relcache
...@@ -458,9 +458,20 @@ static void getRelationIdentity(StringInfo buffer, Oid relid); ...@@ -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 * if the target object is the relation itself or an attribute, but for other
* child objects, only AccessShareLock is acquired on the relation. * 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; * 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 * typically, the lock must be held until commit to guard against a concurrent
* drop operation. * 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 ObjectAddress
get_object_address(ObjectType objtype, List *objname, List *objargs, get_object_address(ObjectType objtype, List *objname, List *objargs,
...@@ -580,9 +591,11 @@ 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 *sourcetype = (TypeName *) linitial(objname);
TypeName *targettype = (TypeName *) linitial(objargs); TypeName *targettype = (TypeName *) linitial(objargs);
Oid sourcetypeid = typenameTypeId(NULL, sourcetype); Oid sourcetypeid;
Oid targettypeid = typenameTypeId(NULL, targettype); Oid targettypeid;
sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
address.classId = CastRelationId; address.classId = CastRelationId;
address.objectId = address.objectId =
get_cast_oid(sourcetypeid, targettypeid, missing_ok); get_cast_oid(sourcetypeid, targettypeid, missing_ok);
...@@ -942,26 +955,31 @@ get_object_address_relobject(ObjectType objtype, List *objname, ...@@ -942,26 +955,31 @@ get_object_address_relobject(ObjectType objtype, List *objname,
/* Extract relation name and open relation. */ /* Extract relation name and open relation. */
relname = list_truncate(list_copy(objname), nnames - 1); relname = list_truncate(list_copy(objname), nnames - 1);
relation = heap_openrv(makeRangeVarFromNameList(relname), relation = heap_openrv_extended(makeRangeVarFromNameList(relname),
AccessShareLock); AccessShareLock,
reloid = RelationGetRelid(relation); missing_ok);
reloid = relation ? RelationGetRelid(relation) : InvalidOid;
switch (objtype) switch (objtype)
{ {
case OBJECT_RULE: case OBJECT_RULE:
address.classId = RewriteRelationId; 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; address.objectSubId = 0;
break; break;
case OBJECT_TRIGGER: case OBJECT_TRIGGER:
address.classId = TriggerRelationId; 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; address.objectSubId = 0;
break; break;
case OBJECT_CONSTRAINT: case OBJECT_CONSTRAINT:
address.classId = ConstraintRelationId; address.classId = ConstraintRelationId;
address.objectId = address.objectId = relation ?
get_relation_constraint_oid(reloid, depname, missing_ok); get_relation_constraint_oid(reloid, depname, missing_ok) :
InvalidOid;
address.objectSubId = 0; address.objectSubId = 0;
break; break;
default: default:
...@@ -975,7 +993,9 @@ get_object_address_relobject(ObjectType objtype, List *objname, ...@@ -975,7 +993,9 @@ get_object_address_relobject(ObjectType objtype, List *objname,
/* Avoid relcache leak when object not found. */ /* Avoid relcache leak when object not found. */
if (!OidIsValid(address.objectId)) if (!OidIsValid(address.objectId))
{ {
if (relation != NULL)
heap_close(relation, AccessShareLock); heap_close(relation, AccessShareLock);
relation = NULL; /* department of accident prevention */ relation = NULL; /* department of accident prevention */
return address; return address;
} }
...@@ -1008,6 +1028,7 @@ get_object_address_attribute(ObjectType objtype, List *objname, ...@@ -1008,6 +1028,7 @@ get_object_address_attribute(ObjectType objtype, List *objname,
errmsg("column name must be qualified"))); errmsg("column name must be qualified")));
attname = strVal(lfirst(list_tail(objname))); attname = strVal(lfirst(list_tail(objname)));
relname = list_truncate(list_copy(objname), list_length(objname) - 1); relname = list_truncate(list_copy(objname), list_length(objname) - 1);
/* XXX no missing_ok support here */
relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode); relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
reloid = RelationGetRelid(relation); reloid = RelationGetRelid(relation);
...@@ -1053,7 +1074,7 @@ get_object_address_type(ObjectType objtype, ...@@ -1053,7 +1074,7 @@ get_object_address_type(ObjectType objtype,
address.objectId = InvalidOid; address.objectId = InvalidOid;
address.objectSubId = 0; address.objectSubId = 0;
tup = LookupTypeName(NULL, typename, NULL); tup = LookupTypeName(NULL, typename, NULL, missing_ok);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
if (!missing_ok) if (!missing_ok)
...@@ -1090,6 +1111,7 @@ get_object_address_opcf(ObjectType objtype, ...@@ -1090,6 +1111,7 @@ get_object_address_opcf(ObjectType objtype,
ObjectAddress address; ObjectAddress address;
Assert(list_length(objargs) == 1); Assert(list_length(objargs) == 1);
/* XXX no missing_ok support here */
amoid = get_am_oid(strVal(linitial(objargs)), false); amoid = get_am_oid(strVal(linitial(objargs)), false);
switch (objtype) switch (objtype)
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/heapam.h" #include "access/heapam.h"
...@@ -29,8 +28,16 @@ ...@@ -29,8 +28,16 @@
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/syscache.h" #include "utils/syscache.h"
static void does_not_exist_skipping(ObjectType objtype, static void does_not_exist_skipping(ObjectType objtype,
List *objname, List *objargs); 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. * Drop one or more objects.
...@@ -73,9 +80,14 @@ RemoveObjects(DropStmt *stmt) ...@@ -73,9 +80,14 @@ RemoveObjects(DropStmt *stmt)
AccessExclusiveLock, AccessExclusiveLock,
stmt->missing_ok); 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)) if (!OidIsValid(address.objectId))
{ {
Assert(stmt->missing_ok);
does_not_exist_skipping(stmt->removeType, objname, objargs); does_not_exist_skipping(stmt->removeType, objname, objargs);
continue; continue;
} }
...@@ -125,9 +137,121 @@ RemoveObjects(DropStmt *stmt) ...@@ -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 * 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, * 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 static void
does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs) does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
...@@ -140,81 +264,125 @@ 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_TYPE:
case OBJECT_DOMAIN: case OBJECT_DOMAIN:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("type \"%s\" does not exist, skipping"); msg = gettext_noop("type \"%s\" does not exist, skipping");
name = TypeNameToString(makeTypeNameFromNameList(objname)); name = TypeNameToString(makeTypeNameFromNameList(objname));
}
break; break;
case OBJECT_COLLATION: case OBJECT_COLLATION:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("collation \"%s\" does not exist, skipping"); msg = gettext_noop("collation \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
}
break; break;
case OBJECT_CONVERSION: case OBJECT_CONVERSION:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("conversion \"%s\" does not exist, skipping"); msg = gettext_noop("conversion \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
}
break; break;
case OBJECT_SCHEMA: case OBJECT_SCHEMA:
msg = gettext_noop("schema \"%s\" does not exist, skipping"); msg = gettext_noop("schema \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
break; break;
case OBJECT_TSPARSER: case OBJECT_TSPARSER:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("text search parser \"%s\" does not exist, skipping"); msg = gettext_noop("text search parser \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
}
break; break;
case OBJECT_TSDICTIONARY: case OBJECT_TSDICTIONARY:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping"); msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
}
break; break;
case OBJECT_TSTEMPLATE: case OBJECT_TSTEMPLATE:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("text search template \"%s\" does not exist, skipping"); msg = gettext_noop("text search template \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
}
break; break;
case OBJECT_TSCONFIGURATION: case OBJECT_TSCONFIGURATION:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("text search configuration \"%s\" does not exist, skipping"); msg = gettext_noop("text search configuration \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
}
break; break;
case OBJECT_EXTENSION: case OBJECT_EXTENSION:
msg = gettext_noop("extension \"%s\" does not exist, skipping"); msg = gettext_noop("extension \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
break; break;
case OBJECT_FUNCTION: case OBJECT_FUNCTION:
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"); msg = gettext_noop("function %s(%s) does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
args = TypeNameListToString(objargs); args = TypeNameListToString(objargs);
}
break; break;
case OBJECT_AGGREGATE: case OBJECT_AGGREGATE:
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"); msg = gettext_noop("aggregate %s(%s) does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
args = TypeNameListToString(objargs); args = TypeNameListToString(objargs);
}
break; break;
case OBJECT_OPERATOR: case OBJECT_OPERATOR:
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"); msg = gettext_noop("operator %s does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
}
break; break;
case OBJECT_LANGUAGE: case OBJECT_LANGUAGE:
msg = gettext_noop("language \"%s\" does not exist, skipping"); msg = gettext_noop("language \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
break; break;
case OBJECT_CAST: case OBJECT_CAST:
{
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"); msg = gettext_noop("cast from type %s to type %s does not exist, skipping");
name = format_type_be(typenameTypeId(NULL, name = TypeNameToString((TypeName *) linitial(objname));
(TypeName *) linitial(objname))); args = TypeNameToString((TypeName *) linitial(objargs));
args = format_type_be(typenameTypeId(NULL, }
(TypeName *) linitial(objargs))); }
break; break;
case OBJECT_TRIGGER: case OBJECT_TRIGGER:
msg = gettext_noop("trigger \"%s\" for table \"%s\" does not exist, skipping"); 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)); name = strVal(llast(objname));
args = NameListToString(list_truncate(list_copy(objname), args = NameListToString(list_truncate(list_copy(objname),
list_length(objname) - 1)); list_length(objname) - 1));
}
break; break;
case OBJECT_EVENT_TRIGGER: case OBJECT_EVENT_TRIGGER:
msg = gettext_noop("event trigger \"%s\" does not exist, skipping"); msg = gettext_noop("event trigger \"%s\" does not exist, skipping");
name = NameListToString(objname); name = NameListToString(objname);
break; break;
case OBJECT_RULE: case OBJECT_RULE:
if (!owningrel_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping"); msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping");
name = strVal(llast(objname)); name = strVal(llast(objname));
args = NameListToString(list_truncate(list_copy(objname), args = NameListToString(list_truncate(list_copy(objname),
list_length(objname) - 1)); list_length(objname) - 1));
}
break; break;
case OBJECT_FDW: case OBJECT_FDW:
msg = gettext_noop("foreign-data wrapper \"%s\" does not exist, skipping"); 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) ...@@ -225,14 +393,20 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
name = NameListToString(objname); name = NameListToString(objname);
break; break;
case OBJECT_OPCLASS: case OBJECT_OPCLASS:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping"); msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping");
name = NameListToString(objname); name = NameListToString(objname);
args = strVal(linitial(objargs)); args = strVal(linitial(objargs));
}
break; break;
case OBJECT_OPFAMILY: case OBJECT_OPFAMILY:
if (!schema_does_not_exist_skipping(objname, &msg, &name))
{
msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping"); msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping");
name = NameListToString(objname); name = NameListToString(objname);
args = strVal(linitial(objargs)); args = strVal(linitial(objargs));
}
break; break;
default: default:
elog(ERROR, "unexpected object type (%d)", (int) objtype); elog(ERROR, "unexpected object type (%d)", (int) objtype);
......
...@@ -86,7 +86,7 @@ compute_return_type(TypeName *returnType, Oid languageOid, ...@@ -86,7 +86,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
Type typtup; Type typtup;
AclResult aclresult; AclResult aclresult;
typtup = LookupTypeName(NULL, returnType, NULL); typtup = LookupTypeName(NULL, returnType, NULL, false);
if (typtup) if (typtup)
{ {
...@@ -224,7 +224,7 @@ interpret_function_parameter_list(List *parameters, ...@@ -224,7 +224,7 @@ interpret_function_parameter_list(List *parameters,
Type typtup; Type typtup;
AclResult aclresult; AclResult aclresult;
typtup = LookupTypeName(NULL, t, NULL); typtup = LookupTypeName(NULL, t, NULL, false);
if (typtup) if (typtup)
{ {
if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined) if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
......
...@@ -103,7 +103,10 @@ OpFamilyCacheLookup(Oid amID, List *opfamilyname, bool missing_ok) ...@@ -103,7 +103,10 @@ OpFamilyCacheLookup(Oid amID, List *opfamilyname, bool missing_ok)
/* Look in specific schema only */ /* Look in specific schema only */
Oid namespaceId; Oid namespaceId;
namespaceId = LookupExplicitNamespace(schemaname, false); namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
if (!OidIsValid(namespaceId))
htup = NULL;
else
htup = SearchSysCache3(OPFAMILYAMNAMENSP, htup = SearchSysCache3(OPFAMILYAMNAMENSP,
ObjectIdGetDatum(amID), ObjectIdGetDatum(amID),
PointerGetDatum(opfname), PointerGetDatum(opfname),
...@@ -179,7 +182,10 @@ OpClassCacheLookup(Oid amID, List *opclassname, bool missing_ok) ...@@ -179,7 +182,10 @@ OpClassCacheLookup(Oid amID, List *opclassname, bool missing_ok)
/* Look in specific schema only */ /* Look in specific schema only */
Oid namespaceId; Oid namespaceId;
namespaceId = LookupExplicitNamespace(schemaname, false); namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
if (!OidIsValid(namespaceId))
htup = NULL;
else
htup = SearchSysCache3(CLAAMNAMENSP, htup = SearchSysCache3(CLAAMNAMENSP,
ObjectIdGetDatum(amID), ObjectIdGetDatum(amID),
PointerGetDatum(opcname), PointerGetDatum(opcname),
......
...@@ -690,10 +690,28 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) ...@@ -690,10 +690,28 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
* non-existent relation * non-existent relation
*/ */
static void static void
DropErrorMsgNonExistent(const char *relname, char rightkind, bool missing_ok) DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
{ {
const struct dropmsgstrings *rentry; 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++) for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
{ {
if (rentry->kind == rightkind) if (rentry->kind == rightkind)
...@@ -702,11 +720,11 @@ DropErrorMsgNonExistent(const char *relname, char rightkind, bool missing_ok) ...@@ -702,11 +720,11 @@ DropErrorMsgNonExistent(const char *relname, char rightkind, bool missing_ok)
{ {
ereport(ERROR, ereport(ERROR,
(errcode(rentry->nonexistent_code), (errcode(rentry->nonexistent_code),
errmsg(rentry->nonexistent_msg, relname))); errmsg(rentry->nonexistent_msg, rel->relname)));
} }
else else
{ {
ereport(NOTICE, (errmsg(rentry->skipping_msg, relname))); ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
break; break;
} }
} }
...@@ -845,7 +863,7 @@ RemoveRelations(DropStmt *drop) ...@@ -845,7 +863,7 @@ RemoveRelations(DropStmt *drop)
/* Not there? */ /* Not there? */
if (!OidIsValid(relOid)) if (!OidIsValid(relOid))
{ {
DropErrorMsgNonExistent(rel->relname, relkind, drop->missing_ok); DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
continue; continue;
} }
......
...@@ -3246,7 +3246,7 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype) ...@@ -3246,7 +3246,7 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be processed */ /* Use LookupTypeName here so that shell types can be processed */
tup = LookupTypeName(NULL, typename, NULL); tup = LookupTypeName(NULL, typename, NULL, false);
if (tup == NULL) if (tup == NULL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
......
...@@ -1259,7 +1259,8 @@ func_get_detail(List *funcname, ...@@ -1259,7 +1259,8 @@ func_get_detail(List *funcname,
/* Get list of possible candidates from namespace search */ /* Get list of possible candidates from namespace search */
raw_candidates = FuncnameGetCandidates(funcname, nargs, fargnames, 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 * Quickly check if there is an exact match to the input datatypes (there
...@@ -1714,7 +1715,7 @@ FuncNameAsType(List *funcname) ...@@ -1714,7 +1715,7 @@ FuncNameAsType(List *funcname)
Oid result; Oid result;
Type typtup; Type typtup;
typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL); typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL, false);
if (typtup == NULL) if (typtup == NULL)
return InvalidOid; return InvalidOid;
...@@ -1873,7 +1874,7 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError) ...@@ -1873,7 +1874,7 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
{ {
FuncCandidateList clist; FuncCandidateList clist;
clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false); clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false, noError);
while (clist) while (clist)
{ {
...@@ -1892,27 +1893,6 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError) ...@@ -1892,27 +1893,6 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
return InvalidOid; 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 * LookupFuncNameTypeNames
* Like LookupFuncName, but the argument types are specified by a * Like LookupFuncName, but the argument types are specified by a
...@@ -1940,7 +1920,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) ...@@ -1940,7 +1920,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
{ {
TypeName *t = (TypeName *) lfirst(args_item); TypeName *t = (TypeName *) lfirst(args_item);
argoids[i] = LookupTypeNameOid(t); argoids[i] = LookupTypeNameOid(NULL, t, noError);
args_item = lnext(args_item); args_item = lnext(args_item);
} }
...@@ -1980,7 +1960,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError) ...@@ -1980,7 +1960,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
{ {
TypeName *t = (TypeName *) lfirst(lc); TypeName *t = (TypeName *) lfirst(lc);
argoids[i] = LookupTypeNameOid(t); argoids[i] = LookupTypeNameOid(NULL, t, noError);
i++; i++;
} }
......
...@@ -148,12 +148,12 @@ LookupOperNameTypeNames(ParseState *pstate, List *opername, ...@@ -148,12 +148,12 @@ LookupOperNameTypeNames(ParseState *pstate, List *opername,
if (oprleft == NULL) if (oprleft == NULL)
leftoid = InvalidOid; leftoid = InvalidOid;
else else
leftoid = typenameTypeId(pstate, oprleft); leftoid = LookupTypeNameOid(pstate, oprleft, noError);
if (oprright == NULL) if (oprright == NULL)
rightoid = InvalidOid; rightoid = InvalidOid;
else else
rightoid = typenameTypeId(pstate, oprright); rightoid = LookupTypeNameOid(pstate, oprright, noError);
return LookupOperName(pstate, opername, leftoid, rightoid, return LookupOperName(pstate, opername, leftoid, rightoid,
noError, location); noError, location);
......
...@@ -56,7 +56,7 @@ static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName, ...@@ -56,7 +56,7 @@ static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName,
*/ */
Type Type
LookupTypeName(ParseState *pstate, const TypeName *typeName, LookupTypeName(ParseState *pstate, const TypeName *typeName,
int32 *typmod_p) int32 *typmod_p, bool missing_ok)
{ {
Oid typoid; Oid typoid;
HeapTuple tup; HeapTuple tup;
...@@ -116,14 +116,21 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, ...@@ -116,14 +116,21 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
* concurrent DDL. But taking a lock would carry a performance * concurrent DDL. But taking a lock would carry a performance
* penalty and would also require a permissions check. * penalty and would also require a permissions check.
*/ */
relid = RangeVarGetRelid(rel, NoLock, false); relid = RangeVarGetRelid(rel, NoLock, missing_ok);
attnum = get_attnum(relid, field); attnum = get_attnum(relid, field);
if (attnum == InvalidAttrNumber) if (attnum == InvalidAttrNumber)
{
if (missing_ok)
typoid = InvalidOid;
else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\" does not exist", errmsg("column \"%s\" of relation \"%s\" does not exist",
field, rel->relname), field, rel->relname),
parser_errposition(pstate, typeName->location))); parser_errposition(pstate, typeName->location)));
}
else
{
typoid = get_atttype(relid, attnum); typoid = get_atttype(relid, attnum);
/* this construct should never have an array indicator */ /* this construct should never have an array indicator */
...@@ -135,6 +142,7 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, ...@@ -135,6 +142,7 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
TypeNameToString(typeName), TypeNameToString(typeName),
format_type_be(typoid)))); format_type_be(typoid))));
} }
}
else else
{ {
/* Normal reference to a type name */ /* Normal reference to a type name */
...@@ -149,10 +157,13 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, ...@@ -149,10 +157,13 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
/* Look in specific schema only */ /* Look in specific schema only */
Oid namespaceId; Oid namespaceId;
namespaceId = LookupExplicitNamespace(schemaname, false); namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
if (OidIsValid(namespaceId))
typoid = GetSysCacheOid2(TYPENAMENSP, typoid = GetSysCacheOid2(TYPENAMENSP,
PointerGetDatum(typname), PointerGetDatum(typname),
ObjectIdGetDatum(namespaceId)); ObjectIdGetDatum(namespaceId));
else
typoid = InvalidOid;
} }
else else
{ {
...@@ -184,6 +195,43 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, ...@@ -184,6 +195,43 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
return (Type) tup; 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 * typenameType - given a TypeName, return a Type structure and typmod
* *
...@@ -196,7 +244,7 @@ typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p) ...@@ -196,7 +244,7 @@ typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
{ {
Type tup; Type tup;
tup = LookupTypeName(pstate, typeName, typmod_p); tup = LookupTypeName(pstate, typeName, typmod_p, false);
if (tup == NULL) if (tup == NULL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
......
...@@ -135,7 +135,7 @@ regprocin(PG_FUNCTION_ARGS) ...@@ -135,7 +135,7 @@ regprocin(PG_FUNCTION_ARGS)
* pg_proc entries in the current search path. * pg_proc entries in the current search path.
*/ */
names = stringToQualifiedNameList(pro_name_or_oid); names = stringToQualifiedNameList(pro_name_or_oid);
clist = FuncnameGetCandidates(names, -1, NIL, false, false); clist = FuncnameGetCandidates(names, -1, NIL, false, false, false);
if (clist == NULL) if (clist == NULL)
ereport(ERROR, ereport(ERROR,
...@@ -192,7 +192,7 @@ regprocout(PG_FUNCTION_ARGS) ...@@ -192,7 +192,7 @@ regprocout(PG_FUNCTION_ARGS)
* qualify it. * qualify it.
*/ */
clist = FuncnameGetCandidates(list_make1(makeString(proname)), clist = FuncnameGetCandidates(list_make1(makeString(proname)),
-1, NIL, false, false); -1, NIL, false, false, false);
if (clist != NULL && clist->next == NULL && if (clist != NULL && clist->next == NULL &&
clist->oid == proid) clist->oid == proid)
nspname = NULL; nspname = NULL;
...@@ -279,7 +279,7 @@ regprocedurein(PG_FUNCTION_ARGS) ...@@ -279,7 +279,7 @@ regprocedurein(PG_FUNCTION_ARGS)
*/ */
parseNameAndArgTypes(pro_name_or_oid, false, &names, &nargs, argtypes); 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) for (; clist; clist = clist->next)
{ {
......
...@@ -71,7 +71,8 @@ extern bool TypeIsVisible(Oid typid); ...@@ -71,7 +71,8 @@ extern bool TypeIsVisible(Oid typid);
extern FuncCandidateList FuncnameGetCandidates(List *names, extern FuncCandidateList FuncnameGetCandidates(List *names,
int nargs, List *argnames, int nargs, List *argnames,
bool expand_variadic, bool expand_variadic,
bool expand_defaults); bool expand_defaults,
bool missing_ok);
extern bool FunctionIsVisible(Oid funcid); extern bool FunctionIsVisible(Oid funcid);
extern Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright); extern Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright);
......
...@@ -20,7 +20,9 @@ ...@@ -20,7 +20,9 @@
typedef HeapTuple Type; typedef HeapTuple Type;
extern Type LookupTypeName(ParseState *pstate, const TypeName *typeName, 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, extern Type typenameType(ParseState *pstate, const TypeName *typeName,
int32 *typmod_p); int32 *typmod_p);
extern Oid typenameTypeId(ParseState *pstate, const TypeName *typeName); extern Oid typenameTypeId(ParseState *pstate, const TypeName *typeName);
......
...@@ -1665,7 +1665,7 @@ plpgsql_parse_wordtype(char *ident) ...@@ -1665,7 +1665,7 @@ plpgsql_parse_wordtype(char *ident)
* Word wasn't found in the namespace stack. Try to find a data type with * Word wasn't found in the namespace stack. Try to find a data type with
* that name, but ignore shell types and complex types. * that name, but ignore shell types and complex types.
*/ */
typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL); typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL, false);
if (typeTup) if (typeTup)
{ {
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(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 ...@@ -169,11 +169,15 @@ NOTICE: cast from type text to type text does not exist, skipping
DROP TRIGGER test_trigger_exists ON test_exists; DROP TRIGGER test_trigger_exists ON test_exists;
ERROR: trigger "test_trigger_exists" for table "test_exists" does not exist ERROR: trigger "test_trigger_exists" for table "test_exists" does not exist
DROP TRIGGER IF EXISTS test_trigger_exists ON test_exists; 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; DROP TRIGGER test_trigger_exists ON no_such_table;
ERROR: relation "no_such_table" does not exist ERROR: relation "no_such_table" does not exist
DROP TRIGGER IF EXISTS test_trigger_exists ON no_such_table; 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 CREATE TRIGGER test_trigger_exists
BEFORE UPDATE ON test_exists BEFORE UPDATE ON test_exists
FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); 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 ...@@ -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; DROP RULE test_rule_exists ON no_such_table;
ERROR: relation "no_such_table" does not exist ERROR: relation "no_such_table" does not exist
DROP RULE IF EXISTS test_rule_exists ON no_such_table; 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 CREATE RULE test_rule_exists AS ON INSERT TO test_exists
DO INSTEAD DO INSTEAD
INSERT INTO test_exists VALUES (NEW.a, NEW.b || NEW.a::text); 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 ...@@ -223,3 +231,68 @@ ERROR: access method "no_such_am" does not exist
DROP TABLE IF EXISTS test_exists; DROP TABLE IF EXISTS test_exists;
DROP TABLE test_exists; DROP TABLE test_exists;
ERROR: table "test_exists" does not exist 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'; ...@@ -280,7 +280,7 @@ SELECT * FROM dropped_objects WHERE schema IS NULL OR schema <> 'pg_toast';
(23 rows) (23 rows)
DROP OWNED BY regression_bob; 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" 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 PL/pgSQL function test_evtrig_dropped_objects() line 8 at EXECUTE statement
SELECT * FROM dropped_objects WHERE type = 'schema'; SELECT * FROM dropped_objects WHERE type = 'schema';
......
...@@ -182,6 +182,9 @@ DROP TRIGGER IF EXISTS test_trigger_exists ON test_exists; ...@@ -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 test_trigger_exists ON no_such_table;
DROP TRIGGER IF EXISTS 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 CREATE TRIGGER test_trigger_exists
BEFORE UPDATE ON test_exists BEFORE UPDATE ON test_exists
FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
...@@ -194,6 +197,9 @@ DROP RULE IF EXISTS test_rule_exists ON test_exists; ...@@ -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 test_rule_exists ON no_such_table;
DROP RULE IF EXISTS 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 CREATE RULE test_rule_exists AS ON INSERT TO test_exists
DO INSTEAD DO INSTEAD
INSERT INTO test_exists VALUES (NEW.a, NEW.b || NEW.a::text); 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; ...@@ -226,3 +232,38 @@ DROP OPERATOR FAMILY IF EXISTS test_operator_family USING no_such_am;
DROP TABLE IF EXISTS test_exists; DROP TABLE IF EXISTS test_exists;
DROP TABLE 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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment