I had an idea as to how we can fix this. I am expressing this in
pseudo-code because I'm not comfortable understand enough with the code
to patch it myself.
Create three lists:
deleted, pending and recentlyDeleted
When any object is deleted, you add it into "deleted" and
"recentlyDeleted". When we reach an object which cannot be deleted due
to a DENY rule, we add it into "pending".
Here is an example of how it would work.
Given the following cascade rules:
-> means "cascade delete"
|-> means "deny delete unless the following objects are deleted"
A -> B -> C
-> D
-> E
C |-> D
D |-> E
E |-> C
Now, say a user deletes A, the algorithm would walk through the problem
like this:
- 1st pass
deleted: A
recentlyDeleted: A
pending:
- 2nd pass (A is removed from "recentlyDeleted" because no objects in
"pending" were waiting on its deletion)
deleted: A, B
recentlyDeleted: B
pending:
- 3rd pass (We can't delete C because D still exists)
deleted: A, B
recentlyDeleted:
pending: C
- 4th pass (We can't delete D because E still exists)
deleted: A, B
recentlyDeleted:
pending: C, D
- 5th pass, we attempt to delete E. We notice that E depends on C being
deleted and it just so happens that C is in "pending", so E's deletion
is allowed to go through.
deleted: A, B, E
recentlyDeleted: E
pending: C, D
- 6th pass, we notice that "recentlyDeleted" is not empty, so we check
"pending" to see if any elements on the list depend on any recently
deleted objects. We find out D may now be deleted.
deleted: A, B, E, D
recentlyDeleted: D
pending: C
- 7th pass, we notice that now C may be deleted.
deleted: A, B, E, D, C
recentlyDeleted: C
pending:
we're done... This is an example of a successful delete. We can detect a
failed delete if the three lists remain unchanged between the beginning
and end of a pass (i.e. there was no change, we got stuck).
Is it possible for someone to translate this pseudo-code into an actual
patch?
Gili
Gili wrote:
> Hi,
>
> I've got this relationship:
>
> On delete of A, cascade to B
> On delete of B, if any "A" instances exist, DENY
>
> What I'm seeing at runtime is that I delete A, it tries to cascade
> to B but this fails because A is still associated with it. Cayenne
> doesn't seem to be smart enough to notice this is ok because A is the
> one triggering the delete in the first place. Here are the logs I get at
> runtime (I added these to the code):
>
> INFO DataContextDeleteAction:279 -
> desktopbeautifier.server.cayenne.delegates.DefaultImag..d=14200 is
> cascading delete to
> desktopbeautifier.server.cayenne.delegates.DefaultContentTyp..d=6080
>
> INFO DataContextDeleteAction:279 -
> desktopbeautifier.server.cayenne.delegates.DefaultImag..d=14200 is
> cascading delete to
> desktopbeautifier.server.cayenne.delegates.ImageDat..d=14520
>
> org.objectstyle.cayenne.access.DeleteDenyException: Can't delete object
> with OID desktopbeautifier.server.cayenne.delegates.ImageData: <id:
> 14520>. Reason: relationship 'image' has Deny. Details: Related objects:
> java.util.Collections$SingletonLis..d=14200
>
> I think I might try writing a unit test tomorrow. Please let me know
> if the above is the expected behavior or if this sounds like a bug.
>
> Thanks,
> Gili
-- http://www.desktopbeautifier.com/
This archive was generated by hypermail 2.0.0 : Thu Sep 15 2005 - 23:35:41 EDT