On Sat, Jan 26, 2013 at 07:21:56PM +1100, Peter Rabbitson wrote:
> On Fri, Jan 25, 2013 at 10:59:46PM +0000, Tim Bunce wrote:
> > On Fri, Jan 25, 2013 at 09:40:07PM +1100, Peter Rabbitson wrote:
> > > On Fri, Jan 25, 2013 at 10:17:11AM +0000, Tim Bunce wrote:
> > > > Re https://rt.cpan.org/Public/Bug/Display.html?id=82942
> > > > 
> > > > The key question: is this a bug or a feature?
> > > 
> > > Can you walk me through your thought process on what makes this a feature?
> > > Not trying to be difficult, I am just having trouble seeing the use-case 
> > > ;)
> > 
> > A cache statement is cached because the user asked for it to be cached.
> 
> Perhaps there is a mismatch of understanding here. For me the only 
> benefit of using a cached statement is to avoid a prepare. Executing the 
> *same* statement with the *same* values *without* rebind does not seem 
> to be possible in the first place (according to the docs at least):

I don't follow you here Peter. This should work fine:

    $sth = $dbh->prepare_cached($sql);
    $sth->bind_param(1, $foo);
    $sth->execute();
    $sth->execute();
    $sth->execute();
    $sth->execute();

> >     $sth = $dbh->prepare_cached($sql);
> > 
> > I think it's reasonable to assume that binding a reference value to a
> > placeholder of a cached statement handle will cause the ref count of the
> > value to increase.
> > 
> >     $sth->bind_param_inout(1, \@foo);
> 
> Yes, otherwise it may get lost before the consequent execute().

> > So, the question then is what options do we have for "fixing" it?
> > 
> > The most obvious thing to do would be to weaken the refs in
> > values %{ $sth->{ParamValues} }. That could be done in the
> > application, so a DBI change isn't strictly needed.
> 
> That won't work as per my above remark. Now that I think of it your 
> cached statements are not copies, they are extra refs. Which means that 
> you can't really weaken it in the cached ones only.
> 
> > If it's agreed that the DBI should weaken the refs then
> > we'd need to discuss when. As soon as they're bound?
> > I can imagine cases where values are bound in a lexical scope
> > that's exited before the $sth->execute() call, so that's not safe.
> > 
> > After the execute()? No, execute might be called again.
> 
> If this is possible - docs/tests should reflect that (I am still fuzzy 
> on what the semantics are, hence no patches to offer).

Does the example above clarify it?

> > After finish()? Maybe. The docs for finish is already say "Calling finish 
> > ...
> > may also make some statement handle attributes (such as NAME and TYPE)
> > unavailable if they have not already been accessed (and thus cached)."
> > It seems reasonable to extend that to say that any references in
> > ParamValues will be weaked.
> 
> After finish() won't work, because the app (DBIC in this case) doesn't 
> know to call finish() before garbage collection, which never happens 
> because of the circular ref. Augh!

> > Bound values are meant to persist across finish(), so there are still risks.
> 
> Also undocumented ;)

Bound values are spec'd to persist in general. No need to mention finish().

> > I'm not keen on adding another attribute just to control this edge case.
> 
> No, we shouldn't. After running through your thought process (thank you) 
> it is clear this can not be fixed with conventional approaches. I need 
> to wrap up Variable::Entangled that we specced out with Aristotle at 
> last YAPC::EU but then neither of us got to completion.
> 
> In the meantime stalling the bugreport with a link to this discussion 
> sounds sane.

Will do.

Tim.

Reply via email to