[Dbix-class] Cascade deletes

Peter Rabbitson rabbit+dbic at rabbit.us
Sat Mar 6 11:59:39 GMT 2010


Bill Moseley wrote:
> First, is there a way to globally disable cascade deletes?  I know I can
> add cascade_delete => 0 to the relationships, but I never want cascade
> deletes in the ORM (I have a database that does that).
> 
> Second,
> 
> Say I have my music db and an error in a relationship name.  Then I do this:
> 
>     my $artist = $schema->resultset( 'Artist' )->create( { name => 'test
>     aritst' } );
>     $artist->delete;
> 
> I get this exception on the delete call:
> 
> DBIx::Class::Relationship::CascadeActions::delete(): Can't find source
> for MyApp::Result::Cdxx at /home/moseley/dbic_music/test.pl
> <http://test.pl> line 19
> 
> So, the Cdxx class didn't get loaded until trying to do the cascade
> delete.  I guess that's ok.  But what I find awkward is that
> $artist->delete threw an exception but still deleted the artist row.  If
> $artist->delete is multiple database calls behind the scene shouldn't
> they be wrapped in a transaction?
> 
> Or is it expected that deletes are explicitly placed in a transaction?
> 
> $schema->txn_do( sub { $artist->delete } );

No it isn't, thank you for bringing this up, fix will be coming up shortly.

> I notice that DBIC does a select to find the related rows (i.e. in the
> Cd table when looking for rows to cascade delete).   Is there a reason
> that's done instead of just deleting directly?
> 
> INSERT INTO artist ( label, name) VALUES ( ?, ? ): '1', 'test aritst'
> INSERT INTO cd ( artist) VALUES ( ? ): '25'
> 
> DELETE FROM artist WHERE ( id = ? ): '25'
> SELECT me.id <http://me.id>, me.year, me.name <http://me.name>,
> me.artist FROM cd me WHERE ( me.artist = ? ): '25'
> DELETE FROM cd WHERE ( id = ? ): '54'
> 
> Why not just delete from cd where artist = 25?

Because this will not invoke the various triggers that could be hidden
in lower classes (at the very least if you delete from an rs CDs then
dbic will not know to delete from Tracks).

In general your intuition is correct that if your database provides
cascading you should not have dbic bother with any of it. A POD
discussion of this (ideally as an addition to delete in Row.pm) is
more than welcome.

> Again, sure seems like that should be inside a transaction.

Correct, fix on TODO list.




More information about the DBIx-Class mailing list