Skip Menu |

This queue is for tickets about the DBIx-Class CPAN distribution.

Report information
The Basics
Id: 36987
Status: resolved
Priority: 0/
Queue: DBIx-Class

People
Owner: Nobody in particular
Requestors: michael [...] ndrix.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in:
  • 0.07006
  • 0.08010
Fixed in: (no value)



Subject: $row->delete after failed transaction
If a row is deleted inside a transaction and that transaction subsequently fails, one cannot delete the row with the delete() method. For example: $schema->txn_do( sub { $row->delete; # this works die; # cancel the transaction with an exception }); $row->delete; # this dies with "Not in storage" Deleting $row inside the transaction calls $row->in_storage(undef). However, when the transaction is rolled back $row is not marked as being back in storage. Ideally, I think it should be. I've been working around this with something like: $schema->resultset('RowClass')->search({ id => $row->id })->delete; which generates the same resulting SQL but is not nearly as concise.
Ok, we basically don't have any sane way of fixing this. The thing is, while your transaction failing for well-known reasons might be something where you know you can go back to the previous stage, if it failed because of something else running on the db at the same time then the object's state might be inconsistent in other ways. So the only solution really is to leave the user the choice of how to roll things back. Your workaround is a bit longer than strictly required though. To tell DBIC "actually, this row -is- still in storage" you can do $obj->in_storage(1); after which delete() will work again. If you want to double check whether the object was deleted by something else in the mean time, do $obj->in_storage(1); $obj->discard_changes; and then check in_storage again. I'd absolutely love an FAQ patch or similar explaining this - I can see why you find the behaviour non-DWIM but I don't think there's a safe solution other than "user figures out consistency". If you think you can come up with a solution that -is- safe, then please send a message to the dbix-class mailing list (subscribe via http://lists.scsys.co.uk/) and we can discuss it on there (or if you're kind enough to write this up for the FAQ please send that patch there as well :). In the meantime, since there's not a lot to do directly about this, I'm going to close the ticket.
Changing to stalled in the hope that the original author will submit a workaround FAQ entry.
On Fri Oct 24 10:11:23 2008, RIBASUSHI wrote: Show quoted text
> Changing to stalled in the hope that the original author will submit a > workaround FAQ entry.
I've attached a documentation patch. It seemed to make more sense to document Row->delete rather than add the content to the FAQ.
From b98db0c596e992960ed6a52d5031bc0b3d778a48 Mon Sep 17 00:00:00 2001 From: Michael Hendricks <michael@ndrix.org> Date: Wed, 17 Dec 2008 09:01:51 -0700 Subject: [PATCH] Document delete behavior within transactions Signed-off-by: Michael Hendricks <michael@ndrix.org> --- lib/DBIx/Class/Row.pm | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/lib/DBIx/Class/Row.pm b/lib/DBIx/Class/Row.pm index c1fb2b0..0c517d1 100644 --- a/lib/DBIx/Class/Row.pm +++ b/lib/DBIx/Class/Row.pm @@ -450,6 +450,13 @@ hashref of the relationship, see L<DBIx::Class::Relationship>. Any database-level cascade or restrict will take precedence over a DBIx-Class-based cascading delete. +If you delete an object within txn_do() (see L<DBIx::Class::Storage/txn_do>) +and the transaction subsequently fails, the object is still marked as not +being in storage. If you know that the object is in storage (by inspecting +the cause of the transaction's failure, for example), you can use +C<< $obj->in_storage(1) >> to indicate the object really is in storage. +This permits a subsequent C<< $obj->delete >> to work as expected. + See also L<DBIx::Class::ResultSet/delete>. =cut -- 1.6.0.2.307.gc4275
Resolved in trunk@5269