summaryrefslogtreecommitdiff
path: root/src/backend/commands/dropcmds.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2011-10-19 23:25:20 -0400
committerRobert Haas <rhaas@postgresql.org>2011-10-19 23:27:19 -0400
commit82a4a777d94bec965ab2f1d04b6e6a3f0447b377 (patch)
treeb3560173b695b8391ca81edf47c4b364005a608b /src/backend/commands/dropcmds.c
parent3301c83536e9da1e573e24ded2e610062dbf9cdc (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.c147
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)));
+}