use strict;
use warnings;
package DB::Transaction;
use base qw(Exporter);
our $VERSION = 0.001000; # 0.001.0
our @EXPORT_OK = qw(run_in_transaction);
my %on_error_options = (
rollback => undef,
continue => undef,
);
my %transactions_deep;
sub run_in_transaction (&;@) {
my $code = shift;
my (%args) = @_;
my $db_handle = $args{db_handle};
my $on_error = $args{on_error} || 'rollback';
die "Don't know how to handle error action '$on_error'\n"
if ! exists $on_error_options{$on_error};
local $db_handle->{AutoCommit} = 0;
local $db_handle->{RaiseError} = 1;
$transactions_deep{"$db_handle"}++;
my $error;
eval {
$code->();
$db_handle->commit if $transactions_deep{"$db_handle"} <= 1;
;1 } || do {
$error = defined $@ ? $@ : 'an error was encountered in your transaction';
$db_handle->rollback if $on_error eq 'rollback';
};
$@ = $error if defined $error;
$transactions_deep{"$db_handle"}--;
delete $transactions_deep{"$db_handle"} if $transactions_deep{"$db_handle"} < 1;
die $error if defined $error && $on_error eq 'rollback';
return ! defined $error;
}
1;
__END__
=head1 NAME
DB::Transaction - feather-weight transaction management for your DBI handles
=head1 SYNOPSIS
use DB::Transaction qw(run_in_transaction);
my $dbh = My::Application->get_dbh;
run_in_transaction {
$dbh->do('
update risky_business -- in some fashion
');
} db_handle => $dbh, on_error => 'rollback';
=head1 DESCRIPTION
DB::Transaction provides one function: run_in_transaction
=head1 EXPORTS
By default, none. On request, C<run_in_transaction>.
=head2 run_in_transaction BLOCK db_handle => $db_handle, on_error => ['rollback' | 'continue']
Begin a transaction on $db_handle, then run BLOCK. Any errors raised in the
course of executing BLOCK will cause the current transaction to be handled
according to your C<on_error> specification.
C<on_error> may be one of these two options:
=over 4
=item * rollback -- call this dbh's ->rollback method
=item * continue -- just keep on chugging, man!
=back
C<on_error =E<gt> 'rollback'> is the default behavior.
Transactions may be nested, though your underlying database may not support
nested transactions. It's up to you to know whether this is supported or not.
=head1 CONTRIBUTING
To contribute back to this project, log in to your GitHub account and visit
L<
http://github.com/shutterstock/perl-db-transaction>, then fork the repository.
Create a feature branch, make your changes, push them back to your fork, and
submit a pull request via GitHub.
# fork the project in github
git clone git://github.com/<your-name>/perl-db-transaction.git
git checkout -b feature-add-spiffy-functionality
emacs -nw t/spiffy-functionality.t # hack hack hack
emacs -nw lib/DB/Transaction.pm # hack hack hack
git push feature-add-spiffy-functionality origin
# submit pull request via github
=head1 AUTHORS
Written by Aaron Cohen <
[email protected]> and Belden Lyman <
[email protected]>
at Shutterstock, Inc. Released to CPAN by Shutterstock, Inc.
If you like the idea of working at a company that supports open-source development,
why not checkout our L<jobs page|
http://shutterstock.com/jobs.mhtml> and drop us a
line?
=head1 COPYRIGHT AND LICENSE
(c) 2013 Shutterstock, Inc. All rights reserved.
This library is free software: you may redistribute it and/or modify it under the same terms as Perl itself;
either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.