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