[Dbix-class] bug in delete_all: CascadeActions::delete removes
parent before children
Noel Burton-Krahn
noel at burton-krahn.com
Mon Oct 27 00:27:21 GMT 2008
On Sun, Oct 26, 2008 at 1:19 AM, Peter Rabbitson <rabbit+list at rabbit.us> wrote:
>
> 1) You call delete_all
> 2) You traverse the entire relationship chain, and start calling delete
> on the resulting three backwards, depth first.
> 3) By the time you get to the main row that you wanted to delete_all in
> the first place, it runs a trigger which is supposed to run some
> statistics on the rows the ref_integrity was supposed to delete - epic
> fail: they are not there anymore.
I don't agree with #3: I do my business logic (in your example, doing
statistics) in Perl, not database triggers. That's one thing ORM is
good for.
> In any case I am not entirely sure what your problem is. If you have
> referential integrity enforced, and have proper ON DELETE xxx clauses
> set - how is it that (quoting your original mail): "The database will
> throw a referential integrity exception when the parent is deleted
> before the children". Smells like a misdesigned schema to me.
Think about it: You can't delete a parent row (a Person) while there
are still child rows (an Address) that refer to it. That's why the
current implementation of delete_all can't work with referential
integrity, because it will attempt to delete the parent before the
child See the example I attached to a previous email.
My example blows up because it has referential integrity checking, but
no "ON DELETE CASCADE" triggers. I'd prefer the ORM to handle
cascading deletes, which is what I was hoping for with delete_all.
Unfortunately, that can't work the way it's current;y implemented.
So, I wonder why keep the current implementation of delete_all at all?
>> It would also be nice to get the ambiguous select thing fixed because
>> that's bitten me a couple of times before too. Where does the SQL
>> construction happen?
>
> Can you rephrase this second issue you are talking about, without
> referring the the first one (which is ENOPROBLEM).
If you construct a sufficiently complex select_related clause, DBIx
will construct ambiguous SQL. Take a look at the SQL that DBIx
generates: It does not uniquely qualify the selected columns. Here
was the SQL that failed, which you'll see if you run my test in my
patch:
SELECT artist_undirected_maps.id1, artist_undirected_maps.id2
FROM artist_undirected_map me
LEFT JOIN artist mapped_artists ON (
mapped_artists.artistid = me.id1 ) OR ( mapped_artists.artistid =
me.id2 )
LEFT JOIN artist_undirected_map artist_undirected_maps ON (
artist_undirected_maps.id1 = mapped_artists.artistid ) OR (
artist_undirected_maps.id2 = mapped_artists.artistid )
WHERE ( ( id1 = ? ) OR ( id2 = ? ) )
The id1 and id2 in the "where" clause should have been uniquely
qualified like me.id1 and me.id2.
~Noel
> _______________________________________________
> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
> Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
>
More information about the DBIx-Class
mailing list