[freetds] errors from dblib

James K. Lowden jklowden at freetds.org
Sat Apr 18 18:29:27 EDT 2009


Frediano Ziglio wrote:
> I got some time to compile and run our dblib tests with MS and Sybase
> libraries.

Very nice!  I assume the log contains only bad results, and the others
work OK?  

It looks like we're more compatible with Sybase than Microsoft....

> You can see from attached files. I got dbsqlok fixed for timeout test
> removing these lines
> 
>   marker = tds_peek(tds);

I spent some time looking at this.  I'm not sure we can remove those rows.
 

The code is deeply confused by the cancel packet.  After the CANCEL is
sent, the server acknowledges it.  But first it sends the pending data. 
dbsqlok() sees the ROWFORMAT2 token and returns success.  

With Microsoft/Sybase, does dbsqlok() fail?  (I assume yes.) 

The error isn't tds_peek().  The error is in tds_goodread().  It should
wait for the cancel acknowledgement, wasting any pending data.  Here's the
stack:  

      tds_peek() 
calls tds_get_byte()
calls tds_read_packet()
calls goodread()
calls tds_goodread()
calls tds_send_cancel() on timeout 
	and continues to wait

My log ends with: 

[snip]
query.c:1951:tds_send_cancel: sending cancel packet
net.c:781:Sending packet
0000 06 01 00 08 00 00 00 00-                        |........|

net.c:654:Received packet
0000 04 01 00 4f 00 00 00 00-61 23 00 00 00 01 00 09 |...O.... a#......|
0010 62 65 67 69 6e 74 69 6d-65 00 00 00 09 62 65 67 |begintim e....beg|
0020 69 6e 74 69 6d 65 10 00-00 00 0c 00 00 00 3d 00 |intime.. ......=.|
0030 ae 01 00 00 d1 ef 9b 00-00 20 e0 1b 01 fd 11 00 |........ . ......|
0040 02 00 01 00 00 00 fd 20-00 02 00 00 00 00 00    |.......  .......|

dblib.c:4579:dbsqlok() exits on result token 0x61
[pins]

tds_goodread() then gets a packet: Token 0x61, TDS_ROWFMT2_TOKEN!  
Evidently, the server had it in its buffer, and when the CANCEL packet
arrived, it flushed the buffer and acknowledged the cancel.  The token
sequence:

61: ROWFMT2
23 00 00 00: length 35 bytes
01 00: 1 column
09: label is 9 bytes 
62 65 67 69 6e 74 69 6d 65: "begintime"
00: no catalog
00: no schema
00: no table
09: colname is 9 bytes 
62 65 67 69 6e 74 69 6d 65: "begintime" 
10 00 00 00: status updatable?  
0c 00 00 00: usertype 12
3d: datatype 61
00: no locale

ae: CONTROL
01 00: length 1 byte
00: no fmt data 

d1: ROW
ef 9b 00 00 20 e0 1b 01: 8-byte datetime
 
fd: DONE
11 00: valid count, more coming
02 00: TDS_TRAN_PROGRESS
01 00 00 00: @@rowcount = 1
 
fd: DONE
20 00: acknowledgement of attention (i.e. of cancel)
02 00: TDS_TRAN_PROGRESS
00 00 00 00: no rowcount

Fooey.  I've run out of time today.  I think the answer is that
tds_goodread() should call tds_process_cancel().  

--jkl




More information about the FreeTDS mailing list