Subject Fetching from a non-cursor
Author Dmitry Yemanov
All,

There was a private discussion going on for some time without getting
anywhere close to the agreement, so I'd like to make it public in a hope
to get more opinions.

In all IB/FB versions, it's possible to execute apriori singleton
statements (EXECUTE PROCEDURE, INSERT RETURNING) with either
isc_dsql_execute() or isc_dsql_execute2(out_sqlda=NULL), i.e. without
returning the output values in the same round-trip.

I'm trying to understand how this behavior should be formally treated:

1) as correct and results should be discarded after execution
2) as wrong and error should be thrown (no room to store output values)
3) as an incomplete operation waiting for isc_dsql_fetch() to get the
results

Currently, the latter is true and it's even documented in the API guide.
However, a fetch call against a non-cursor (such singleton statements
don't create an internal cursor and IMO this is absolutely correct)
makes no sense to me. Even if we'd try to utilize that fact and write
some universal code that treats such a statement as a regular cursor and
uses a common keep-fetching-until-EOS-mark approach, then we'd found
that (a) the second fetch call results in a request synchronization
error instead of returning the end-of-stream status, and (b) an attempt
to use DSQL_close for that statement results in a "cursor is not open"
error. Thus you must be aware that only one fetch can be performed and
nothing else is needed (and I don't see this in the documentation).

So, what are the benefits of allowing fetches against non-cursors in
general but throwing errors for the common usage patterns? Was is to
intentionally support option (3) above with a hope that users would
figure out that only single fetch call is necessary? If so, why was it
decided to be better than options (1) and (2)?

Firebird 2.5 has disabled an ability to fetch from a non-cursor, so the
only way to execute singleton statements now is to use
isc_dsql_execute2() with a non-NULL output sqlda. This worked always and
is expected to work forever.

However, if you execute such statements without output sqlda, you have
no chances to get the returned values. This may be treated as a bug and
we have requests to restore the legacy behavior. I have to admit they
are somewhat valid, as the disabled behavior was documented. It's
trivial to restore the old logic, but it turns us back to the question:
what is the point in choosing one bad behavior to replace another bad
one? Maybe we could find a solution without drawbacks?

Keeping the legacy background aside, I'd rather choose option (1) or (2)
to be applied in this case. But maybe I'm completely missing the point
and option (3) is really the good one. If so, I'd suppose issues (a) and
(b) deserve fixing.

Comments anyone?


Dmitry