aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-07-11 16:08:57 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-07-11 16:08:57 +0000
commit9f66d5273bbd1ac60c5e72d6b1add635c04e9317 (patch)
tree04692fd94d1ce4e8a6b983bd61f1de93405f265b /src
parent51ca7bdb677319f0bb7eea9a0b468934a8fbe678 (diff)
downloadpostgresql-9f66d5273bbd1ac60c5e72d6b1add635c04e9317.tar.gz
postgresql-9f66d5273bbd1ac60c5e72d6b1add635c04e9317.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/dependency.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index cab4f1006bc..ff3657d0bdd 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.60 2006/10/04 00:29:50 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.60.2.1 2008/07/11 16:08:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -113,7 +113,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);
@@ -351,7 +352,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",
@@ -483,6 +484,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
@@ -699,7 +703,7 @@ recursiveDeletion(const ObjectAddress *object,
*/
if (!deleteDependentObjects(object, objDescription,
behavior, msglevel,
- oktodelete, depRel))
+ oktodelete, depRel, alreadyDeleted))
ok = false;
/*
@@ -765,6 +769,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.
*
@@ -780,7 +785,8 @@ deleteDependentObjects(const ObjectAddress *object,
DropBehavior behavior,
int msglevel,
ObjectAddresses *oktodelete,
- Relation depRel)
+ Relation depRel,
+ ObjectAddresses *alreadyDeleted)
{
bool ok = true;
ScanKeyData key[3];
@@ -847,7 +853,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:
@@ -863,7 +870,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: