What does a DBIx::* module have to do in order to correctly call
Apache::DBI's no-op version of disconnect() when running under mod_perl with
Apache::DBI?

Below is an example that illustrates a bug I found when using a particular
DBIx:: module.

---
package MyTest;

use strict;
use Apache::DBI;
use DBIx::ContextualFetch;

sub handler
{
  my($r) = shift;

  my $dbh = DBI->connect('dbi:...', 'myuser', 'mypass',
                         { RootClass => 'DBIx::ContextualFetch' });

  $r->send_http_header('text/plain');

  $dbh->do('...any valid sql...') ?
    print 'OK' : print 'Failed';

  $dbh->disconnect; # This calls the wrong disconnect()!

  return 200;
}

1;
---

Run it under httpd -X to further isolate the problem and you'll see that the
first request works, but all subsequent requests fail.  This happens because
the disconnect() call actually calls the "real" disconnect method instead of
the Apache::DBI implementation, which is a no-op.  On the next request,
Apache::DBI happily provides what is now a disconnected $dbh.  Any attempt
to use that $dbh fails, obviously.

If you enable Apache::DBI's debugging output ($Apache::DBI::DEBUG = 1),
you'll see that the correct connect() method is called.  That is, only one
connection is made and then re-used.

So, getting back to my original question, who is at fault here?  Is this an
Apache::DBI bug, a DBIx::ContextualFetch bug, or something else?

One easy "fix" is to add a disconnect() method to DBIx::ContextualFetch that
detects when Apache::DBI is in use.  Example:

sub DBIx::ContextualFetch::disconnect
{
  if($ENV{'MOD_PERL'} && $Apache::DBI::VERSION)
  {
    # Do nothing when Apache::DBI is in use
    return 1;
  }
  
  shift->SUPER::disconnect(@_);
}

But isn't Apache::DBI supposed to be "transparent" and do all this stuff for
me?  Or are all bets off when using a DBIx module?  If so, what is a DBIx
author supposed to do to be a "good Apache::DBI citizen"?

-John



-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html

Reply via email to