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.