diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/dropcmds.c | 258 | ||||
-rw-r--r-- | src/backend/commands/functioncmds.c | 4 | ||||
-rw-r--r-- | src/backend/commands/opclasscmds.c | 26 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 26 | ||||
-rw-r--r-- | src/backend/commands/typecmds.c | 2 |
5 files changed, 257 insertions, 59 deletions
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c index b25317ebad4..e64ad8027e2 100644 --- a/src/backend/commands/dropcmds.c +++ b/src/backend/commands/dropcmds.c @@ -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); diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 7763feccf97..350cb76ab8c 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -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) diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index c910c3964c6..5d7b37c674a 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -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 { diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 26a4613c474..08b037e501f 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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; } diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index d85c16c7270..c1ee69b3233 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -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), |