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 @@
*
*
* 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)
{
Relation sdepRel;
ListCell *cell;
ObjectAddresses *deleteobjs;
deleteobjs = new_object_addresses();
sdepRel = heap_open(SharedDependRelationId, AccessExclusiveLock);
......@@ -1105,6 +1108,9 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
while ((tuple = systable_getnext(scan)) != NULL)
{
ObjectAddress obj;
GrantObjectType objtype;
InternalGrant istmt;
Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
/* We only operate on objects on the current database */
......@@ -1113,11 +1119,7 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
switch (sdepForm->deptype)
{
ObjectAddress obj;
GrantObjectType objtype;
InternalGrant istmt;
/* Shouldn't happen */
/* Shouldn't happen */
case SHARED_DEPENDENCY_PIN:
case SHARED_DEPENDENCY_INVALID:
elog(ERROR, "unexpected dependency type");
......@@ -1126,25 +1128,25 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
switch (sdepForm->classid)
{
case RelationRelationId:
{
/* is it a sequence or non-sequence? */
Form_pg_class pg_class_tuple;
HeapTuple tuple;
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(sdepForm->objid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u",
sdepForm->objid);
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
istmt.objtype = ACL_OBJECT_SEQUENCE;
else
istmt.objtype = ACL_OBJECT_RELATION;
ReleaseSysCache(tuple);
{
/* is it a sequence or non-sequence? */
Form_pg_class pg_class_tuple;
HeapTuple tuple;
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(sdepForm->objid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u",
sdepForm->objid);
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
istmt.objtype = ACL_OBJECT_SEQUENCE;
else
istmt.objtype = ACL_OBJECT_RELATION;
ReleaseSysCache(tuple);
}
break;
}
case DatabaseRelationId:
istmt.objtype = ACL_OBJECT_DATABASE;
break;
......@@ -1178,20 +1180,12 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
ExecGrantStmt_oids(&istmt);
break;
case SHARED_DEPENDENCY_OWNER:
/*
* 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 */
/* Save it for later deleting it */
obj.classId = sdepForm->classid;
obj.objectId = sdepForm->objid;
obj.objectSubId = 0;
performDeletion(&obj, behavior);
add_exact_object_address(&obj, deleteobjs);
break;
}
}
......@@ -1199,7 +1193,12 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
systable_endscan(scan);
}
/* the dependency mechanism does the actual work */
performMultipleDeletions(deleteobjs, behavior);
heap_close(sdepRel, AccessExclusiveLock);
free_object_addresses(deleteobjs);
}
/*
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* 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
int32 objectSubId; /* Subitem within the object (column of table) */
} ObjectAddress;
/* expansible list of ObjectAddresses */
typedef struct ObjectAddresses ObjectAddresses;
/*
* This enum covers all system catalogs whose OIDs can appear in
......@@ -144,6 +146,9 @@ typedef enum ObjectClass
extern void performDeletion(const ObjectAddress *object,
DropBehavior behavior);
extern void performMultipleDeletions(const ObjectAddresses *objects,
DropBehavior behavior);
extern void deleteWhatDependsOn(const ObjectAddress *object,
bool showNotices);
......@@ -160,6 +165,16 @@ extern ObjectClass getObjectClass(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 */
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