]> granicus.if.org Git - postgresql/commitdiff
Consolidate DROP handling for some object types.
authorRobert Haas <rhaas@postgresql.org>
Thu, 20 Oct 2011 03:25:20 +0000 (23:25 -0400)
committerRobert Haas <rhaas@postgresql.org>
Thu, 20 Oct 2011 03:27:19 +0000 (23:27 -0400)
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.

17 files changed:
src/backend/catalog/objectaddress.c
src/backend/commands/Makefile
src/backend/commands/collationcmds.c
src/backend/commands/conversioncmds.c
src/backend/commands/dropcmds.c [new file with mode: 0644]
src/backend/commands/extension.c
src/backend/commands/schemacmds.c
src/backend/commands/tsearchcmds.c
src/backend/commands/typecmds.c
src/backend/tcop/utility.c
src/include/catalog/objectaddress.h
src/include/commands/collationcmds.h
src/include/commands/conversioncmds.h
src/include/commands/defrem.h
src/include/commands/extension.h
src/include/commands/schemacmds.h
src/include/commands/typecmds.h

index 395c11605a3872f4501fd98d375b7ccf5db5f151..de2a26dada9143f615c47bc99ec07d5b37fe8169 100644 (file)
 #include "utils/syscache.h"
 #include "utils/tqual.h"
 
-static ObjectAddress get_object_address_unqualified(ObjectType objtype,
-                                                          List *qualname, bool missing_ok);
-static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
-                                                          List *objname, Relation *relp,
-                                                          LOCKMODE lockmode, bool missing_ok);
-static ObjectAddress get_object_address_relobject(ObjectType objtype,
-                                                        List *objname, Relation *relp, bool missing_ok);
-static ObjectAddress get_object_address_attribute(ObjectType objtype,
-                                                        List *objname, Relation *relp,
-                                                        LOCKMODE lockmode, bool missing_ok);
-static ObjectAddress get_object_address_type(ObjectType objtype,
-                                               List *objname, bool missing_ok);
-static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
-                                               List *objargs, bool missing_ok);
-static bool object_exists(ObjectAddress address);
-
 /*
  * ObjectProperty
  *
@@ -93,6 +77,7 @@ typedef struct
        Oid                     class_oid;                      /* oid of catalog */
        Oid                     oid_index_oid;          /* oid of index on system oid column */
        int                     oid_catcache_id;        /* id of catcache on system oid column  */
+       AttrNumber      attnum_namespace;       /* attnum of namespace field */
 } ObjectPropertyType;
 
 static ObjectPropertyType ObjectProperty[] =
@@ -100,130 +85,172 @@ static ObjectPropertyType ObjectProperty[] =
        {
                CastRelationId,
                CastOidIndexId,
-               -1
+               -1,
+               InvalidAttrNumber
        },
        {
                CollationRelationId,
                CollationOidIndexId,
-               COLLOID
+               COLLOID,
+               Anum_pg_collation_collnamespace
        },
        {
                ConstraintRelationId,
                ConstraintOidIndexId,
-               CONSTROID
+               CONSTROID,
+               Anum_pg_constraint_connamespace
        },
        {
                ConversionRelationId,
                ConversionOidIndexId,
-               CONVOID
+               CONVOID,
+               Anum_pg_conversion_connamespace
        },
        {
                DatabaseRelationId,
                DatabaseOidIndexId,
-               DATABASEOID
+               DATABASEOID,
+               InvalidAttrNumber
        },
        {
                ExtensionRelationId,
                ExtensionOidIndexId,
-               -1
+               -1,
+               Anum_pg_extension_extnamespace
        },
        {
                ForeignDataWrapperRelationId,
                ForeignDataWrapperOidIndexId,
-               FOREIGNDATAWRAPPEROID
+               FOREIGNDATAWRAPPEROID,
+               InvalidAttrNumber
        },
        {
                ForeignServerRelationId,
                ForeignServerOidIndexId,
-               FOREIGNSERVEROID
+               FOREIGNSERVEROID,
+               InvalidAttrNumber
        },
        {
                ProcedureRelationId,
                ProcedureOidIndexId,
-               PROCOID
+               PROCOID,
+               Anum_pg_proc_pronamespace
        },
        {
                LanguageRelationId,
                LanguageOidIndexId,
-               LANGOID
+               LANGOID,
+               InvalidAttrNumber,
        },
        {
                LargeObjectMetadataRelationId,
                LargeObjectMetadataOidIndexId,
-               -1
+               -1,
+               InvalidAttrNumber
        },
        {
                OperatorClassRelationId,
                OpclassOidIndexId,
-               CLAOID
+               CLAOID,
+               Anum_pg_opclass_opcnamespace,
        },
        {
                OperatorRelationId,
                OperatorOidIndexId,
-               OPEROID
+               OPEROID,
+               Anum_pg_operator_oprnamespace
        },
        {
                OperatorFamilyRelationId,
                OpfamilyOidIndexId,
-               OPFAMILYOID
+               OPFAMILYOID,
+               Anum_pg_opfamily_opfnamespace
        },
        {
                AuthIdRelationId,
                AuthIdOidIndexId,
-               AUTHOID
+               AUTHOID,
+               InvalidAttrNumber
        },
        {
                RewriteRelationId,
                RewriteOidIndexId,
-               -1
+               -1,
+               InvalidAttrNumber
        },
        {
                NamespaceRelationId,
                NamespaceOidIndexId,
-               NAMESPACEOID
+               NAMESPACEOID,
+               InvalidAttrNumber
        },
        {
                RelationRelationId,
                ClassOidIndexId,
-               RELOID
+               RELOID,
+               Anum_pg_class_relnamespace
        },
        {
                TableSpaceRelationId,
                TablespaceOidIndexId,
                TABLESPACEOID,
+               InvalidAttrNumber
        },
        {
                TriggerRelationId,
                TriggerOidIndexId,
-               -1
+               -1,
+               InvalidAttrNumber
        },
        {
                TSConfigRelationId,
                TSConfigOidIndexId,
-               TSCONFIGOID
+               TSCONFIGOID,
+               Anum_pg_ts_config_cfgnamespace
        },
        {
                TSDictionaryRelationId,
                TSDictionaryOidIndexId,
-               TSDICTOID
+               TSDICTOID,
+               Anum_pg_ts_dict_dictnamespace
        },
        {
                TSParserRelationId,
                TSParserOidIndexId,
-               TSPARSEROID
+               TSPARSEROID,
+               Anum_pg_ts_parser_prsnamespace
        },
        {
                TSTemplateRelationId,
                TSTemplateOidIndexId,
-               TSTEMPLATEOID
+               TSTEMPLATEOID,
+               Anum_pg_ts_template_tmplnamespace,
        },
        {
                TypeRelationId,
                TypeOidIndexId,
-               TYPEOID
+               TYPEOID,
+               Anum_pg_type_typnamespace
        }
 };
 
+static ObjectAddress get_object_address_unqualified(ObjectType objtype,
+                                                          List *qualname, bool missing_ok);
+static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
+                                                          List *objname, Relation *relp,
+                                                          LOCKMODE lockmode, bool missing_ok);
+static ObjectAddress get_object_address_relobject(ObjectType objtype,
+                                                        List *objname, Relation *relp, bool missing_ok);
+static ObjectAddress get_object_address_attribute(ObjectType objtype,
+                                                        List *objname, Relation *relp,
+                                                        LOCKMODE lockmode, bool missing_ok);
+static ObjectAddress get_object_address_type(ObjectType objtype,
+                                               List *objname, bool missing_ok);
+static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
+                                               List *objargs, bool missing_ok);
+static bool object_exists(ObjectAddress address);
+static ObjectPropertyType *get_object_property_data(Oid class_id);
+
 /*
  * Translate an object name and arguments (as passed by the parser) to an
  * ObjectAddress.
@@ -828,6 +855,7 @@ object_exists(ObjectAddress address)
        ScanKeyData skey[1];
        SysScanDesc sd;
        bool            found;
+       ObjectPropertyType         *property;
 
        /* Sub-objects require special treatment. */
        if (address.objectSubId != 0)
@@ -847,35 +875,22 @@ object_exists(ObjectAddress address)
                }
                return found;
        }
-       else 
-       {
-               int                     index;
 
-               /*
-                * Weird backward compatibility hack: ObjectAddress notation uses
-                * LargeObjectRelationId for large objects, but since PostgreSQL
-                * 9.0, the relevant catalog is actually LargeObjectMetadataRelationId.
-                */
-               if (address.classId == LargeObjectRelationId)
-                       address.classId = LargeObjectMetadataRelationId;
+       /*
+        * Weird backward compatibility hack: ObjectAddress notation uses
+        * LargeObjectRelationId for large objects, but since PostgreSQL
+        * 9.0, the relevant catalog is actually LargeObjectMetadataRelationId.
+        */
+       if (address.classId == LargeObjectRelationId)
+               address.classId = LargeObjectMetadataRelationId;
 
-               /*
-                * For object types that have a relevant syscache, we use it; for
-                * everything else, we'll have to do an index-scan.  Search the
-                * ObjectProperty array to find out which it is.
-                */
-               for (index = 0; index < lengthof(ObjectProperty); index++)
-               {
-                       if (ObjectProperty[index].class_oid == address.classId)
-                       {
-                               cache = ObjectProperty[index].oid_catcache_id;
-                               indexoid = ObjectProperty[index].oid_index_oid;
-                               break;
-                       }
-               }
-               if (index == lengthof(ObjectProperty))
-                       elog(ERROR, "unrecognized classid: %u", address.classId);
-       }
+       /*
+        * For object types that have a relevant syscache, we use it; for
+        * everything else, we'll have to do an index-scan.
+        */
+       property = get_object_property_data(address.classId);
+       cache = property->oid_catcache_id;
+       indexoid = property->oid_index_oid;
 
        /* Found a syscache? */
        if (cache != -1)
@@ -895,7 +910,6 @@ object_exists(ObjectAddress address)
        return found;
 }
 
-
 /*
  * Check ownership of an object previously identified by get_object_address.
  */
@@ -1060,3 +1074,58 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
                                 (int) objtype);
        }
 }
+
+/*
+ * get_object_namespace
+ *
+ * Find the schema containing the specified object.  For non-schema objects,
+ * this function returns InvalidOid.
+ */
+Oid
+get_object_namespace(const ObjectAddress *address)
+{
+       int                     cache;
+       HeapTuple       tuple;
+       bool            isnull;
+       Oid                     oid;
+       ObjectPropertyType         *property;
+
+       /* If not owned by a namespace, just return InvalidOid. */
+       property = get_object_property_data(address->classId);
+       if (property->attnum_namespace == InvalidAttrNumber)
+               return InvalidOid;
+
+       /* Currently, we can only handle object types with system caches. */
+       cache = property->oid_catcache_id;
+       Assert(cache != -1);
+
+       /* Fetch tuple from syscache and extract namespace attribute. */
+       tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "cache lookup failed for cache %d oid %u",
+                        cache, address->objectId);
+       oid = DatumGetObjectId(SysCacheGetAttr(cache,
+                                                                                  tuple,
+                                                                                  property->attnum_namespace,
+                                                                                  &isnull));
+       Assert(!isnull);
+       ReleaseSysCache(tuple);
+
+       return oid;
+}
+
+/*
+ * Find ObjectProperty structure by class_id.
+ */
+static ObjectPropertyType *
+get_object_property_data(Oid class_id)
+{
+       int                     index;
+
+       for (index = 0; index < lengthof(ObjectProperty); index++)
+               if (ObjectProperty[index].class_oid == class_id)
+                       return &ObjectProperty[index];
+
+       elog(ERROR, "unrecognized class id: %u", class_id);
+       return NULL;            /* not reached */
+}
index 81fd6581f32da44abc111b83e6a37663a8782d37..4af7aad00b5b8d5d89e99da625096bc5174a7475 100644 (file)
@@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
 
 OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o  \
        collationcmds.o constraint.o conversioncmds.o copy.o \
-       dbcommands.o define.o discard.o explain.o extension.o \
+       dbcommands.o define.o discard.o dropcmds.o explain.o extension.o \
        foreigncmds.o functioncmds.o \
        indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \
        portalcmds.o prepare.o proclang.o \
index a0a0c7d06828fd66acd98baa75e66fc9c31219cb..20aa204403dc280d0503e0ce5670919a4f32b49d 100644 (file)
@@ -144,67 +144,6 @@ DefineCollation(List *names, List *parameters)
        (void) pg_newlocale_from_collation(newoid);
 }
 
-/*
- * DROP COLLATION
- */
-void
-DropCollationsCommand(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       /*
-        * First we identify all the collations, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the collations depends on another. (Not that
-        * that is very likely, but we may as well do this consistently.)
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *name = (List *) lfirst(cell);
-               Oid                     collationOid;
-               HeapTuple       tuple;
-               Form_pg_collation coll;
-               ObjectAddress object;
-
-               collationOid = get_collation_oid(name, drop->missing_ok);
-
-               if (!OidIsValid(collationOid))
-               {
-                       ereport(NOTICE,
-                                       (errmsg("collation \"%s\" does not exist, skipping",
-                                                       NameListToString(name))));
-                       continue;
-               }
-
-               tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(collationOid));
-               if (!HeapTupleIsValid(tuple))
-                       elog(ERROR, "cache lookup failed for collation %u",
-                                collationOid);
-               coll = (Form_pg_collation) GETSTRUCT(tuple);
-
-               /* Permission check: must own collation or its namespace */
-               if (!pg_collation_ownercheck(collationOid, GetUserId()) &&
-                       !pg_namespace_ownercheck(coll->collnamespace, GetUserId()))
-                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
-                                                  NameStr(coll->collname));
-
-               object.classId = CollationRelationId;
-               object.objectId = collationOid;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-
-               ReleaseSysCache(tuple);
-       }
-
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
 /*
  * Rename collation
  */
index cd7ae600ff69bcccb82651e0cf43b8915066f545..7d6063de1a764ba4a82aeb1c0c2ba14b99742f85 100644 (file)
@@ -117,67 +117,6 @@ CreateConversionCommand(CreateConversionStmt *stmt)
                                         from_encoding, to_encoding, funcoid, stmt->def);
 }
 
-/*
- * DROP CONVERSION
- */
-void
-DropConversionsCommand(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       /*
-        * First we identify all the conversions, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the conversions depends on another. (Not that
-        * that is very likely, but we may as well do this consistently.)
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *name = (List *) lfirst(cell);
-               Oid                     conversionOid;
-               HeapTuple       tuple;
-               Form_pg_conversion con;
-               ObjectAddress object;
-
-               conversionOid = get_conversion_oid(name, drop->missing_ok);
-
-               if (!OidIsValid(conversionOid))
-               {
-                       ereport(NOTICE,
-                                       (errmsg("conversion \"%s\" does not exist, skipping",
-                                                       NameListToString(name))));
-                       continue;
-               }
-
-               tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conversionOid));
-               if (!HeapTupleIsValid(tuple))
-                       elog(ERROR, "cache lookup failed for conversion %u",
-                                conversionOid);
-               con = (Form_pg_conversion) GETSTRUCT(tuple);
-
-               /* Permission check: must own conversion or its namespace */
-               if (!pg_conversion_ownercheck(conversionOid, GetUserId()) &&
-                       !pg_namespace_ownercheck(con->connamespace, GetUserId()))
-                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
-                                                  NameStr(con->conname));
-
-               object.classId = ConversionRelationId;
-               object.objectId = conversionOid;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-
-               ReleaseSysCache(tuple);
-       }
-
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
 /*
  * Rename conversion
  */
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
new file mode 100644 (file)
index 0000000..8297730
--- /dev/null
@@ -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)));
+}
index ba1e2c45cd97c89265912d338a98f52bf48ea4b0..c334ca9cf8c5e287669a47702665cedb5b0677a2 100644 (file)
@@ -1563,69 +1563,6 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
        return extensionOid;
 }
 
-
-/*
- *     RemoveExtensions
- *             Implements DROP EXTENSION.
- */
-void
-RemoveExtensions(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       /*
-        * First we identify all the extensions, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the extensions depends on another.
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *names = (List *) lfirst(cell);
-               char       *extensionName;
-               Oid                     extensionId;
-               ObjectAddress object;
-
-               if (list_length(names) != 1)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                        errmsg("extension name cannot be qualified")));
-               extensionName = strVal(linitial(names));
-
-               extensionId = get_extension_oid(extensionName, drop->missing_ok);
-
-               if (!OidIsValid(extensionId))
-               {
-                       ereport(NOTICE,
-                                       (errmsg("extension \"%s\" does not exist, skipping",
-                                                       extensionName)));
-                       continue;
-               }
-
-               /* Permission check: must own extension */
-               if (!pg_extension_ownercheck(extensionId, GetUserId()))
-                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
-                                                  extensionName);
-
-               object.classId = ExtensionRelationId;
-               object.objectId = extensionId;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-       }
-
-       /*
-        * Do the deletions.  Objects contained in the extension(s) are removed by
-        * means of their dependency links to the extensions.
-        */
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
-
 /*
  * Guts of extension deletion.
  *
index 9d1d6535fd9dda989a664b88b8e1fa225f1a18b2..8daa9d0e36bf396317e0c9113c7a372176ce764c 100644 (file)
@@ -146,69 +146,6 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
        SetUserIdAndSecContext(saved_uid, save_sec_context);
 }
 
-
-/*
- *     RemoveSchemas
- *             Implements DROP SCHEMA.
- */
-void
-RemoveSchemas(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       /*
-        * First we identify all the schemas, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the schemas depends on another.
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *names = (List *) lfirst(cell);
-               char       *namespaceName;
-               Oid                     namespaceId;
-               ObjectAddress object;
-
-               if (list_length(names) != 1)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                        errmsg("schema name cannot be qualified")));
-               namespaceName = strVal(linitial(names));
-
-               namespaceId = get_namespace_oid(namespaceName, drop->missing_ok);
-
-               if (!OidIsValid(namespaceId))
-               {
-                       ereport(NOTICE,
-                                       (errmsg("schema \"%s\" does not exist, skipping",
-                                                       namespaceName)));
-                       continue;
-               }
-
-               /* Permission check */
-               if (!pg_namespace_ownercheck(namespaceId, GetUserId()))
-                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
-                                                  namespaceName);
-
-               object.classId = NamespaceRelationId;
-               object.objectId = namespaceId;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-       }
-
-       /*
-        * Do the deletions.  Objects contained in the schema(s) are removed by
-        * means of their dependency links to the schema.
-        */
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
-
 /*
  * Guts of schema deletion.
  */
index 16e6940d131fd1ef83e36d020525143e3387c1e9..5f206d8440a661a4ea5be7830015009191c2166c 100644 (file)
@@ -278,65 +278,6 @@ DefineTSParser(List *names, List *parameters)
        heap_close(prsRel, RowExclusiveLock);
 }
 
-/*
- * DROP TEXT SEARCH PARSER
- */
-void
-RemoveTSParsers(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       if (!superuser())
-               ereport(ERROR,
-                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                                errmsg("must be superuser to drop text search parsers")));
-
-       /*
-        * First we identify all the objects, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the objects depends on another.
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *names = (List *) lfirst(cell);
-               Oid                     prsOid;
-               ObjectAddress object;
-
-               prsOid = get_ts_parser_oid(names, true);
-
-               if (!OidIsValid(prsOid))
-               {
-                       if (!drop->missing_ok)
-                       {
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                                errmsg("text search parser \"%s\" does not exist",
-                                                               NameListToString(names))));
-                       }
-                       else
-                       {
-                               ereport(NOTICE,
-                               (errmsg("text search parser \"%s\" does not exist, skipping",
-                                               NameListToString(names))));
-                       }
-                       continue;
-               }
-
-               object.classId = TSParserRelationId;
-               object.objectId = prsOid;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-       }
-
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
 /*
  * Guts of TS parser deletion.
  */
@@ -730,76 +671,6 @@ AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid)
        return oldNspOid;
 }
 
-/*
- * DROP TEXT SEARCH DICTIONARY
- */
-void
-RemoveTSDictionaries(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       /*
-        * First we identify all the objects, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the objects depends on another.
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *names = (List *) lfirst(cell);
-               Oid                     dictOid;
-               ObjectAddress object;
-               HeapTuple       tup;
-               Oid                     namespaceId;
-
-               dictOid = get_ts_dict_oid(names, true);
-
-               if (!OidIsValid(dictOid))
-               {
-                       if (!drop->missing_ok)
-                       {
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                          errmsg("text search dictionary \"%s\" does not exist",
-                                                         NameListToString(names))));
-                       }
-                       else
-                       {
-                               ereport(NOTICE,
-                                               (errmsg("text search dictionary \"%s\" does not exist, skipping",
-                                                               NameListToString(names))));
-                       }
-                       continue;
-               }
-
-               tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictOid));
-               if (!HeapTupleIsValid(tup))             /* should not happen */
-                       elog(ERROR, "cache lookup failed for text search dictionary %u",
-                                dictOid);
-
-               /* Permission check: must own dictionary or its namespace */
-               namespaceId = ((Form_pg_ts_dict) GETSTRUCT(tup))->dictnamespace;
-               if (!pg_ts_dict_ownercheck(dictOid, GetUserId()) &&
-                       !pg_namespace_ownercheck(namespaceId, GetUserId()))
-                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
-                                                  NameListToString(names));
-
-               object.classId = TSDictionaryRelationId;
-               object.objectId = dictOid;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-
-               ReleaseSysCache(tup);
-       }
-
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
 /*
  * Guts of TS dictionary deletion.
  */
@@ -1262,65 +1133,6 @@ AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid)
        return oldNspOid;
 }
 
-/*
- * DROP TEXT SEARCH TEMPLATE
- */
-void
-RemoveTSTemplates(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       if (!superuser())
-               ereport(ERROR,
-                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                                errmsg("must be superuser to drop text search templates")));
-
-       /*
-        * First we identify all the objects, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the objects depends on another.
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *names = (List *) lfirst(cell);
-               Oid                     tmplOid;
-               ObjectAddress object;
-
-               tmplOid = get_ts_template_oid(names, true);
-
-               if (!OidIsValid(tmplOid))
-               {
-                       if (!drop->missing_ok)
-                       {
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                                errmsg("text search template \"%s\" does not exist",
-                                                               NameListToString(names))));
-                       }
-                       else
-                       {
-                               ereport(NOTICE,
-                                               (errmsg("text search template \"%s\" does not exist, skipping",
-                                                               NameListToString(names))));
-                       }
-                       continue;
-               }
-
-               object.classId = TSTemplateRelationId;
-               object.objectId = tmplOid;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-       }
-
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
 /*
  * Guts of TS template deletion.
  */
@@ -1714,72 +1526,6 @@ AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid)
        return oldNspOid;
 }
 
-/*
- * DROP TEXT SEARCH CONFIGURATION
- */
-void
-RemoveTSConfigurations(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       /*
-        * First we identify all the objects, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the objects depends on another.
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *names = (List *) lfirst(cell);
-               Oid                     cfgOid;
-               Oid                     namespaceId;
-               ObjectAddress object;
-               HeapTuple       tup;
-
-               tup = GetTSConfigTuple(names);
-
-               if (!HeapTupleIsValid(tup))
-               {
-                       if (!drop->missing_ok)
-                       {
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                       errmsg("text search configuration \"%s\" does not exist",
-                                                  NameListToString(names))));
-                       }
-                       else
-                       {
-                               ereport(NOTICE,
-                                               (errmsg("text search configuration \"%s\" does not exist, skipping",
-                                                               NameListToString(names))));
-                       }
-                       continue;
-               }
-
-               /* Permission check: must own configuration or its namespace */
-               cfgOid = HeapTupleGetOid(tup);
-               namespaceId = ((Form_pg_ts_config) GETSTRUCT(tup))->cfgnamespace;
-               if (!pg_ts_config_ownercheck(cfgOid, GetUserId()) &&
-                       !pg_namespace_ownercheck(namespaceId, GetUserId()))
-                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
-                                                  NameListToString(names));
-
-               object.classId = TSConfigRelationId;
-               object.objectId = cfgOid;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-
-               ReleaseSysCache(tup);
-       }
-
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
 /*
  * Guts of TS configuration deletion.
  */
index 7c27f85cdc66a545ed137360ec2eccb72099394c..5069c5759ec60e730a70f98d2145dc78b200e156 100644 (file)
@@ -618,98 +618,6 @@ DefineType(List *names, List *parameters)
        pfree(array_type);
 }
 
-
-/*
- *     RemoveTypes
- *             Implements DROP TYPE and DROP DOMAIN
- *
- * Note: if DOMAIN is specified, we enforce that each type is a domain, but
- * we don't enforce the converse for DROP TYPE
- */
-void
-RemoveTypes(DropStmt *drop)
-{
-       ObjectAddresses *objects;
-       ListCell   *cell;
-
-       /*
-        * First we identify all the types, then we delete them in a single
-        * performMultipleDeletions() call.  This is to avoid unwanted DROP
-        * RESTRICT errors if one of the types depends on another.
-        */
-       objects = new_object_addresses();
-
-       foreach(cell, drop->objects)
-       {
-               List       *names = (List *) lfirst(cell);
-               TypeName   *typename;
-               Oid                     typeoid;
-               HeapTuple       tup;
-               ObjectAddress object;
-               Form_pg_type typ;
-
-               /* Make a TypeName so we can use standard type lookup machinery */
-               typename = makeTypeNameFromNameList(names);
-
-               /* Use LookupTypeName here so that shell types can be removed. */
-               tup = LookupTypeName(NULL, typename, NULL);
-               if (tup == NULL)
-               {
-                       if (!drop->missing_ok)
-                       {
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                                errmsg("type \"%s\" does not exist",
-                                                               TypeNameToString(typename))));
-                       }
-                       else
-                       {
-                               ereport(NOTICE,
-                                               (errmsg("type \"%s\" does not exist, skipping",
-                                                               TypeNameToString(typename))));
-                       }
-                       continue;
-               }
-
-               typeoid = typeTypeId(tup);
-               typ = (Form_pg_type) GETSTRUCT(tup);
-
-               /* Permission check: must own type or its namespace */
-               if (!pg_type_ownercheck(typeoid, GetUserId()) &&
-                       !pg_namespace_ownercheck(typ->typnamespace, GetUserId()))
-                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
-                                                  format_type_be(typeoid));
-
-               if (drop->removeType == OBJECT_DOMAIN)
-               {
-                       /* Check that this is actually a domain */
-                       if (typ->typtype != TYPTYPE_DOMAIN)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                                errmsg("\"%s\" is not a domain",
-                                                               TypeNameToString(typename))));
-               }
-
-               /*
-                * Note: we need no special check for array types here, as the normal
-                * treatment of internal dependencies handles it just fine
-                */
-
-               object.classId = TypeRelationId;
-               object.objectId = typeoid;
-               object.objectSubId = 0;
-
-               add_exact_object_address(&object, objects);
-
-               ReleaseSysCache(tup);
-       }
-
-       performMultipleDeletions(objects, drop->behavior);
-
-       free_object_addresses(objects);
-}
-
-
 /*
  * Guts of type deletion.
  */
index 0749227398b12ebc0e6aedce78c5137b5c1517d1..a74019a0d65a76445952833acc21d194378b346a 100644 (file)
@@ -644,61 +644,18 @@ standard_ProcessUtility(Node *parsetree,
                        break;
 
                case T_DropStmt:
+                       switch (((DropStmt *) parsetree)->removeType)
                        {
-                               DropStmt   *stmt = (DropStmt *) parsetree;
-
-                               switch (stmt->removeType)
-                               {
-                                       case OBJECT_TABLE:
-                                       case OBJECT_SEQUENCE:
-                                       case OBJECT_VIEW:
-                                       case OBJECT_INDEX:
-                                       case OBJECT_FOREIGN_TABLE:
-                                               RemoveRelations(stmt);
-                                               break;
-
-                                       case OBJECT_TYPE:
-                                       case OBJECT_DOMAIN:
-                                               RemoveTypes(stmt);
-                                               break;
-
-                                       case OBJECT_COLLATION:
-                                               DropCollationsCommand(stmt);
-                                               break;
-
-                                       case OBJECT_CONVERSION:
-                                               DropConversionsCommand(stmt);
-                                               break;
-
-                                       case OBJECT_SCHEMA:
-                                               RemoveSchemas(stmt);
-                                               break;
-
-                                       case OBJECT_TSPARSER:
-                                               RemoveTSParsers(stmt);
-                                               break;
-
-                                       case OBJECT_TSDICTIONARY:
-                                               RemoveTSDictionaries(stmt);
-                                               break;
-
-                                       case OBJECT_TSTEMPLATE:
-                                               RemoveTSTemplates(stmt);
-                                               break;
-
-                                       case OBJECT_TSCONFIGURATION:
-                                               RemoveTSConfigurations(stmt);
-                                               break;
-
-                                       case OBJECT_EXTENSION:
-                                               RemoveExtensions(stmt);
-                                               break;
-
-                                       default:
-                                               elog(ERROR, "unrecognized drop object type: %d",
-                                                        (int) stmt->removeType);
-                                               break;
-                               }
+                               case OBJECT_TABLE:
+                               case OBJECT_SEQUENCE:
+                               case OBJECT_VIEW:
+                               case OBJECT_INDEX:
+                               case OBJECT_FOREIGN_TABLE:
+                                       RemoveRelations((DropStmt *) parsetree);
+                                       break;
+                               default:
+                                       RemoveObjects((DropStmt *) parsetree);
+                                       break;
                        }
                        break;
 
index 2da6309054b1fdfe9b1260e1906a23d7c6f9ab74..eddccb880173fd28baa5b2b30fb49ebb007fa2dc 100644 (file)
@@ -35,4 +35,6 @@ extern void check_object_ownership(Oid roleid,
                                           ObjectType objtype, ObjectAddress address,
                                           List *objname, List *objargs, Relation relation);
 
+extern Oid     get_object_namespace(const ObjectAddress *address);
+
 #endif   /* PARSE_OBJECT_H */
index 6dbeb751aa95da5baa3f5ff758a379486e8f7947..ce4727c0f11b1c0a82d7da9a6435d011c8c7bdfa 100644 (file)
@@ -18,7 +18,6 @@
 #include "nodes/parsenodes.h"
 
 extern void DefineCollation(List *names, List *parameters);
-extern void DropCollationsCommand(DropStmt *drop);
 extern void RenameCollation(List *name, const char *newname);
 extern void AlterCollationOwner(List *name, Oid newOwnerId);
 extern void AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId);
index f77023ffe323b15ffe689952e79827e09989b73b..c0e7cd9d712f05cca6b4d336618373026fc12ce5 100644 (file)
@@ -18,7 +18,6 @@
 #include "nodes/parsenodes.h"
 
 extern void CreateConversionCommand(CreateConversionStmt *parsetree);
-extern void DropConversionsCommand(DropStmt *drop);
 extern void RenameConversion(List *name, const char *newname);
 extern void AlterConversionOwner(List *name, Oid newOwnerId);
 extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId);
index 81c515ebed32f942b17ab00795c7d0def4eb8703..64eeb736701f2cd521fc86f7ba9977edd12ac4bb 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "nodes/parsenodes.h"
 
+/* commands/dropcmds.c */
+extern void RemoveObjects(DropStmt *stmt);
 
 /* commands/indexcmds.c */
 extern Oid DefineIndex(RangeVar *heapRelation,
@@ -122,12 +124,10 @@ extern void DefineTSParser(List *names, List *parameters);
 extern void RenameTSParser(List *oldname, const char *newname);
 extern void AlterTSParserNamespace(List *name, const char *newschema);
 extern Oid     AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid);
-extern void RemoveTSParsers(DropStmt *drop);
 extern void RemoveTSParserById(Oid prsId);
 
 extern void DefineTSDictionary(List *names, List *parameters);
 extern void RenameTSDictionary(List *oldname, const char *newname);
-extern void RemoveTSDictionaries(DropStmt *drop);
 extern void RemoveTSDictionaryById(Oid dictId);
 extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
 extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
@@ -138,12 +138,10 @@ extern void DefineTSTemplate(List *names, List *parameters);
 extern void RenameTSTemplate(List *oldname, const char *newname);
 extern void AlterTSTemplateNamespace(List *name, const char *newschema);
 extern Oid     AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid);
-extern void RemoveTSTemplates(DropStmt *stmt);
 extern void RemoveTSTemplateById(Oid tmplId);
 
 extern void DefineTSConfiguration(List *names, List *parameters);
 extern void RenameTSConfiguration(List *oldname, const char *newname);
-extern void RemoveTSConfigurations(DropStmt *stmt);
 extern void RemoveTSConfigurationById(Oid cfgId);
 extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
 extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
index 2792c6dd49f7f5cfac3883d3b3afc42674732688..f22ac80735a93fdb9ef60ddd174172c654045f6f 100644 (file)
@@ -29,7 +29,6 @@ extern Oid    CurrentExtensionObject;
 
 extern void CreateExtension(CreateExtensionStmt *stmt);
 
-extern void RemoveExtensions(DropStmt *stmt);
 extern void RemoveExtensionById(Oid extId);
 
 extern Oid InsertExtensionTuple(const char *extName, Oid extOwner,
index a9f8f6cb5d1ce9e405b3cab22e1e7b291ed4234d..ec8d8957d99e3b3667a708a546b2d33b182ea2d8 100644 (file)
@@ -20,7 +20,6 @@
 extern void CreateSchemaCommand(CreateSchemaStmt *parsetree,
                                        const char *queryString);
 
-extern void RemoveSchemas(DropStmt *drop);
 extern void RemoveSchemaById(Oid schemaOid);
 
 extern void RenameSchema(const char *oldname, const char *newname);
index 23726fb0fb28a85bea85327ae87c6b491e88a221..429a964f913fa2dc145bd384a036d10419d49cca 100644 (file)
@@ -20,7 +20,6 @@
 #define DEFAULT_TYPDELIM               ','
 
 extern void DefineType(List *names, List *parameters);
-extern void RemoveTypes(DropStmt *drop);
 extern void RemoveTypeById(Oid typeOid);
 extern void DefineDomain(CreateDomainStmt *stmt);
 extern void DefineEnum(CreateEnumStmt *stmt);