Incorporating feedback (thanks) and other ideas:
sub perform_transaction {
! my ($dbh, $attr, $coderef, @args) = @_;
my $wantarray = wantarray;
my $use_transaction = 1;
my $orig_AutoCommit = $dbh->{AutoCommit};
if ($orig_AutoCommit) {
unless (eval { $dbh->{AutoCommit} = 0; 1 }) {
die unless $allow_non_transaction;
$use_transaction = 0;
}
}
+ local $dbh->{RaiseError} = 1;
eval {
@result = ($wantarray) ? $coderef->(@args) : scalar $coderef->(@args);
$dbh->commit if $use_transaction;
+ $attr->{OnCommit}->() if $attr->{OnCommit}->();
};
if ($@) {
local $@; protect original error
! my $rv = eval { ($use_transaction) ? $dbh->rollback : 0 };
+ $attr->{OnRollback}->($rv) if $attr->{OnRollback};
}
die if $@; # propagate original error
$dbh->{AutoCommit} = 1 if $orig_AutoCommit;
return $result[0] unless $wantarray;
return @result;
}
But as I tinker with it I wonder if it's a solution chasing a problem.
Where, and how, and why, would it be used?
Anyone got any realistic examples?
Tim.