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.

Reply via email to