diff options
author | Robert Haas <rhaas@postgresql.org> | 2011-10-19 23:25:20 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2011-10-19 23:27:19 -0400 |
commit | 82a4a777d94bec965ab2f1d04b6e6a3f0447b377 (patch) | |
tree | b3560173b695b8391ca81edf47c4b364005a608b /src/backend/commands/dropcmds.c | |
parent | 3301c83536e9da1e573e24ded2e610062dbf9cdc (diff) |
Consolidate DROP handling for some object types.
This gets rid of a significant amount of duplicative code.
KaiGai Kohei, reviewed in earlier versions by Dimitri Fontaine, with
further review and cleanup by me.
Diffstat (limited to 'src/backend/commands/dropcmds.c')
-rw-r--r-- | src/backend/commands/dropcmds.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c new file mode 100644 index 00000000000..8297730e3cf --- /dev/null +++ b/src/backend/commands/dropcmds.c @@ -0,0 +1,147 @@ +/*------------------------------------------------------------------------- + * + * dropcmds.c + * handle various "DROP" operations + * + * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/catalog/dropcmds.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/heapam.h" +#include "catalog/dependency.h" +#include "catalog/namespace.h" +#include "catalog/objectaddress.h" +#include "catalog/pg_class.h" +#include "commands/defrem.h" +#include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "parser/parse_type.h" +#include "utils/acl.h" + +static void does_not_exist_skipping(ObjectType objtype, List *objname); + +/* + * Drop one or more objects. + * + * We don't currently handle all object types here. Relations, for example, + * require special handling, because (for example) indexes have additional + * locking requirements. + * + * We look up all the objects first, and then delete them in a single + * performMultipleDeletions() call. This avoids unnecessary DROP RESTRICT + * errors if there are dependencies between them. + */ +void +RemoveObjects(DropStmt *stmt) +{ + ObjectAddresses *objects; + ListCell *cell1; + + objects = new_object_addresses(); + + foreach(cell1, stmt->objects) + { + ObjectAddress address; + List *objname = lfirst(cell1); + Relation relation = NULL; + Oid namespaceId; + + /* Get an ObjectAddress for the object. */ + address = get_object_address(stmt->removeType, + objname, NIL, + &relation, + AccessExclusiveLock, + stmt->missing_ok); + + /* Issue NOTICE if supplied object was not found. */ + if (!OidIsValid(address.objectId)) + { + does_not_exist_skipping(stmt->removeType, objname); + continue; + } + + /* Check permissions. */ + namespaceId = get_object_namespace(&address); + if (!OidIsValid(namespaceId) || + !pg_namespace_ownercheck(namespaceId, GetUserId())) + check_object_ownership(GetUserId(), stmt->removeType, address, + objname, NIL, relation); + + /* Release any relcache reference count, but keep lock until commit. */ + if (relation) + heap_close(relation, NoLock); + + add_exact_object_address(&address, objects); + } + + /* Here we really delete them. */ + performMultipleDeletions(objects, stmt->behavior); + + free_object_addresses(objects); +} + +/* + * 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. + */ +static void +does_not_exist_skipping(ObjectType objtype, List *objname) +{ + const char *msg = NULL; + char *name = NULL; + + switch (objtype) + { + case OBJECT_TYPE: + case OBJECT_DOMAIN: + 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); + break; + case OBJECT_CONVERSION: + 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); + break; + case OBJECT_TSDICTIONARY: + 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); + break; + case OBJECT_TSCONFIGURATION: + 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; + default: + elog(ERROR, "unexpected object type (%d)", (int)objtype); + break; + } + + ereport(NOTICE, (errmsg(msg, name))); +} |