ap / DBIx-Connector

Fast, safe DBI connection and transaction management
https://metacpan.org/release/DBIx-Connector
40 stars 14 forks source link

in_txn always returns true? #11

Closed rledousa closed 13 years ago

rledousa commented 13 years ago

Hi

Loving DBIx::Connector so far. One question - in_txn() returns true even before I do $conn->txn(..). Here's an example:

#class var
my $conn = DBIx::Connector->new($dsn,$dbUser,$dbPwd, {AutoCommit => 0, RaiseError => 1, PrintError => 0});

sub do_something {
:
# for testing
print $conn->in_txn() . "\n";
$conn->txn(fixup => sub {
print $conn->in_txn() . "\n";
:
:
} );
}

If I set AutoCommit => 1 (enabled), then in_txn() works as expected ( returns false outside of txn, '1' inside).

If AutoCommit => 0, both print statements shows true. I'm using mysql 5.1. Am I doing something wrong or misunderstanding in_txn()?

thx

theory commented 13 years ago

On May 9, 2011, at 4:50 PM, rledousa wrote:

Hi

Loving DBIx::Connector so far.

Great!

One question - in_txn() returns true even before I do $conn->txn(..). Here's an example:

#class var
my $conn = DBIx::Connector->new($dsn,$dbUser,$dbPwd, {AutoCommit => 0, RaiseError => 1, PrintError => 0});

sub do_something {
:
# for testing
print ($conn->in_txn()) ? 'true' : 'false';
$conn->txn(fixup => sub {...} );
}

I expect to see 'false'. but the print statement always shows true. I'm using mysql 5.1. Am I doing something wrong or misunderstanding in_txn()?

This gives me an error:

use DBIx::Connector;
my $dsn = 'dbi:Pg:dbname=try';
my $dbUser = 'postgres';
my $dbPwd;
my $conn = DBIx::Connector->new($dsn, $dbUser, $dbPwd, {
    AutoCommit => 0,
    RaiseError => 1,
    PrintError => 0
});

print $conn->in_txn ? 'true' : 'false';

Which I will fix. But your example never calls do_somthing(), so I can't tell what might be up with that. Can you provide more context.

Best,

David

rledousa commented 13 years ago

thx for the reply

sorry for not adding the code that calls do_something(). I was just trying to provide a bare-bones example. To add more flesh, here's what I did: I created a simple class which has the class var ($conn) and a constructor which does nothing more than bless and return. I instantiate the class in my test script, then call do_something($sql) and pass in some sql for testing, eg

sub new {
        my ($this, $args) = @_;

        my $class = ref($this) || $this;

        my $self = {
                dbh => 'handle'
        };

        bless $self, $class;

        return $self;
}

sub do_something {
  my ($self, $sql) = @_;
  print $conn->in_txn();   # this always prints '1' if AutoCommit is false
  $conn->txn(fixup => sub { $_->do($sql)} );
}

again, I'm using mysql. Dunno if that makes a difference for you.

theory commented 13 years ago

On May 10, 2011, at 8:35 AM, rledousa wrote:

print $conn->in_txn(); # this always prints '1' if AutoCommit is false

Oh, this comment is key. If AutoCommit is false, you are in a transaction. That's the way the DBI works, too:

perl -MDBI -E 'say DBI->connect("dbi:Pg:dbname=try")->{AutoCommit}' 1

That is, if AutoCommit is off, then you are in a transaction automatically:

   If true, then database changes cannot be rolled‐back (undone).  If
   false, then database changes automatically occur within a
   "transaction", which must either be committed or rolled back using the
   "commit" or "rollback" methods.

I recommend that you set AutoCommit to true, frankly, and use begin_work(), commit(), and rollback() to handle transactions when using the DBI. When using DBIx::Connector, if you plan to use run(), txn(), or svp(), I recommend it even more strongly.

Best,

David

rledousa commented 13 years ago

thanks David. I'd read that, but wasn't clear if that is the same behavior for your module.