On Tue, May 04, 2004 at 01:41:56PM -0400, Jeff Urlwin wrote:
>
> > =head2 Skipping Non-SELECT Results
> >
> > When executing stored procedures, for example, applications
> > are sometimes only interested in the results of SELECT
> > statements executed by the procedure and not in any INSERTs,
> > DELETEs, or UPDATEs that it may also have executed. So it
> > would be helpful to make it easy to skip those non-SELECT
> > results (as DBD::ODBC currently does).
>
> Which, in hindsight, I think I should never have done ;)
>
> However, it does have the affect of making complex stored procedure calls
> more "transparent" as to what they do, if they simply return a result at the
> end. (i.e. call some_vendor_supplied_complex_proc() and only get the output
> results, rather than the intermediate results -- which may vary per call).
>
> It also made the end-user's life easier, retrieving the values from stored
> procedures, since they are not returned until after the last statement has
> returned it's result set.
Yes. I appreciate the value of it and I tried hard to find a way to
make it work efficiently. (See below.)
> > A complete implementation of skipping non-SELECT results
> > would require that execute() should call more_results()
> > whenever NUM_OF_FIELDS was 0. (It can't be limited to apply
> > only to "batches" because many drivers can't tell if there
> > are multiple results until they try to fetch them.)
> >
> > So, at least for now, this feature won't be part of the DBI
> > but, as always, drivers are free to implement their own
> > mechanisms under the control of driver-specific attributes.
>
> I may decide to "break" current behavior in, hiding behind the DBI
> specification...
> Note that adding the "auto-skip" support, made DBD::ODBC more difficult, I
> think -- that and, I believe I get varying results based upon NUM_OF_FIELDS
> == 0. I have to recheck that code a bit.
I'm not sure what you're saying there.
> [snip]
>
> > I have left a $sth->{SkipNonSelect} attribute in this example
> > but, as discussed above, I'm not proposing to include it in the spec.
>
> Hmm...I hope you leave it in so that I can use it to attempt to keep
> compatible with what I have mangled already. Can you make it an optional
> attribute for drivers to implement? (I.e. SkipNonSelect defaults to undef
> or 0. If you set SkipNonSelect to 1, and the driver supports it, it will
> stay as 1, however, if the driver doesn't support it, it will remain undef
> or 0.)? Just a thought to give the end-user feedback if it's supported or
> not.
Making it an optional feature would work, especially as batch support
varies so much between databases anyway.
I was thinking in terms of having the Driver.xst code check for the
SkipNonSelect flag and NUM_OF_FIELDS==0 and then call more_results()
for you. So the driver internals whouldn't need to handle it directly.
But I figured many apps would want to leave SkipNonSelect enabled but
that would make execute() calls more expensive.
If, instead, I just document the SkipNonSelect flag but leave drivers
to handle it internally, if they want to, then drivers can do so in
a more efficient way.
Umm, but now it dawns on me that I can have Driver.xst call a
dbd_more_results() C function and skip the method call overhead.
> [more snipping]
> >
> > =head2 Active
> >
> > The interaction between the Active attribute, the finish
> > method, and row fetch errors needs to be reconsidered in
> > relation to batches.
> >
> > The finish() method will discard I<all> pending result sets.
> > The more_results() method automatically discards any
> > unfetched rows from the current sub-statement.
> >
> > The statement handle Active attribute is used to indicate
> > that there is active state on the database server associated
> > with this handle. In other words that there is more data to
> > be fetched, and that
> > finish() should be called before the statement handle is destroyed.
> >
> > The principles described at the start mean that
> > $sth->{Active} I<should> go false at the end of I<each> set
> > of SELECT results. However, that goes against the definition
> > of what Active means because in a batch there I<is> still
> > active state on the server.
> >
> > So Active will remain true while there is active state on the
> > server. This looser definition gives more flexibility to the
> > driver and should discourage applications from making
> > inappropriate assumptions.
> >
> > The original principle still applies: Active should
> > automatically go false after results from a statement handle
> > are fully consumed, and $sth->finish can be used to force it
> > to false if required.
> >
> > This means:
> >
> > Active should be false after execute() of a single non-SELECT
> > statement, or a stored procedure that returns a single non-SELECT
> > statement row count. Applications shouldn't need to call finish()
> > in these cases.
> >
> > Active can be true for a non-SELECT sub-statement (within a batch),
> > which isn't the case currently. But no code should be
> > relying on that.
>
> Hmmm...I'm glad you say "Can be true" in this paragraph above, but I'm
> concerned it would be mis-read as "should be" or "shall be". I believe we
> have to treat Active differently in batches. It should have a definition
> for the current 'sub-statement'. That's all it can be without getting into
> trouble -- unless I'm missing something.
I'm not quite sure what you're saying so I'll reword that last paragraph
and see what you make of it :)
Active I<will> be true for a non-SELECT sub-statement I<if> it is
not the last sub-statement in the batch.
Tim.