From 6dafb5b4ae9753b3951878dd1d6f353cc6f9e388 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 11 Jul 2008 16:08:50 +0000 Subject: [PATCH] Fix an oversight in the original implementation of performMultipleDeletions(): 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 | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index d38934177c..d8be2cb129 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -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: -- 2.50.1