Skip to Content.
Sympa Menu

freetds - Re: [freetds] ODBC handling of raiserror

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "James K. Lowden" <jklowden AT freetds.org>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] ODBC handling of raiserror
  • Date: Sun, 11 Feb 2007 01:06:41 -0500

James K. Lowden wrote:
> IMO SQLExecute should
> return SQL_ERROR only when it *failed* e.g. couldn't send the SQL to the
> server or the server could not execute the SQL. If we get a TDS_ERROR
> packet followed by a DONE packet, SQLExecute should fail. Otherwise, it
> should return WITH_INFO.

I am concerned that our ODBC result processing is weak. I think part of
the reason it's weak is that resultset processing is implemented in the
client libraries. Consider:

1. ct-lib, db-lib, and ODBC all do fundamentally the same thing.
2. Each one uses libtds, each in its own way.
3. It would be possible to write any one in terms of the other. E.g., it
would be possible to write an ODBC driver that uses db-lib instead of
libtds.

I think we should define an API for libtds that can be used by both ODBC
and db-lib. I think they share functionality that could usefully be in
libtds. I would like feedback on the idea.

Consider this table:

db-lib ODBC libtds (proposed)
-------------- -------------- -----------------
dbexecsql SQLExecute tds_execsql
dbresults SQLMoreResults tds_results
dbnextrow SQLFetch tds_nextrow

The trickiest part, I think we all agree, is DONE handling, which would be
in tds_nextrow. A TDS_ROW packet may be followed by:

1. Another TDS_ROW (easy), or
2. TDS_DONE (also easy), or
3. TDS_ERROR / TDS_EED, or
4. Any number of compute rows, output parameters, and return status.

(Normally, any errors about a query are returned before the data, but
sometimes the error occurs within a row e.g. "select type, type/(type-108)
from systypes where type > 100". After encountering such an error, the
server stops sending rows for that query.)

Currently, there is too much stream handling -- too much awareness of what
tokens have been received or are expected -- in the client libraries, and
too much state information is shared between them and libtds. db-lib and
ODBC have *very* different ideas about buffering and cursors, but they
both need to process *exactly* the same packets. Let's do the packet
processing (stream handling) in libtds, once and for all.

Consider just these lines from dbnextrow and SQLFetch:

db-lib:
const int mask =
TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE;
...
switch (tds_process_tokens(tds, &res_type, NULL, mask)) {

ODBC:
odbc_process_tokens(stmt,
TDS_RETURN_ROW|TDS_STOPAT_COMPUTE|TDS_STOPAT_ROW);

None of this is necessary or desirable!

tds_nextrow would read a TDS_ROW packet. It would peek at the stream, and
keep processing it until it saw a DONE packet. For "after regular
results" data, it would populate a structure that the client library could
query at its leisure.

My goal is to remove every call to tds_process_tokens from the client
libraries. Eventually, the client libraries would call only a few libtds
functions, all defined in src/tds/api.c. There would be less state
information to share. The read-until-mask logic would go away. The
"what's next" states would be simplified to 1) row pending, 2) results
pending, or 3) nothing pending. To get "post results" data (e.g. return
status), the client library wouldn't even examine the stream; it would
examine its own data structure to see if it was populated by tds_nextrow.


I consider this to be a logical next step for libtds. Some time ago we
removed all the endianism from the client libraries and made sure that
issue was completely handled in libtds. More recently Frediano moved all
network calls to net.c. I propose to move all the stream-state
information and all knowledge of token sequences into libtds. All that
would remain in the client libraries would be error checking and
"personalities". Plenty enough, those.

What do you think?

--jkl




Archive powered by MHonArc 2.6.24.

Top of Page