Tom Lane wrote:

> What I was thinking of was
> 
>       find all target objects using pg_shdepend, make an
>               ObjectAddresses list of them
> 
>       for (each item of list)
>       {
>               if (already deleted)
>                       continue;
>               if (implicit dependency of some later list item)
>                       continue;
>               pass item to performDeletion, with entire list
>                       as oktodelete context
>       }

Ok, this patch implements more or less this idea; except that instead of
checking the list of implicit dependencies for later objects, we iterate
twice on the list of objects to delete, and create a list of implicit
dependencies on all of them the first time, and delete those not on that
list the second time.

Regression tests pass.  This patch makes the following example work as
expected.  Note that the first "drop owned" is stopped by the FK on tt3;
by adding the cascade, it drops the foreign key.

Let me know if it fixes your problem, and I'll commit it early tomorrow.
(Or you can do it if you're in a hurry ...)


create user foo;
create user bar;

\c - bar
create table tt3 (f1 int);

\c - foo
create table tt1 (f1 int);
create table tt2 (f1 int primary key);
alter table tt1 add foreign key (f1) references tt2;
grant references on table tt2 to bar;

\c - bar
alter table tt3 add foreign key (f1) references tt2;

\c - foo
drop owned by foo;
drop owned by foo cascade;



-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Index: src/backend/catalog/dependency.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/dependency.c,v
retrieving revision 1.58
diff -c -p -r1.58 dependency.c
*** src/backend/catalog/dependency.c    14 Jul 2006 14:52:17 -0000      1.58
--- src/backend/catalog/dependency.c    20 Aug 2006 04:46:38 -0000
***************
*** 56,69 ****
  #include "utils/syscache.h"
  
  
- /* expansible list of ObjectAddresses */
- typedef struct
- {
-       ObjectAddress *refs;            /* => palloc'd array */
-       int                     numrefs;                /* current number of 
references */
-       int                     maxrefs;                /* current size of 
palloc'd array */
- } ObjectAddresses;
- 
  /* for find_expr_references_walker */
  typedef struct
  {
--- 56,61 ----
*************** static const Oid object_classes[MAX_OCLA
*** 92,106 ****
  };
  
  
- static void findAutoDeletableObjects(const ObjectAddress *object,
-                                                ObjectAddresses *oktodelete,
-                                                Relation depRel);
  static bool recursiveDeletion(const ObjectAddress *object,
                                  DropBehavior behavior,
                                  int msglevel,
                                  const ObjectAddress *callingObject,
                                  ObjectAddresses *oktodelete,
!                                 Relation depRel);
  static bool deleteDependentObjects(const ObjectAddress *object,
                                           const char *objDescription,
                                           DropBehavior behavior,
--- 84,96 ----
  };
  
  
  static bool recursiveDeletion(const ObjectAddress *object,
                                  DropBehavior behavior,
                                  int msglevel,
                                  const ObjectAddress *callingObject,
                                  ObjectAddresses *oktodelete,
!                                 Relation depRel,
!                                 ObjectAddresses *alreadyDeleted);
  static bool deleteDependentObjects(const ObjectAddress *object,
                                           const char *objDescription,
                                           DropBehavior behavior,
*************** static bool find_expr_references_walker(
*** 112,125 ****
                                                        
find_expr_references_context *context);
  static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
  static int    object_address_comparator(const void *a, const void *b);
- static void init_object_addresses(ObjectAddresses *addrs);
  static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
                                   ObjectAddresses *addrs);
- static void add_exact_object_address(const ObjectAddress *object,
-                                                ObjectAddresses *addrs);
- static bool object_address_present(const ObjectAddress *object,
-                                          ObjectAddresses *addrs);
- static void term_object_addresses(ObjectAddresses *addrs);
  static void getRelationDescription(StringInfo buffer, Oid relid);
  
  
--- 102,109 ----
*************** performDeletion(const ObjectAddress *obj
*** 161,170 ****
         */
        init_object_addresses(&oktodelete);
  
!       findAutoDeletableObjects(object, &oktodelete, depRel);
  
        if (!recursiveDeletion(object, behavior, NOTICE,
!                                                  NULL, &oktodelete, depRel))
                ereport(ERROR,
                                (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
                                 errmsg("cannot drop %s because other objects 
depend on it",
--- 145,154 ----
         */
        init_object_addresses(&oktodelete);
  
!       findAutoDeletableObjects(object, &oktodelete, depRel, true);
  
        if (!recursiveDeletion(object, behavior, NOTICE,
!                                                  NULL, &oktodelete, depRel, 
NULL))
                ereport(ERROR,
                                (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
                                 errmsg("cannot drop %s because other objects 
depend on it",
*************** performDeletion(const ObjectAddress *obj
*** 178,183 ****
--- 162,214 ----
        pfree(objDescription);
  }
  
+ /*
+  * As above, but the oktodelete list may have already filled with some
+  * objects.  Also, the deleted objects are saved in the alreadyDeleted
+  * list.
+  */
+ void
+ performDeletionWithList(const ObjectAddress *object,
+                                               ObjectAddresses *oktodelete,
+                                               DropBehavior behavior,
+                                               ObjectAddresses *alreadyDeleted)
+ {
+       char       *objDescription;
+       Relation        depRel;
+ 
+       /*
+        * Get object description for possible use in failure message. Must do
+        * this before deleting it ...
+        */
+       objDescription = getObjectDescription(object);
+ 
+       /*
+        * We save some cycles by opening pg_depend just once and passing the
+        * Relation pointer down to all the recursive deletion steps.
+        */
+       depRel = heap_open(DependRelationId, RowExclusiveLock);
+ 
+       /*
+        * Construct a list of objects that are reachable by AUTO or INTERNAL
+        * dependencies from the target object.  These should be deleted 
silently,
+        * even if the actual deletion pass first reaches one of them via a
+        * non-auto dependency.
+        */
+       findAutoDeletableObjects(object, oktodelete, depRel, true);
+ 
+       if (!recursiveDeletion(object, behavior, NOTICE,
+                                                  NULL, oktodelete, depRel, 
alreadyDeleted))
+               ereport(ERROR,
+                               (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                                errmsg("cannot drop %s because other objects 
depend on it",
+                                               objDescription),
+               errhint("Use DROP ... CASCADE to drop the dependent objects 
too.")));
+ 
+       heap_close(depRel, RowExclusiveLock);
+ 
+       pfree(objDescription);
+ }
+ 
  
  /*
   * deleteWhatDependsOn: attempt to drop everything that depends on the
*************** deleteWhatDependsOn(const ObjectAddress 
*** 215,221 ****
         */
        init_object_addresses(&oktodelete);
  
!       findAutoDeletableObjects(object, &oktodelete, depRel);
  
        /*
         * Now invoke only step 2 of recursiveDeletion: just recurse to the 
stuff
--- 246,252 ----
         */
        init_object_addresses(&oktodelete);
  
!       findAutoDeletableObjects(object, &oktodelete, depRel, true);
  
        /*
         * Now invoke only step 2 of recursiveDeletion: just recurse to the 
stuff
*************** deleteWhatDependsOn(const ObjectAddress 
*** 246,260 ****
  /*
   * findAutoDeletableObjects: find all objects that are reachable by AUTO or
   * INTERNAL dependency paths from the given object.  Add them all to the
!  * oktodelete list.  Note that the originally given object will also be
!  * added to the list.
   *
   * depRel is the already-open pg_depend relation.
   */
! static void
  findAutoDeletableObjects(const ObjectAddress *object,
                                                 ObjectAddresses *oktodelete,
!                                                Relation depRel)
  {
        ScanKeyData key[3];
        int                     nkeys;
--- 277,291 ----
  /*
   * findAutoDeletableObjects: find all objects that are reachable by AUTO or
   * INTERNAL dependency paths from the given object.  Add them all to the
!  * oktodelete list.  If addself is true, the originally given object will also
!  * be added to the list.
   *
   * depRel is the already-open pg_depend relation.
   */
! void
  findAutoDeletableObjects(const ObjectAddress *object,
                                                 ObjectAddresses *oktodelete,
!                                                Relation depRel, bool addself)
  {
        ScanKeyData key[3];
        int                     nkeys;
*************** findAutoDeletableObjects(const ObjectAdd
*** 269,275 ****
         */
        if (object_address_present(object, oktodelete))
                return;
!       add_exact_object_address(object, oktodelete);
  
        /*
         * Scan pg_depend records that link to this object, showing the things
--- 300,307 ----
         */
        if (object_address_present(object, oktodelete))
                return;
!       if (addself)
!               add_exact_object_address(object, oktodelete);
  
        /*
         * Scan pg_depend records that link to this object, showing the things
*************** findAutoDeletableObjects(const ObjectAdd
*** 316,322 ****
                                otherObject.classId = foundDep->classid;
                                otherObject.objectId = foundDep->objid;
                                otherObject.objectSubId = foundDep->objsubid;
!                               findAutoDeletableObjects(&otherObject, 
oktodelete, depRel);
                                break;
                        case DEPENDENCY_PIN:
  
--- 348,354 ----
                                otherObject.classId = foundDep->classid;
                                otherObject.objectId = foundDep->objid;
                                otherObject.objectSubId = foundDep->objsubid;
!                               findAutoDeletableObjects(&otherObject, 
oktodelete, depRel, true);
                                break;
                        case DEPENDENCY_PIN:
  
*************** recursiveDeletion(const ObjectAddress *o
*** 387,393 ****
                                  int msglevel,
                                  const ObjectAddress *callingObject,
                                  ObjectAddresses *oktodelete,
!                                 Relation depRel)
  {
        bool            ok = true;
        char       *objDescription;
--- 419,426 ----
                                  int msglevel,
                                  const ObjectAddress *callingObject,
                                  ObjectAddresses *oktodelete,
!                                 Relation depRel,
!                                 ObjectAddresses *alreadyDeleted)
  {
        bool            ok = true;
        char       *objDescription;
*************** recursiveDeletion(const ObjectAddress *o
*** 553,559 ****
                                                        
getObjectDescription(&owningObject))));
  
                if (!recursiveDeletion(&owningObject, behavior, msglevel,
!                                                          object, oktodelete, 
depRel))
                        ok = false;
  
                pfree(objDescription);
--- 586,592 ----
                                                        
getObjectDescription(&owningObject))));
  
                if (!recursiveDeletion(&owningObject, behavior, msglevel,
!                                                          object, oktodelete, 
depRel, alreadyDeleted))
                        ok = false;
  
                pfree(objDescription);
*************** recursiveDeletion(const ObjectAddress *o
*** 579,587 ****
         */
  
        /*
!        * Step 3: delete the object itself.
         */
        doDeletion(object);
  
        /*
         * Delete any comments associated with this object.  (This is a 
convenient
--- 612,626 ----
         */
  
        /*
!        * Step 3: delete the object itself, and save it to the list of
!        * deleted objects if appropiate.
         */
        doDeletion(object);
+       if (alreadyDeleted != NULL)
+       {
+               if (!object_address_present(object, alreadyDeleted))
+                       add_exact_object_address(object, alreadyDeleted);
+       }
  
        /*
         * Delete any comments associated with this object.  (This is a 
convenient
*************** deleteDependentObjects(const ObjectAddre
*** 712,718 ****
                                                                        
getObjectDescription(&otherObject))));
  
                                if (!recursiveDeletion(&otherObject, behavior, 
msglevel,
!                                                                          
object, oktodelete, depRel))
                                        ok = false;
                                break;
                        case DEPENDENCY_AUTO:
--- 751,757 ----
                                                                        
getObjectDescription(&otherObject))));
  
                                if (!recursiveDeletion(&otherObject, behavior, 
msglevel,
!                                                                          
object, oktodelete, depRel, NULL))
                                        ok = false;
                                break;
                        case DEPENDENCY_AUTO:
*************** deleteDependentObjects(const ObjectAddre
*** 728,734 ****
                                                                
getObjectDescription(&otherObject))));
  
                                if (!recursiveDeletion(&otherObject, behavior, 
msglevel,
!                                                                          
object, oktodelete, depRel))
                                        ok = false;
                                break;
                        case DEPENDENCY_PIN:
--- 767,773 ----
                                                                
getObjectDescription(&otherObject))));
  
                                if (!recursiveDeletion(&otherObject, behavior, 
msglevel,
!                                                                          
object, oktodelete, depRel, NULL))
                                        ok = false;
                                break;
                        case DEPENDENCY_PIN:
*************** object_address_comparator(const void *a,
*** 1334,1340 ****
   *
   * init_object_addresses: initialize an ObjectAddresses array.
   */
! static void
  init_object_addresses(ObjectAddresses *addrs)
  {
        /* Initialize array to empty */
--- 1373,1379 ----
   *
   * init_object_addresses: initialize an ObjectAddresses array.
   */
! void
  init_object_addresses(ObjectAddresses *addrs)
  {
        /* Initialize array to empty */
*************** add_object_address(ObjectClass oclass, O
*** 1376,1382 ****
   *
   * As above, but specify entry exactly.
   */
! static void
  add_exact_object_address(const ObjectAddress *object,
                                                 ObjectAddresses *addrs)
  {
--- 1415,1421 ----
   *
   * As above, but specify entry exactly.
   */
! void
  add_exact_object_address(const ObjectAddress *object,
                                                 ObjectAddresses *addrs)
  {
*************** add_exact_object_address(const ObjectAdd
*** 1400,1406 ****
   *
   * We return "true" if object is a subobject of something in the array, too.
   */
! static bool
  object_address_present(const ObjectAddress *object,
                                           ObjectAddresses *addrs)
  {
--- 1439,1445 ----
   *
   * We return "true" if object is a subobject of something in the array, too.
   */
! bool
  object_address_present(const ObjectAddress *object,
                                           ObjectAddresses *addrs)
  {
*************** object_address_present(const ObjectAddre
*** 1425,1431 ****
  /*
   * Clean up when done with an ObjectAddresses array.
   */
! static void
  term_object_addresses(ObjectAddresses *addrs)
  {
        pfree(addrs->refs);
--- 1464,1470 ----
  /*
   * Clean up when done with an ObjectAddresses array.
   */
! void
  term_object_addresses(ObjectAddresses *addrs)
  {
        pfree(addrs->refs);
Index: src/backend/catalog/pg_shdepend.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/pg_shdepend.c,v
retrieving revision 1.12
diff -c -p -r1.12 pg_shdepend.c
*** src/backend/catalog/pg_shdepend.c   14 Jul 2006 14:52:18 -0000      1.12
--- src/backend/catalog/pg_shdepend.c   20 Aug 2006 04:40:13 -0000
***************
*** 22,27 ****
--- 22,28 ----
  #include "catalog/pg_authid.h"
  #include "catalog/pg_conversion.h"
  #include "catalog/pg_database.h"
+ #include "catalog/pg_depend.h"
  #include "catalog/pg_language.h"
  #include "catalog/pg_namespace.h"
  #include "catalog/pg_operator.h"
*************** void
*** 1060,1068 ****
--- 1061,1079 ----
  shdepDropOwned(List *roleids, DropBehavior behavior)
  {
        Relation        sdepRel;
+       Relation        depRel;
        ListCell   *cell;
+       int                     i;
+       ObjectAddresses deleteobjs;
+       ObjectAddresses implicitobjs;
+       ObjectAddresses alreadyDeleted;
+ 
+       init_object_addresses(&deleteobjs);
+       init_object_addresses(&implicitobjs);
+       init_object_addresses(&alreadyDeleted);
  
        sdepRel = heap_open(SharedDependRelationId, AccessExclusiveLock);
+       depRel = heap_open(DependRelationId, RowExclusiveLock);
  
        /*
         * For each role, find the dependent objects and drop them using the
*************** shdepDropOwned(List *roleids, DropBehavi
*** 1086,1094 ****
  
                        ereport(ERROR,
                                        
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
!                                  errmsg("cannot drop objects owned by %s 
because they are "
!                                                 "required by the database 
system",
!                                                 getObjectDescription(&obj))));
                }
  
                ScanKeyInit(&key[0],
--- 1097,1105 ----
  
                        ereport(ERROR,
                                        
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
!                                        errmsg("cannot drop objects owned by 
%s because they are "
!                                                       "required by the 
database system",
!                                                       
getObjectDescription(&obj))));
                }
  
                ScanKeyInit(&key[0],
*************** shdepDropOwned(List *roleids, DropBehavi
*** 1105,1110 ****
--- 1116,1124 ----
  
                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 */
*************** shdepDropOwned(List *roleids, DropBehavi
*** 1113,1123 ****
  
                        switch (sdepForm->deptype)
                        {
!                                       ObjectAddress obj;
!                                       GrantObjectType objtype;
!                                       InternalGrant istmt;
! 
!                                       /* Shouldn't happen */
                                case SHARED_DEPENDENCY_PIN:
                                case SHARED_DEPENDENCY_INVALID:
                                        elog(ERROR, "unexpected dependency 
type");
--- 1127,1133 ----
  
                        switch (sdepForm->deptype)
                        {
!                               /* Shouldn't happen */
                                case SHARED_DEPENDENCY_PIN:
                                case SHARED_DEPENDENCY_INVALID:
                                        elog(ERROR, "unexpected dependency 
type");
*************** shdepDropOwned(List *roleids, DropBehavi
*** 1126,1150 ****
                                        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);
!                                                       break;
!                                               }
                                                case DatabaseRelationId:
                                                        istmt.objtype = 
ACL_OBJECT_DATABASE;
                                                        break;
--- 1136,1160 ----
                                        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);
!                                                               break;
!                                                       }
                                                case DatabaseRelationId:
                                                        istmt.objtype = 
ACL_OBJECT_DATABASE;
                                                        break;
*************** shdepDropOwned(List *roleids, DropBehavi
*** 1178,1197 ****
                                        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 */
                                        obj.classId = sdepForm->classid;
                                        obj.objectId = sdepForm->objid;
                                        obj.objectSubId = 0;
!                                       performDeletion(&obj, behavior);
                                        break;
                        }
                }
--- 1188,1199 ----
                                        ExecGrantStmt_oids(&istmt);
                                        break;
                                case SHARED_DEPENDENCY_OWNER:
!                                       /* Save it for later deleting it */
                                        obj.classId = sdepForm->classid;
                                        obj.objectId = sdepForm->objid;
                                        obj.objectSubId = 0;
! 
!                                       add_exact_object_address(&obj, 
&deleteobjs);
                                        break;
                        }
                }
*************** shdepDropOwned(List *roleids, DropBehavi
*** 1199,1205 ****
--- 1201,1265 ----
                systable_endscan(scan);
        }
  
+       /*
+        * Get the list of all objects that would be deleted after deleting the
+        * whole "deleteobjs" list.  We do this by creating a list of all
+        * implicit (INTERNAL and AUTO) dependencies for each object we
+        * collected above.  Note that we must exclude the objects themselves
+        * from this list!
+        */
+       for (i = 0; i < deleteobjs.numrefs; i++)
+       {
+               ObjectAddress obj = deleteobjs.refs[i];
+ 
+               /*
+                * if it's in the implicit list, we don't need to delete it
+                * explicitly nor follow the dependencies, because that was
+                * already done in a previous iteration.
+                */
+               if (object_address_present(&obj, &implicitobjs))
+                       continue;
+ 
+               /*
+                * Add the objects dependent on this one to the global list of
+                * implicit objects.
+                */
+               findAutoDeletableObjects(&obj, &implicitobjs, depRel, false);
+       }
+ 
+       /*
+        * Do the deletion.  On each iteration, skip deleting objects that were
+        * already deleted, and those that will be deleted in the future
+        * because of being in the implicit list.
+        */
+       for (i = 0; i < deleteobjs.numrefs; i++)
+       {
+               ObjectAddress obj = deleteobjs.refs[i];
+ 
+               /*
+                * Skip this object if it was already deleted in a previous
+                * iteration
+                */
+               if (object_address_present(&obj, &alreadyDeleted))
+                       continue;
+ 
+               /*
+                * Skip this object if it's also present in the list of implicit
+                * objects -- it will be deleted later.
+                */
+               if (object_address_present(&obj, &implicitobjs))
+                       continue;
+ 
+               /* delete the objects that remain */
+               performDeletionWithList(&obj, &implicitobjs, behavior, 
&alreadyDeleted);
+       }
+ 
        heap_close(sdepRel, AccessExclusiveLock);
+       heap_close(depRel, RowExclusiveLock);
+ 
+       term_object_addresses(&deleteobjs);
+       term_object_addresses(&implicitobjs);
+       term_object_addresses(&alreadyDeleted);
  }
  
  /*
Index: src/include/catalog/dependency.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/dependency.h,v
retrieving revision 1.25
diff -c -p -r1.25 dependency.h
*** src/include/catalog/dependency.h    27 Jun 2006 18:35:05 -0000      1.25
--- src/include/catalog/dependency.h    20 Aug 2006 03:54:36 -0000
***************
*** 15,20 ****
--- 15,21 ----
  #define DEPENDENCY_H
  
  #include "nodes/parsenodes.h" /* for DropBehavior */
+ #include "utils/rel.h"
  
  
  /*----------
*************** typedef struct ObjectAddress
*** 112,117 ****
--- 113,126 ----
        int32           objectSubId;    /* Subitem within the object (column of 
table) */
  } ObjectAddress;
  
+ /* expansible list of ObjectAddresses */
+ typedef struct ObjectAddresses
+ {
+       ObjectAddress *refs;            /* => palloc'd array */
+       int                     numrefs;                /* current number of 
references */
+       int                     maxrefs;                /* current size of 
palloc'd array */
+ } ObjectAddresses;
+ 
  
  /*
   * This enum covers all system catalogs whose OIDs can appear in
*************** typedef enum ObjectClass
*** 141,149 ****
--- 150,167 ----
  
  /* in dependency.c */
  
+ extern void findAutoDeletableObjects(const ObjectAddress *object,
+                                                ObjectAddresses *oktodelete,
+                                                Relation depRel, bool addself);
+ 
  extern void performDeletion(const ObjectAddress *object,
                                DropBehavior behavior);
  
+ extern void performDeletionWithList(const ObjectAddress *object,
+                                               ObjectAddresses *oktodelete,
+                                               DropBehavior behavior,
+                                               ObjectAddresses 
*alreadyDeleted);
+ 
  extern void deleteWhatDependsOn(const ObjectAddress *object,
                                        bool showNotices);
  
*************** extern ObjectClass getObjectClass(const 
*** 160,165 ****
--- 178,193 ----
  
  extern char *getObjectDescription(const ObjectAddress *object);
  
+ extern void init_object_addresses(ObjectAddresses *addrs);
+ 
+ extern void add_exact_object_address(const ObjectAddress *object,
+                                                ObjectAddresses *addrs);
+ 
+ extern bool object_address_present(const ObjectAddress *object,
+                                          ObjectAddresses *addrs);
+ 
+ extern void term_object_addresses(ObjectAddresses *addrs);
+ 
  /* in pg_depend.c */
  
  extern void recordDependencyOn(const ObjectAddress *depender,
---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to