Skip to Content.
Sympa Menu

freetds - Re: [freetds] Server - Problems with TDS 4.2 COLFMT token

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "James K. Lowden" <jklowden AT schemamania.org>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] Server - Problems with TDS 4.2 COLFMT token
  • Date: Fri, 14 May 2004 00:42:07 -0400

On Thu, 13 May 2004, Steve Kirkendall <skirkendall AT dsl-only.net> wrote:
>
> Most of my success in writing a tiny SQL server has come with TDS 5.0.
> Now I'm making another attempt at using TDS 4.2, and I'm running into a
> problem. It seems that the client (the FreeTDS ODBC driver on a Windows
> machine) is parsing the 0xA1(COLFMT) token incorrectly. It keeps
> reading column info past the end of the token.

OK, first you send 0xA0, from which the client derives the number of
columns. That looks fine, and, you're right, the information is not
repeated in the next packet.

Then you want to send 0xA1. The best reference I know is
src/tds/token.c::tds_process_col_fmt(). Based on that, for N columns the
packet consists of N frames of:

bytes type name
----- ---- --------------
2 int-16 usertype
2 mask flags
[Sybase uses a 4-byte usertype, no flags]
1 int-8 column_type
0/1/4 int column_size

[If column_type requires a 4-byte width descriptor, that implies the
following field is the length of the table name (!)]
n char[n] table name, n == characters in table name.

[If column_size is a 1-byte field, it's the width of the column, for
variable-size and nullable datatypes.]
1 int-8 column_size

sp_datatype_info normally has these metadata ('-' indicates it's missing
from your 0xA0 packet, which you presumably intend):

col name type size varies
------ ------------------ -------- ------ ------
1 TYPE_NAME char 255 1
2 DATA_TYPE smallint 2 0
3 PRECISION int 4 1
4 LITERAL_PREFIX char 32 1
5 LITERAL_SUFFIX char 32 1
6 CREATE_PARAMS char 32 1
7 NULLABLE smallint 2 1
8 CASE_SENSITIVE smallint 2 0
9 SEARCHABLE smallint 2 0
10 UNSIGNED_ATTRIBUTE smallint 2 1
11 MONEY smallint 2 0
12 AUTO_INCREMENT smallint 2 1
13 LOCAL_TYPE_NAME char 255 1
- 14 MINIMUM_SCALE smallint 2 1
- 15 MAXIMUM_SCALE smallint 2 1
- 16 SQL_DATA_TYPE smallint 2 0
- 17 SQL_DATETIME_SUB smallint 2 1
- 18 NUM_PREC_RADIX int 4 1
- 19 INTERVAL_PRECISION smallint 2 1
- 20 USERTYPE smallint 2 1

So we should expect 13 columns in your 0xA1. (In your 0xA0, "PRECISION"
is unnamed.) After that, the client would expect 0xD1 (row data). And,
indeed, that's what your're sending. I parse your packet thus:

a1 46 00
00 00 00 00 2f 20
00 00 00 00 34
00 00 00 00 38
00 00 00 00 2f 20
00 00 00 00 2f 20
00 00 00 00 2f 00
00 00 00 00 34
00 00 00 00 34
00 00 00 00 34
00 00 00 00 34
00 00 00 00 34
00 00 00 00 34
00 00 00 00 2f 20

ae 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^^
This is the next token.

d1 04 43 48 41 52 01 00 00 00 00 00 01 27 01 27 00 00 00 00 00 [...]
^^
Here's the start of the row data.

By way of comparison, here's the same answer from a 7.0 server:

a1 73 00
02 00 01 00 27 ff
06 00 08 00 34
0d 00 01 00 26 04
02 00 09 00 27 20
02 00 09 00 27 20
02 00 09 00 27 20
0d 00 01 00 26 02
06 00 08 00 34
06 00 08 00 34
0d 00 09 00 26 02
06 00 08 00 34
0d 00 09 00 26 02
02 00 01 00 27 ff
0d 00 01 00 26 02
0d 00 01 00 26 02
06 00 08 00 34
0d 00 09 00 26 02
0d 00 01 00 26 04
0d 00 01 00 26 02
0d 00 01 00 26 02

a9 04 00 02 0c 0b 00

I don't know why, but tds_process_col_fmt() appears not to recognize when
it has read 13 columns' worth of data. It is as though it loses track of
how many there are. It sees a "14th" column:

ae 0d 00 00 00 00
00 00 00 00 ...

and claims to find a type = 0. Really, it should just punt at that point.


If I were you, I'd get out gdb or put in some logging statements. I'd
suspect memory corruption of some kind, but I really can't guess where.

> Also, the description of the COLFMT token in "tds.html" seems to be
> way off. It shows 0xA1 as containing column names (duplicating the
> names sent via 0xA0(COLNAME) tokens) but really it just contains four
> NUL bytes, a type byte and optionally a length byte for each column...
> assuming the tds_send_colinfo() function in src/server/server.c is
> correct.

Thanks for pointing that out. It's been a looong time since I looked at
the 4.2 packets.

--jkl




Archive powered by MHonArc 2.6.24.

Top of Page