On Oct 26, 2009, at 1:59 PM, Tim Bunce wrote:

It output nothing. When I uncommented that second-to-last line, it output "Set in STH". So it seems that a callback added to the dbh for a statement method name does not end up getting passed on to the statement handle. So I guess the Callbacks attribute is not passed on to statement handles created
for the database handle?

Yeap.

Seems a shame…

I recall thinking about it but opting not to. I can't recall why though.
Possibly just to err on the side of caution.

I'm open to persuasion.

I understand the caution, but it does seem inconsistent to me. I'd really like to be able to set STH callbacks once in a DBH and be done with it, just as a I can any other DBH attributes that also apply to STHs.

One other thing: It's nice that the callbacks execute before the method call, so that you can disable it by undefing $_. But it'd be equally handle
to have callbacks after the method call.

Yes, I'd always planned for that but never had a need to implement it myself. I'd figured the callback code ref could, optionally, be an array ref and if so, the second element would be the callback to call on method return.

Yes, I saw that in our [exchange](http://markmail.org/message/m2lr3n74nluh52jn ) in 2005. What would it take to make this happen?

Note that a post-prepare() callback could be used to implement
inheritance of Callbacks.

(If the method attributes of prepare($sql, \%attr) were applied to the
newly created sth, in the same way as connect(), then a pre-prepare
callback could be used to pass down the $dbh->{Callbacks} to the $sth.)

Oh, that kind of callback. I'd love to see attributes to prepare passed on to the sth. It makes perfect sense to me. I note that you thought in 2005 that it wouldn't happen before DBI2, but since that's probably another 5 years away at this rate…

For example, I'd love to be able
to create a callback on a statement handle to convert a timestamp column to
a DateTime object:

   $sth->{PostCallbacks}{fetch} = sub {
       my ($sth, $row) = @_;
       $row->[3] = DateTime::Format::Pg->parse_datetime($row->[3]);
   };

That particular example is potentially risky - or at least unportable.
What if the driver doesn't implement a higher-level method (like
fetchrow_hashref or fetchall_* etc) in terms of fetch?

Is that not a problem for any callback on any driver-implemented method?

I've always felt the best way to do that kind of thing would be to tie() the individual elements of the row buffer array - but I've never needed
to do it myself so never explored it.

Well, and tie is pretty hackish IMHO. But let me cite another example. In our prior discussions, you [wrote](http://markmail.org/message/dgnpmnzkk4g532lc ):

Note that sth callbacks, for example, give you a relatively clean way to set the UTF8 flag on fetched data.

Given that callbacks execute before data is fetched, how, exactly, could this be done with the current implementation? I would exepct something like this (using post-callbacks):

   $sth->{PostCallbacks}{fetch} = sub {
       my ($sth, $row) = @_;
       Encode::_utf8_on $_ for @$row;
       return;
   };

But that obviously won't work.

Another issue to keep in mind is that there's only one callback per method.
In other words there's no way for multiple callbacks for a single
method to coexist on a handle. That limits the usefulness of Callbacks
in general.

Maybe. I don't think it's like JavaScript where you have any number of libraries all adding their callbacks to global DOM elements. We have lexical handles that can be modified only in scope. I don't think there's much need to worry about supporting multiple callbacks until someone needs them. And even then I'd suggest:

    if (my $cb = $sth->{Callbacks}{fetch}) {
        $sth->{Callbacks}{fetch} = sub {
            $cb->(@_);
             ... #other stuff ...
        }
    } else {
        $sth->{Callbacks}{fetch} = sub {
             ... #other stuff ...
        }
    }

I dont think additional infrastructure is needed until the cowpaths demand it.

Ideally I'd like to see an abstract interface for managing callbacks,
rather than the current "stuff it in a hash". That way future support
for post-method callbacks and multi-callbacks per method and handle
could be added without exposing (and locking us into) particular
implementation details.

Do you have something in mind? What would it look like?

Best,

David

Reply via email to