Skip to content

Instantly share code, notes, and snippets.

@theory
Created December 31, 2011 00:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theory/1542242 to your computer and use it in GitHub Desktop.
Save theory/1542242 to your computer and use it in GitHub Desktop.
How to add a Transaction Guard to a DBIx::Connector Subclass
package DBIx::Connector::TxnGuard;
use strict;
use warnings;
use Carp;
sub new {
my ($class, $dbh) = @_;
$dbh->begin_work;
return bless { dbh => $dbh };
}
sub dbh { shift->{dbh} }
sub commit {
my $self = shift;
$self->{dbh}->commit;
$self->{finished} = 1;
}
sub rollback {
my $self = shift;
$self->{dbh}->rollback;
$self->{finished} = 1;
}
sub DESTROY {
my $self = shift;
return if $self->{finished};
$self->{dbh}->rollback;
carp "Uncommitted guard left scope, transaction rolled back";
}
package DBIx::Connector::WithTxnGuard;
use parent 'DBIx::Connector';
use Carp;
# Note: if the mode is "ping", run() will ping before returning the $dbh. If
# it's "no_ping" of "fixup", it won't, and will just return the handle. I
# don't know if you want to have some way to try to reconnect and execute code
# again with "fixup" mode; I don't see how you could, since the code to be
# exeuted is not within the control of the guard.
sub txn_guard {
my $self = shift;
croak "Attempt to create transaction guard when already in transaction"
if $self->in_txn;
DBIx::Connector::TxnGuard->new( $self->run(@_ => sub { shift }) );
}
package main;
my $conn = DBIx::Connector::WithTxnGuard->new('dbi:Pg:dbname=david', '', '', {
PrintError => 0,
RaiseError => 1,
AutoCommit => 1,
pg_enable_utf8 => 1,
pg_server_prepare => 0,
});
my $guard = $conn->txn_guard;
$guard->dbh->do('CREATE TABLE guardtest(id int)');
# $guard->rollback;
# $guard->commit;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment