]> granicus.if.org Git - postgresql/commitdiff
Fix an oversight in the original implementation of performMultipleDeletions():
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 11 Jul 2008 16:08:50 +0000 (16:08 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 11 Jul 2008 16:08:50 +0000 (16:08 +0000)
the alreadyDeleted list has to be passed down through
deleteDependentObjects(), else objects that are deleted via auto/internal
dependencies don't get reported back up to performMultipleDeletions().
Depending on the visitation order, this could cause the code to try to delete
an already-deleted object, leading to strange errors in DROP OWNED (typically
"cache lookup failed for relation NNNNN" or similar).  Per bug #4289.

Patch for back branches only.  This code has recently been rewritten in HEAD,
and doesn't have this particular bug anymore.

src/backend/catalog/dependency.c

index d38934177c4a9806ffbac78fa17bef91433f0cea..d8be2cb129d764f40ba37e857958bc0ab510f86b 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.69 2008/01/01 19:45:48 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.69.2.1 2008/07/11 16:08:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -130,7 +130,8 @@ static bool deleteDependentObjects(const ObjectAddress *object,
                                           DropBehavior behavior,
                                           int msglevel,
                                           ObjectAddresses *oktodelete,
-                                          Relation depRel);
+                                          Relation depRel,
+                                          ObjectAddresses *alreadyDeleted);
 static void doDeletion(const ObjectAddress *object);
 static bool find_expr_references_walker(Node *node,
                                                        find_expr_references_context *context);
@@ -369,7 +370,7 @@ deleteWhatDependsOn(const ObjectAddress *object,
        if (!deleteDependentObjects(object, objDescription,
                                                                DROP_CASCADE,
                                                                showNotices ? NOTICE : DEBUG2,
-                                                               oktodelete, depRel))
+                                                               oktodelete, depRel, NULL))
                ereport(ERROR,
                                (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
                                 errmsg("failed to drop all objects depending on %s",
@@ -501,6 +502,9 @@ findAutoDeletableObjects(const ObjectAddress *object,
  *
  * depRel is the already-open pg_depend relation.
  *
+ * alreadyDeleted is a list to add objects to as they are deleted, or NULL
+ * if the caller doesn't need to have such a list.
+ *
  *
  * In RESTRICT mode, we perform all the deletions anyway, but ereport a message
  * and return FALSE if we find a restriction violation.  performDeletion
@@ -717,7 +721,7 @@ recursiveDeletion(const ObjectAddress *object,
         */
        if (!deleteDependentObjects(object, objDescription,
                                                                behavior, msglevel,
-                                                               oktodelete, depRel))
+                                                               oktodelete, depRel, alreadyDeleted))
                ok = false;
 
        /*
@@ -783,6 +787,7 @@ recursiveDeletion(const ObjectAddress *object,
  *     behavior: desired drop behavior
  *     oktodelete: stuff that's AUTO-deletable
  *     depRel: already opened pg_depend relation
+ *     alreadyDeleted: optional list to add deleted objects to
  *
  * Returns TRUE if all is well, false if any problem found.
  *
@@ -798,7 +803,8 @@ deleteDependentObjects(const ObjectAddress *object,
                                           DropBehavior behavior,
                                           int msglevel,
                                           ObjectAddresses *oktodelete,
-                                          Relation depRel)
+                                          Relation depRel,
+                                          ObjectAddresses *alreadyDeleted)
 {
        bool            ok = true;
        ScanKeyData key[3];
@@ -865,7 +871,8 @@ deleteDependentObjects(const ObjectAddress *object,
                                                                        getObjectDescription(&otherObject))));
 
                                if (!recursiveDeletion(&otherObject, behavior, msglevel,
-                                                                          object, oktodelete, depRel, NULL))
+                                                                          object, oktodelete, depRel,
+                                                                          alreadyDeleted))
                                        ok = false;
                                break;
                        case DEPENDENCY_AUTO:
@@ -881,7 +888,8 @@ deleteDependentObjects(const ObjectAddress *object,
                                                                getObjectDescription(&otherObject))));
 
                                if (!recursiveDeletion(&otherObject, behavior, msglevel,
-                                                                          object, oktodelete, depRel, NULL))
+                                                                          object, oktodelete, depRel,
+                                                                          alreadyDeleted))
                                        ok = false;
                                break;
                        case DEPENDENCY_PIN: