On Thu, Feb 03, 2005 at 03:49:11PM -0800, David Wheeler wrote:
> On Feb 3, 2005, at 3:30 PM, Tim Bunce wrote:
> 
> >>Should be pretty straight-forward. Are there other events for which
> >>you'd like to add callbacks? OnPrepare, perhaps? OnExecute? OnFetch?
> >
> >Yes, but let's just start with the connect ones for now.
> 
> Okay. It seems pretty simple. Your initial implementation is quite 
> straight-forward:
> 
>       if ($dbh and my $oc = $dbh->{OnConnect}) {
>           $oc->($dbh, $dsn, $user, $pass, $attr) if ref $oc eq 'CODE';
>       }
> 
> The only issue I can think of is that some callbacks will be called 
> much more than others. Do you think that it's a performance issue to be 
> checking for a callback every time the method is called when most 
> people won't use it at all? I don't think I see a way around that, 
> though...

One way I'd had in the back of my mind way to use the DBI dispatcher
to fire the callbacks.

   $h->{Callbacks}->{$method_name} = \&foo; # called on entry
   $h->{Callbacks}->{$method_name} = [ \&foo, \&bar ]; # foo on entry, bar on 
exit
   $h->{Callbacks}->{$method_name} = [ [EMAIL PROTECTED], \&bar ]; # each of 
@subrefs on entry, bar on exit

that way _every_ method would get pre and post call hooks for free.
If a handle has no callbacks the cost would be unmeasurable (just
a bit flag test in the dispatcher).  If a handle has any callbacks
then the added cost for calling a method that doesn't have a callback
would just be one hash lookup.

How's your C coding? :)

This approach doesn't directly support callbacks that need to fire
_within_ a method, such as the proposed OnConnectCached firing only
if connect_cached() does _not_ need to call connect().

[For that case you could have an pre-connect_cached callback that
temporarily installs a connect callback which sets a flag, and a
post-connect_cached callback that resets %$attr if the flag's not set.
But that's getting quite baroque!]

Alternatively connect_cached() could call a new method in that
situation and the hooks could be applied to that. But that's
relatively expensive and it would be 'odd' for that method to be
called with the $attr that was passed to connect_cached().

Alternatively some pseudo-method-names could be supported in the
$h->{Callbacks} hash (ie "connect_cached.reused") and the relevant
methods could check for and call them directly. Then the extra code
in connect_cached would something like this:

  if (my $cb = $dbh->{Callbacks}) {
      my $oc = $cb->{"connect_cached.reused"};
      $oc->($dbh, $dsn, $user, $pass, $attr) if ref $oc eq 'CODE';
  }

Umm, food for thought...

Tim.

Reply via email to