sub perform_transaction {
my ($dbh, $coderef, $allow_non_transaction) = @_;
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;
}
}
eval {
@result = (wantarray) ? $coderef->() : scalar $coderef->();
$dbh->commit if $use_transaction;
};
if ($@ && $use_transaction) {
local $@; # protect original error
eval { $dbh->rollback };
}
die if $@; # propagate original error
$dbh->{AutoCommit} = 1 if $orig_AutoCommit;
return $result[0] unless wantarray;
return @result;
}
Hopefully it's self-explanatory. Comments welcome.
Tim
p.s. I've not actually tested this yet.