DBD-Sybase: number of rows affected with freetds

Bob Kline bkline at rksystems.com
Tue Jul 18 01:18:58 EDT 2000

On Mon, 17 Jul 2000, Bob Kline wrote:

> I took a look myself at the ctlib code.  According to the Sybase
> documentation, a call to ct_res_info with CS_ROW_COUNT as the second
> argument (CS_INT type) is supposed to obtain "The number of rows
> affected by the current command."  And it looks as if the DBD driver has
> a call to ct_res_info with that argument, expecting the documented
> result. However, the freetds version of ctlib is pulling the value from
> the row_count member of the TDSRESULTINFO structure (which holds the
> number of rows in a result set) instead of from the rows_affected member
> of the TDSSOCKET structure (whose name makes its purpose clear).  This
> is sounding like a promising candidate for the cause of at least part of
> the problem.  What do you think, Brian?
> However, that's not the only thing I found.  I also noticed that even if
> that problem were fixed, it doesn't appear as the call to ct_res_info
> would get invoked, because the DBD C code where this would happen is in
> a loop (see st_next_result() in dbdimp.c) whose test reads:
>     while ((retcode = ct_results(cmd, &restype)) == CS_SUCCEED) { ... }
> and the first call to ct_results gets back CS_END_RESULTS instead of
> CS_SUCCEED so the imp_sth->numRows value is left as it was initialized:
> as -1.
> So it looks like there may be two problems that need fixing.  I'm not
> sure where the second problem should be fixed, but it's tempting to
> think that if the loop referred to above were altered so that its test
> continued:
>         || retcode == CS_END_RESULTS) { ....
> this would fix the original poster's problem (assuming the first bug
> also got fixed).

Cranking up the microscope another power or two ....

The tempting fix suggested above for the second problem started nagging
at the back of my mind, since the existing DBD code works fine with
Sybase's implementation of ctlib.  So I took a closer look at what was
happening under that implementation (never underestimate the value of
DBI->trace()), and here's what I found.

Inside the loop described above, for the first call to ct_results(), the
return value is CS_SUCCEED, and the result type is CS_CMD_SUCCEED, which
indicates that a command which does not return data, such as an INSERT
or UPDATE statement, has completed successfully.  The second call to
ct_results() also returns CS_SUCCEED, with a result type of CS_CMD_DONE,
which indicates that the results of the current logical command have
been completely processed, and it is safe to invoke ct_res_info().  Only
on the third call to ct_results() is the return value CS_END_RESULTS,
which breaks out of the loop.  There is a misleading entry in a table of
return values in the ctlib docs, which says that a return value from
ct_results() of CS_SUCCEED means a "result set is available for
processing."  This is true in some cases, but clearly (borne out by the
text and the sample code elsewhere in the Sybase documentation) not for
all cases.  According to the Sybase docs, the sequence described here is
what a client program should expect to see following a successfully
executed INSERT or UPDATE statement.

So, Edmund, it looks as if you can solve your problem with a patch to
freetds/src/ctlib/ct.c which addresses both of the problems described
above, without any need to persuade the DBD maintainer to modify

Hope this helps.

Bob Kline
mailto:bkline at rksystems.com

More information about the FreeTDS mailing list