package Transactions; use Carp qw(croak); use Exporter::Tidy default => [ qw(transaction commit rollback) ]; our $VERSION = '0.03'; sub commit () { croak "Can't commit outside a transaction" } sub rollback () { croak "Can't rollback outside a transaction" } sub transaction ($&) { my ($object, $sub) = @_; local $^W; local *{ caller() . '::commit' } = sub () { die "COMMIT\n" }; local *{ caller() . '::rollback' } = sub () { die "ROLLBACK\n" }; local $@; eval { $object->begin_work; $sub->(); }; if ($@ eq "COMMIT\n") { $object->commit; } elsif ($@ eq "ROLLBACK\n") { $object->rollback; } elsif ($@) { die $@ . "commit not safe after errors, transaction rolled back.\n"; } else { $object->commit; } } 1; __END__ =head1 NAME transactions - Easier DBI(-ish) transactions =head1 SYNOPSIS use Transactions; my $dbh = DBI->connect(...); transaction $dbh, sub { for (1..10) { my $sth = $dbh->prepare(...); $sth->execute() or rollback; } }; =head1 DESCRIPTION This module exports custom C, C and C functions to make using transactions easier. =head2 Functions =over 13 =item transaction $object, sub BLOCK Begins a transaction and evals BLOCK. Commits the transaction if the BLOCK does not die, rolls it back when it does. $object is the object that can() C, C and C. =item commit To be used in C's BLOCK. Commits the transaction and ends the block (like C). =item rollback To be used in C's BLOCK. Rolls the transaction back and ends the block (like C). =back =head1 CAVEATS Do not nest transactions. Maybe it works, but I haven't tested that. The code block actually is a sub, so in it, C ends only that code block, not any surrounding subroutine. =head1 LICENSE There is no license. This software was released into the public domain. Do with it what you want, but on your own risk. The author disclaims any responsibility. =head1 AUTHOR Juerd Waalboer =cut