gchatelier has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I can't figure out what I am doing wrong when trying to use a DBI handler in a sub...

The warn I get :
Issuing rollback() for database handle being DESTROY'd without explicit disconnect().

I'd like to use my dbhandler in a function :
my $conn = DBI->connect("dbi...); sub { my $conn = shift; ... }
I would be really appreciates explainations on what happens...

Some more informations as requested,here is a simple exemple that doesn't work properly :
use somepackage; my $conn = somepackage::connectdb(); $conn->{AutoCommit} = 0; ... sub foo { my ($conn, $bar) = @_; my $sth = $conn->prepare(qq{ SELECT COUNT(*) AS MYCOUNT FROM MYTABLE WHERE ID=? }); $sth->execute($bar); my $ref = $sth->fetchrow_hashref(); $sth->finish(); return $ref->{MYCOUNT}; } print &foo($conn, 'some id'); ... $conn->disconnect(); __END__
code into somepackage :
sub connectdb { my $user = 'user'; my $password = 'password'; my $host = 'host'; my $sid = 'SID'; return (DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $pas +sword, {PrintError => 1, RaiseError => 1, AutoCommit => 0})); }
Greg

Replies are listed 'Best First'.
Re: Passing a DBI handler the proper way
by sgifford (Prior) on Jun 14, 2006 at 14:46 UTC
    That happens when the last reference to the handle goes out of scope.

    If you don't keep a reference to the handle after calling the sub, then when the sub returns the last handle will go out of scope, causing the error you describe.

    There's lots of other possibilities, too; you'll need look through your code with this possibility in mind. If you can't find it, reduce it to a very small example and post that.

Re: Passing a DBI handler the proper way
by dsheroh (Monsignor) on Jun 14, 2006 at 14:51 UTC
    Can you post more code, ideally a minimal program that runs, but experiences the problem you're asking about? (There's also a good chance that you'll find the answer yourself in the course of creating such a minimal example.)

    The little bit that you've already posted looks correct, so I'm fairly sure your problem is in the code you haven't posted.

    The only other thing I can see is that, whenever DBI complains about the absence of an explicit disconnect, it means your handle is going out of scope and being destroyed before you call $conn->disconnect, which is somewhat unsafe. You should always call disconnect when you're done with the database handle. This warning is likely coming when the main program exits (since that's where you're originally setting up $conn) and has nothing to do with the sub, though.

Re: Passing a DBI handler the proper way
by MonkE (Hermit) on Jun 14, 2006 at 14:54 UTC

    It sounds like your database handle $conn is going out of scope before you properly close it. You are explicitly disconnecting $conn when you're finished with it right?

    Even if you are disconnecting, you will still get a warning about an outstanding, uncommitted transaction, if you haven't performed a commit before you disconnect. You may want to specify auto-commit when you open the database connection (or at least be aware of its setting):

    $conn = DBI->connect('dbi...', $user, $password, { RaiseError => 1, AutoCommit => 1 });

    It is difficult to say anything more without more information to go on.

    Updated: Changed AutoCommit value from 0 to 1
      I think you meant AutoCommit => 1. :)

      ---
      It's all fine and dandy until someone has to look at the code.
        If you don't want to AutoCommmit, then you could do $conn->commit instead.

        -a

Re: Passing a DBI handler the proper way
by derby (Abbot) on Jun 14, 2006 at 14:55 UTC

    As others have said, you need to post more code to get a better answer. I would guess that you have AutoCommit set to 0 , putting yourself in a Transaction, and then you're forgetting to commit the transaction. Can you tell if the data is being properly created, updated or deleleted?

    -derby