On Wed, Mar 31, 2010 at 10:14:04AM -0700, David E. Wheeler wrote:
> Fellow DBIers,
> 
> I was just discussing writing a callback on connect() to change
> authentication (my correspondent wants to use realm files). But then I
> discovered to my disappointment that there is no support for callbacks
> on connect(). This makes sense, frankly, since the method is called
> before the callbacks are applied, and callbacks execute before the
> method, not afterward (at least for now).

Yeap.

> But I've found great use by adding callbacks on connected(), so that
> they execute just after a connection. So I was wondering how folks
> felt about the idea of adding a connecting() method that executes just
> before the DBI tries to connect to the database? I think this would be
> a nice complement to connecting(), and instantly make a simple
> interface for adding a pre-connection callback, too.

DBI->connect effectively does:

    $drh = DBI->install_driver($driver);
    $dbh = $drh->connect(...);

Assuming we added a $dbh->connecting() method, how would it be called,
and how would the callback have been enabled prior to calling it?

Why not register the callback on the driver:

    DBI->install_driver('Pg')->{Callbacks}{connect} = ...;

That'll affect all subsequent connects using that driver and won't work
with proxy drivers like Gofer, which is why DBI docs discourage messing
with driver handles, but it may fit your needs.

Tim.

p.s. On a slight tangent: most drivers implement $dbh->connect with code like:

    my $this = DBI::_new_dbh($drh, ...);

It's long bugged me that this isn't a method call.
In http://cpansearch.perl.org/src/TIMB/DBI-1.609/TODO_2005.txt
(which is old but still has useful information) I suggested:

    Rework handle creation to use methods:
    Maybe $h->new_child(\%handle_attr)
        dr::connect =>
            $dbh = $drh->new_child(\%attr);
            $dbh->connect(...)  - calls $dbh->reset()
    &   db::prepare =>
            sub ...::db::prepare {
            my ($dbh, $sql, $attr) = @_;
            $sth = $dbh->new_child($attr)
            my @statements = $dbh->preparse($sql);
            $sth->{PendingStatements} = \...@statements if @statements > 1;
            $sth->prepare( shift @statements ) or return;
            return $sth;
        }

If we did that (and handled backwards compatibility somewhow)
then presumably new_child() could apply the Callbacks attribute
which would then fire on the subsequent $dbh->connect call.

Reply via email to