DBIx::Transaction::db - Database handle that is aware of nested transactions |
DBIx::Transaction::db - Database handle that is aware of nested transactions
See the DBIx::Transaction manpage
When you connect to a database using DBIx::Transaction, your database handle
will be a DBIx::Transaction::db object. These objects keep track of your
transaction state, allowing for transactions to occur within transactions,
and only sending ``commit
'' or ``rollback
'' instructions to the underlying
database when the outermost transaction has completed. See the DBIx::Transaction manpage
for a more complete explanation.
The following methods are overridden by DBIx::Transaction::db:
If there are no transactions currently running, begin_work
will check
if AutoCommit
is enabled. If it is enabled, a begin_work
instruction
is sent to the underlying database layer. If AutoCommit
is disabled, we
assume that the database has already started a transaction for us, and do
nothing. This means that you must always use begin_work to start a
transaction, even if AutoCommit
is enabled!
If there is a transaction started, begin_work
simply records that a nested
transaction has started.
begin_work
returns the result of the database's begin_work
call if it
makes one; otherwise it always returns true.
If there are no sub-transactions currently running, rollback
will issue the
rollback
call to the underlying database layer.
If there are sub-transactions currently running, rollback
notes that the
nested transaction has been aborted.
If there is no transaction running at all, rollback
will raise a fatal
error.
commit
records that this
transaction has completed successfully and does nothing to the underlying
database layer.
If there are no sub-transactions currently running, commit
checks if
there have been any transaction errors. If there has been a transaction
error, commit
raises an exception. Otherwise, a commit
call is
issued to the underlying database layer.
If there is no transaction running at all, commit
will raise a fatal
error. This error will contain a full stack trace, and should also contain
the file names and line numbers where any rollbacks or query failures
happened.
commit
for the current transaction.
The following method is provided for convienence in setting up database transactions:
transaction($coderef)
$coderef
within a transaction.
$coderef
is expected to return a scalar value.
If $coderef
returns true, the transaction is committed. If
$coderef
returns false or raises a fatal error, the transaction
is rolled back. The return value is the same as what is returned by
$coderef
.
This method is supplied to make it easier to create nested transactions out of many small transactions. Example:
sub get_max_id { my $dbh = shift; # this will roll back if it can't get MAX(num) $dbh->transaction(sub { if(my($id) = $dbh->selectrow_array("SELECT MAX(num) FROM foo")) { return $id; } else { return; } }); } sub do_something { my($dbh, $num) = @_; $dbh->transaction(sub { $dbh->do("UPDATE foo SET bar = bar + 1 WHERE num = $num"); }); } sub do_many_things { my $dbh = shift; # if any of these sub-transactions roll back, the whole thing will roll # back $dbh->transaction(sub { if( do_something($dbh, 1) && do_something($dbh, 2) && (my $id = get_max_id($dbh)) ) { return do_something($dbh, $id); } else { return; } }); }
The following methods are used by the overridden methods. In most cases you won't have to use them yourself.
$dbh->rollback while $dbh->transaction_level;
But I would suggest that you structure your code so that each transaction and sub-transaction bails out safely instead, as that's a lot easier to trace and debug with confidence.
transaction_level
by one. This is used by the begin_work
override
and should not be called directly.
transaction_level
by one. If this results in a negative number
(meaning more transactions have been commited/rolled back than started),
dec_transaction_level
throws a fatal error. This is used by the
commit
and rollback
methods and should not be called directly.
rollback
.
Optional parameters are the package, filename, and line where
the transaction error occured. If provided, they will be used in
error messages relating to the rollback.
rollback
, and cleared whenever the
outermost transaction issues a rollback
.
close_transaction($method)
$method
(``commit
'' or ``rollback
'') on the underlying database layer and
resetting the DBIx::Transaction state. This method is used by the
commit
and rollback
methods and you shouldn't need to use it yourself,
unless you wanted to forcibly bail out of an entire transaction without
calling rollback
repeatedly, but as stated above, that's a bad idea,
isn't it?
the DBI manpage, the DBIx::Transaction manpage
Tyler ``Crackerjack'' MacDonald <japh@crackerjack.net>
Copyright 2005 Tyler MacDonald This is free software; you may redistribute it under the same terms as perl itself.
DBIx::Transaction::db - Database handle that is aware of nested transactions |