>         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.

Er, is this giving users enough rope to shoot themselves in the foot ?

Since &$coderef can contain *any* code, might users be (mis)led to believe
that anything they do in the coderef will get "rolled back" on any error ?

While it would be neat to have such a capability (ie, adding transaction
monitor capability to DBI), in this present form, the docs will need to be very 
explicit about
what its capabilities really are (Bold and UPPERCASE THE POD DESCRIPTION).

OTOH, might a partial xaction monitor behavior be possible by the DBI
layer flagging that its "acting as  xaction monitor", and then tracking every
database handle that gets used within the $coderef, and applying the
rollback/commit to *all* such handles ? It ain't 2PC, but its a start.
E.g., a execute_for_fetch() pulling data from $srcdbh into $tgtdbh;
apps might want both to operate within a xaction, so if 
$tgtdbh fails and is rolled back, $srcdbh is likewise rolledback in order to 
release locks. (Probably lots of complications if apps start threading within
the $coderef)

And for that matter, maybe support an add'l $coderef, e.g, $recoverref,
the app can provide to perform any app level rollback operation ?

Or maybe just add class level begin_transaction(), commit(), and rollback()
to DBI, eg,

DBI->begin_transaction();

$dbh1->do(...);
$dbh2->do(...);

...some code...

DBI->commit();

with maybe some args to begin_transaction() to provide a rollback exit label
and/or a rollback coderef ? Or maybe borrowing some try/catch code from
http://www.perl.com/lpt/a/2002/11/14/exception.html ?

BTW: has there ever been an attempt to build a xaction monitor in Perl ?

Overthinking again,
Dean Arnold
Presicient Corp.
www.presicient.com

Reply via email to