mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 16:21:20 +03:00
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.
This commit is contained in:
parent
51ca7bdb67
commit
9f66d5273b
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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,
|
DropBehavior behavior,
|
||||||
int msglevel,
|
int msglevel,
|
||||||
ObjectAddresses *oktodelete,
|
ObjectAddresses *oktodelete,
|
||||||
Relation depRel);
|
Relation depRel,
|
||||||
|
ObjectAddresses *alreadyDeleted);
|
||||||
static void doDeletion(const ObjectAddress *object);
|
static void doDeletion(const ObjectAddress *object);
|
||||||
static bool find_expr_references_walker(Node *node,
|
static bool find_expr_references_walker(Node *node,
|
||||||
find_expr_references_context *context);
|
find_expr_references_context *context);
|
||||||
@ -351,7 +352,7 @@ deleteWhatDependsOn(const ObjectAddress *object,
|
|||||||
if (!deleteDependentObjects(object, objDescription,
|
if (!deleteDependentObjects(object, objDescription,
|
||||||
DROP_CASCADE,
|
DROP_CASCADE,
|
||||||
showNotices ? NOTICE : DEBUG2,
|
showNotices ? NOTICE : DEBUG2,
|
||||||
oktodelete, depRel))
|
oktodelete, depRel, NULL))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
|
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
|
||||||
errmsg("failed to drop all objects depending on %s",
|
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.
|
* 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
|
* In RESTRICT mode, we perform all the deletions anyway, but ereport a message
|
||||||
* and return FALSE if we find a restriction violation. performDeletion
|
* and return FALSE if we find a restriction violation. performDeletion
|
||||||
@ -699,7 +703,7 @@ recursiveDeletion(const ObjectAddress *object,
|
|||||||
*/
|
*/
|
||||||
if (!deleteDependentObjects(object, objDescription,
|
if (!deleteDependentObjects(object, objDescription,
|
||||||
behavior, msglevel,
|
behavior, msglevel,
|
||||||
oktodelete, depRel))
|
oktodelete, depRel, alreadyDeleted))
|
||||||
ok = false;
|
ok = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -765,6 +769,7 @@ recursiveDeletion(const ObjectAddress *object,
|
|||||||
* behavior: desired drop behavior
|
* behavior: desired drop behavior
|
||||||
* oktodelete: stuff that's AUTO-deletable
|
* oktodelete: stuff that's AUTO-deletable
|
||||||
* depRel: already opened pg_depend relation
|
* 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.
|
* Returns TRUE if all is well, false if any problem found.
|
||||||
*
|
*
|
||||||
@ -780,7 +785,8 @@ deleteDependentObjects(const ObjectAddress *object,
|
|||||||
DropBehavior behavior,
|
DropBehavior behavior,
|
||||||
int msglevel,
|
int msglevel,
|
||||||
ObjectAddresses *oktodelete,
|
ObjectAddresses *oktodelete,
|
||||||
Relation depRel)
|
Relation depRel,
|
||||||
|
ObjectAddresses *alreadyDeleted)
|
||||||
{
|
{
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
ScanKeyData key[3];
|
ScanKeyData key[3];
|
||||||
@ -847,7 +853,8 @@ deleteDependentObjects(const ObjectAddress *object,
|
|||||||
getObjectDescription(&otherObject))));
|
getObjectDescription(&otherObject))));
|
||||||
|
|
||||||
if (!recursiveDeletion(&otherObject, behavior, msglevel,
|
if (!recursiveDeletion(&otherObject, behavior, msglevel,
|
||||||
object, oktodelete, depRel, NULL))
|
object, oktodelete, depRel,
|
||||||
|
alreadyDeleted))
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
case DEPENDENCY_AUTO:
|
case DEPENDENCY_AUTO:
|
||||||
@ -863,7 +870,8 @@ deleteDependentObjects(const ObjectAddress *object,
|
|||||||
getObjectDescription(&otherObject))));
|
getObjectDescription(&otherObject))));
|
||||||
|
|
||||||
if (!recursiveDeletion(&otherObject, behavior, msglevel,
|
if (!recursiveDeletion(&otherObject, behavior, msglevel,
|
||||||
object, oktodelete, depRel, NULL))
|
object, oktodelete, depRel,
|
||||||
|
alreadyDeleted))
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
case DEPENDENCY_PIN:
|
case DEPENDENCY_PIN:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user