eval { local $dbh->{AutoCommit} = 0; }; $self->{_can_do_transactions} = $@ ? 0 : 1;
can be written more reliably as
$self->{_can_do_transactions} = eval { local $dbh->{AutoCommit} = 0; 1 };
But That boils down to the following code, which you might want to use directly.
$self->{_can_do_transactions} = eval { $dbh->begin_work(); $dbh->rollback() };
I don't see the point of determining the capability in advance, so we end up with:
my $in_trans = eval { $dbh->begin_work() }; if (!eval { code_that_touches_db(); $dbh->commit() if $in_trans; 1 }) { my $msg = $@; eval { $dbh->rollback() } if $in_trans; die $msg; }
Cleaner?
use Sub::ScopeFinalizer qw( scope_finalizer ); { my $in_trans = eval { $dbh->begin_work() }; my $pending_rollback = scope_finalizer { local $@; eval { $dbh->rollback() } if $in_trans; }; code_that_touches_db(); $pending_rollback->disable(); $dbh->commit() if $in_trans; }
Cleaner still?
BEGIN { package TransactionMaybe; sub begin { my ($class, $dbh) = @_; my $in_trans = eval { $dbh->begin_work() }; return bless([$dbh, $in_trans], $class); } sub commit { my ($self) = @_; my $dbh = $self->[0]; our $in_trans; local *in_trans = \($self->[1]); $dbh->commit() if $in_trans; $in_trans = 0; } sub DESTROY { my ($dbh, $in_trans) = @$self; local $@; eval { $dbh->rollback() } if $in_trans; } $INC{'TransactionMaybe.pm'} = 1; } { my $transaction = TransactionMaybe->begin($dbh); code_that_touches_db(); $transaction->commit(); }
However, it seems to me it's a bug to call call the same code_that_touches_db() whether transactions are available or not.
In reply to Re: How to safely test if a database handle is capable of transactions?
by ikegami
in thread How to safely test if a database handle is capable of transactions?
by larryl
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |