Noel Burton-Krahn wrote:
> On Sun, Oct 26, 2008 at 1:19 AM, Peter Rabbitson <[EMAIL PROTECTED]> 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.

Neither do I, but for someone who does DBIC all of a sudden becomes a
non-starter.

> 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.

You can not have a referential constraint without ON UPDATE/ON DELETE
triggers. Refer to your RDBMS manual to find out which trigger is used
by default if one is not supplied explicitly (usually RESTRICT).

> 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?

Because delete() on a resultset calls DELETE FROM <table> WHERE
<sql-abstract condition>, whereas delete_all() retrieves all the rows in
the resultset and then calls delete() on the row objects _one_by_one_.
This has two benefits:

1) Your business logic defined in Perl will actually run, since it is
most likely hooked up in an overloaded row-level delete(). If you do
$rs->delete, the row-level delete()s never get called, so again - no
statistics for you.

2) Most (if not all) databases do not support complex WHERE conditions
with joins for the DELETE call. So if the condition of your current $rs
is moderately complex you can not call ->delete on it and expect things
to work. Current trunk actually warns you of the fact.

All-in-all this is not a bug, but totally expected and _desired_
behavior. Fix your constraints.

> 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.
> 

I applied your patch to latest trunk, and this is what I get. Please
point out the problem:

[EMAIL PROTECTED]:~/devel/dbic/delete_rambling$ DBIC_TRACE=1 prove -Ilib
-It/lib t/100delete_all_cascades.t -v
t/100delete_all_cascades....1..16
ok 1 - create database
ok 2 - connect to db
INSERT INTO person (name) VALUES (?): 'fred'
ok 3 - create Person: id=1 name=fred
SELECT me.id, me.name FROM person me:
ok 4 - found Person: id=1 name=fred
INSERT INTO address (address, person_id) VALUES (?, ?): 'fred's address
1', '1'
ok 5 - create Address: id=1 person_id=1 address=fred's address 1
INSERT INTO address (address, person_id) VALUES (?, ?): 'fred's address
2', '1'
ok 6 - create Address: id=2 person_id=1 address=fred's address 2
INSERT INTO address (address, person_id) VALUES (?, ?): 'fred's address
3', '1'
ok 7 - create Address: id=3 person_id=1 address=fred's address 3
SELECT me.id, me.person_id, me.address FROM address me:
ok 8 - found created Address: id=1 person_id=1 address=fred's address 1
ok 9 - found created Address: id=2 person_id=1 address=fred's address 2
ok 10 - found created Address: id=3 person_id=1 address=fred's address 3
SELECT me.id, me.name FROM person me WHERE ( ( ( me.id = ? ) ) ): '1'
ok 11 - address->person: id=1 name=fred
SELECT me.id, me.person_id, me.address FROM address me WHERE (
me.person_id = ? ): '1'
ok 12 - person->address: id=1 person_id=1 address=fred's address 1
ok 13 - person->address: id=2 person_id=1 address=fred's address 2
ok 14 - person->address: id=3 person_id=1 address=fred's address 3
SELECT address.id, address.person_id, address.address FROM person me
LEFT JOIN address address ON ( address.person_id = me.id ) WHERE ( name
= ? ): 'fred'
DELETE FROM address WHERE ( id = ? ): '1'
DELETE FROM address WHERE ( id = ? ): '2'
DELETE FROM address WHERE ( id = ? ): '3'
SELECT me.id, me.name FROM person me WHERE ( name = ? ): 'fred'
DELETE FROM person WHERE ( id = ? ): '1'
SELECT me.id, me.person_id, me.address FROM address me WHERE (
me.person_id = ? ): '1'
ok 15 - delete_all
SELECT COUNT( * ) FROM person me WHERE ( name = ? ): 'fred'
ok 16 - Person really gone
ok
All tests successful.
Files=1, Tests=16,  0 wallclock secs ( 0.19 cusr +  0.02 csys =  0.21 CPU)
[EMAIL PROTECTED]:~/devel/dbic/delete_rambling$


Cheers


_______________________________________________
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

Reply via email to