Commit df18c51f authored by Alvaro Herrera's avatar Alvaro Herrera

Fix DROP OWNED BY to correctly consider the implicitly-deleted objects list for

each object to be deleted, instead of the previous hack that just skipped
INTERNAL dependencies, which didn't really work.  Per report from Tom Lane.

To do this, introduce a new performMultipleDeletions entry point in
dependency.c to delete multiple objects at once.  The dependency code then has
the responsability of tracking INTERNAL and AUTO dependencies as needed.

Along the way, change ObjectAddresses so that we can allocate an ObjectAddress
list from outside dependency.c and not have to export the internal
representation.
parent 4e23d6e0
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.12 2006/07/14 14:52:18 momjian Exp $ * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.13 2006/08/20 21:56:16 alvherre Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1061,6 +1061,9 @@ shdepDropOwned(List *roleids, DropBehavior behavior) ...@@ -1061,6 +1061,9 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
{ {
Relation sdepRel; Relation sdepRel;
ListCell *cell; ListCell *cell;
ObjectAddresses *deleteobjs;
deleteobjs = new_object_addresses();
sdepRel = heap_open(SharedDependRelationId, AccessExclusiveLock); sdepRel = heap_open(SharedDependRelationId, AccessExclusiveLock);
...@@ -1105,6 +1108,9 @@ shdepDropOwned(List *roleids, DropBehavior behavior) ...@@ -1105,6 +1108,9 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
while ((tuple = systable_getnext(scan)) != NULL) while ((tuple = systable_getnext(scan)) != NULL)
{ {
ObjectAddress obj;
GrantObjectType objtype;
InternalGrant istmt;
Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple); Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
/* We only operate on objects on the current database */ /* We only operate on objects on the current database */
...@@ -1113,11 +1119,7 @@ shdepDropOwned(List *roleids, DropBehavior behavior) ...@@ -1113,11 +1119,7 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
switch (sdepForm->deptype) switch (sdepForm->deptype)
{ {
ObjectAddress obj; /* Shouldn't happen */
GrantObjectType objtype;
InternalGrant istmt;
/* Shouldn't happen */
case SHARED_DEPENDENCY_PIN: case SHARED_DEPENDENCY_PIN:
case SHARED_DEPENDENCY_INVALID: case SHARED_DEPENDENCY_INVALID:
elog(ERROR, "unexpected dependency type"); elog(ERROR, "unexpected dependency type");
...@@ -1126,25 +1128,25 @@ shdepDropOwned(List *roleids, DropBehavior behavior) ...@@ -1126,25 +1128,25 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
switch (sdepForm->classid) switch (sdepForm->classid)
{ {
case RelationRelationId: case RelationRelationId:
{ {
/* is it a sequence or non-sequence? */ /* is it a sequence or non-sequence? */
Form_pg_class pg_class_tuple; Form_pg_class pg_class_tuple;
HeapTuple tuple; HeapTuple tuple;
tuple = SearchSysCache(RELOID, tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(sdepForm->objid), ObjectIdGetDatum(sdepForm->objid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", elog(ERROR, "cache lookup failed for relation %u",
sdepForm->objid); sdepForm->objid);
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple); pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
if (pg_class_tuple->relkind == RELKIND_SEQUENCE) if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
istmt.objtype = ACL_OBJECT_SEQUENCE; istmt.objtype = ACL_OBJECT_SEQUENCE;
else else
istmt.objtype = ACL_OBJECT_RELATION; istmt.objtype = ACL_OBJECT_RELATION;
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
}
break; break;
}
case DatabaseRelationId: case DatabaseRelationId:
istmt.objtype = ACL_OBJECT_DATABASE; istmt.objtype = ACL_OBJECT_DATABASE;
break; break;
...@@ -1178,20 +1180,12 @@ shdepDropOwned(List *roleids, DropBehavior behavior) ...@@ -1178,20 +1180,12 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
ExecGrantStmt_oids(&istmt); ExecGrantStmt_oids(&istmt);
break; break;
case SHARED_DEPENDENCY_OWNER: case SHARED_DEPENDENCY_OWNER:
/* Save it for later deleting it */
/*
* If there's a regular (non-shared) dependency on this
* object marked with DEPENDENCY_INTERNAL, skip this
* object. We will drop the referencer object instead.
*/
if (objectIsInternalDependency(sdepForm->classid, sdepForm->objid))
continue;
/* Drop the object */
obj.classId = sdepForm->classid; obj.classId = sdepForm->classid;
obj.objectId = sdepForm->objid; obj.objectId = sdepForm->objid;
obj.objectSubId = 0; obj.objectSubId = 0;
performDeletion(&obj, behavior);
add_exact_object_address(&obj, deleteobjs);
break; break;
} }
} }
...@@ -1199,7 +1193,12 @@ shdepDropOwned(List *roleids, DropBehavior behavior) ...@@ -1199,7 +1193,12 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
systable_endscan(scan); systable_endscan(scan);
} }
/* the dependency mechanism does the actual work */
performMultipleDeletions(deleteobjs, behavior);
heap_close(sdepRel, AccessExclusiveLock); heap_close(sdepRel, AccessExclusiveLock);
free_object_addresses(deleteobjs);
} }
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.25 2006/06/27 18:35:05 momjian Exp $ * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.26 2006/08/20 21:56:16 alvherre Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -112,6 +112,8 @@ typedef struct ObjectAddress ...@@ -112,6 +112,8 @@ typedef struct ObjectAddress
int32 objectSubId; /* Subitem within the object (column of table) */ int32 objectSubId; /* Subitem within the object (column of table) */
} ObjectAddress; } ObjectAddress;
/* expansible list of ObjectAddresses */
typedef struct ObjectAddresses ObjectAddresses;
/* /*
* This enum covers all system catalogs whose OIDs can appear in * This enum covers all system catalogs whose OIDs can appear in
...@@ -144,6 +146,9 @@ typedef enum ObjectClass ...@@ -144,6 +146,9 @@ typedef enum ObjectClass
extern void performDeletion(const ObjectAddress *object, extern void performDeletion(const ObjectAddress *object,
DropBehavior behavior); DropBehavior behavior);
extern void performMultipleDeletions(const ObjectAddresses *objects,
DropBehavior behavior);
extern void deleteWhatDependsOn(const ObjectAddress *object, extern void deleteWhatDependsOn(const ObjectAddress *object,
bool showNotices); bool showNotices);
...@@ -160,6 +165,16 @@ extern ObjectClass getObjectClass(const ObjectAddress *object); ...@@ -160,6 +165,16 @@ extern ObjectClass getObjectClass(const ObjectAddress *object);
extern char *getObjectDescription(const ObjectAddress *object); extern char *getObjectDescription(const ObjectAddress *object);
extern ObjectAddresses *new_object_addresses(void);
extern void add_exact_object_address(const ObjectAddress *object,
ObjectAddresses *addrs);
extern bool object_address_present(const ObjectAddress *object,
ObjectAddresses *addrs);
extern void free_object_addresses(ObjectAddresses *addrs);
/* in pg_depend.c */ /* in pg_depend.c */
extern void recordDependencyOn(const ObjectAddress *depender, extern void recordDependencyOn(const ObjectAddress *depender,
......
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