TDS 7.0 protocol documentation

This is a try to document the TDS protocol version 7.0. It has a lot of holes, but it contains a lot of new information over the documentation furnished by the FreeTDS project.

All this is obtained through reverse engineering and it would be pretty interesting to match it against the TDS 5.0 documentation, for example. I'm convinced a lot of new information could be discovered. If anyone is interested in doing this, please contact the project. We'll be more than happy to provide you with any documentation we have gathered so far and that cannot be posted here from various reasons.




0x79 (121) TDS_RETURNSTATUS

Return status of a stored procedure. Precedes TDS_DONEPROC packets (or TDS_PARAM packets, if the stored procedure has output parameters).

00 1 79 Packet type (TDS_RETURNSTATUS)
01 4 XX XX XX XX Return status

0x81 (129) TDS_COLMETADATA

Column meta data information for results (column names, types etc.).

00 1 81 Packet type (TDS_COLMETADATA)
01 2 XX XX Number of columns
XX 2 XX XX Column usertype id (0 for base types)
XX 2 XX XX Column flags (0x01=is nullable, 0x02=case sensitive, 0x04|0x08=is writable, 0x10=auto increment, 0x20=computed)
XX 1 XX Column data type
XX X XX XX XX... Column size (variable size data only): 4 bytes for TEXT, NTEXT and IMAGE data, 2 bytes for large data (type & 0x80 != 0), 1 byte for other data
XX 2 XX XX Column table length (TEXT, NTEXT and IMAGE data only)
XX X XX XX XX... Column table name -- fully qualified if database or user different than current (TEXT, NTEXT and IMAGE data only)
XX 1 XX Column precision (NUMERIC and DECIMAL types only)
XX 1 XX Column scale (NUMERIC and DECIMAL types only)
XX 1 XX Column name length
XX X XX XX XX... Column name

Marked fields are repeated for each column.

0x88 (136) TDS_ALTCOLMETADATA (?)

Column meta data information for compute clause.

00 1 88 Packet type (TDS_ALTCOLMETADATA (?))
01 2 XX XX Number of columns
03 2 01 00 Unknown
05 1 XX Number of columns specified in BY clause (e.g. for COMPUTE ... BY a, b this is 2)
XX 2 XX XX Index of column specified in BY clause (number of columns specified by above value)

XX 1 XX Type of aggregation (0x30=STDEV, 0x31=STDEVP, 0x32=VAR, 0x33=VARP, 0x4B=COUNT, 0x4D=SUM, 0x4F=AVG, 0x51=MIN, 0x52=MAX)
XX 2 XX XX Column index (in TDS_COLMETADATA packet)
XX 2 XX XX Column usertype id (0 for base types)
XX 2 XX XX Column flags (?)
XX 1 XX Column data type
XX 1 XX Column size (variable size data types only)
XX 1 XX Column precision (NUMERIC and DECIMAL types only)
XX 1 XX Column scale (NUMERIC and DECIMAL types only)
XX 1 XX Column name length (this is probably always 0, so the next field's existence is questionable)
XX X XX XX XX... Column name

Marked fields are repeated for each column.

0xA4 (164) TDS_TABNAME

Table name information for result columns. Follows immediately after a TDS_COLMETADATA packet. Returned by SELECT .. FOR BROWSE queries.

00 1 A4 Packet type (TDS_TABNAME)
01 2 XX XX Packet size
XX 2 XX XX Table name length
XX X XX XX XX ... Table name (can be fully qualified with no quoting, e.g. 'myDb..my Table')

Marked fields are repeated for each table from whose columns appear in the result (watch packet size for end).

0xA5 (165) TDS_COLINFO

Supplementary meta data information for result columns. Follows immediately after a TDS_TABNAME packet. Returned by SELECT .. FOR BROWSE queries.

00 1 A5 Packet type (TDS_COLINFO)
01 2 XX XX Packet size
XX 1 XX Column index (in TDS_COLMETADATA packet, 1-based)
XX 1 XX Column table index (in TDS_TABNAME packet, 1-based)
XX 1 XX Column flags (0x04=expression, 0x08=key, 0x10=hidden, 0x20=name present)
XX 1 XX Column name length (only present if flags & 0x20 != 0)
XX X XX XX XX ... Column name (only present if flags & 0x20 != 0, the TDS_COLMETADATA contains the label/alias)

Marked fields are repeated for each column coming from some table (watch packet size for end).

0xA9 (169) TDS_ORDER

Column ordering information. Follows after a TDS_COLMETADATA packet (or its associated TDS_COLINFO packet).

The list of columns indexes after which the result is ordered (1-based).

00 1 A9 Packet type (TDS_ORDER)
01 2 XX XX Packet size
XX 2 XX XX Column index

Marked fields are repeated for each column the result is ordered by.

0xAA (170) TDS_ERROR
0xAB (171) TDS_INFO

Error (TDS_ERROR) or message/warning (TDS_INFO).

00 1 AA/AB Packet type (TDS_ERROR/TDS_INFO)
01 2 XX XX Packet size
03 4 XX XX XX XX Error message number
07 1 XX State (error dependent)
08 1 XX Severity (0,1=information, 2-18=warnings-regular errors, 19-25=fatal errors, connection is usually closed
09 2 XX XX Message length
0B X XX XX XX ... Message
XX 1 XX Server name length
XX X XX XX XX ... Server name
XX 1 XX Procedure name length
XX X XX XX XX ... Procedure name
XX 1 XX Line number
XX 1 XX Unknown (usually 0x00)

0xAC (172) TDS_PARAM

Stored procedure output parameter (one such package is returned for each output parameter). Precedes TDS_ENDPROC. WRITETEXT seems to also generate a TDS_PARAM with a formal type of 0x00.

Parameter type seems to be exactly the type submitted (e.g. if the formal parameter is of type NVARCHAR and the actual parameter sent is of type VARCHAR the output parameter will have type VARCHAR).

00 1 AC Packet type (TDS_PARAM)
01 2 XX XX Packet size
03 1 XX Parameter name length
04 X XX XX XX ... Parameter name
XX 1 01 Unknown (seems to always be 0x01)
XX 1 XX Formal type (the type that is declared in the stored procedure header); for TDS_PARAM packets returned by WRITETEXT seems to be 0x00
XX 3 00 00 00 Unknown (seem to always be set to 0x00)
XX 1 XX Actual column type
XX X XX ... Maximum size (only variable size types): 2 bytes for large types (type & 0x80 != 0), 1 byte for all other types (TEXT, NTEXT and IMAGE cannot be parameters)
XX 1 XX Precision (only DECIMAL and NUMERIC data)
XX 1 XX Scale (only DECIMAL and NUMERIC data)
XX X XX ... Actual size (only variable size types): 2 bytes for large types (type & 0x80 != 0), 1 byte for all other types (TEXT, NTEXT and IMAGE cannot be parameters)
XX X XX XX XX ... Parameter value

0xAD (173) TDS_LOGINACK

Login acknowledge.

00 1 AD Packet type (TDS_LOGINACK)
01 2 XX XX Packet size
03 1 XX Unknown (usually 0x01)
04 4 XX XX 00 00 TDS version (e.g. 07 00 00 00 for 7.0)
08 1 XX Database product name length
09 X XX XX XX ... Database product name
XX 4 XX XX XX XX Database product version (e.g. 07 00 02 6F stands for 07.00.0879 -- 879 = (0x02+1)<<8 | 0x6F -- quite weird)

0xD1 (209) TDS_ROW

One result row.

00 1 D1 Packet type (TDS_ROW)
XX X XX XX XX ... Column data (size and format depend on the column's data type)

Marked fields are repeated for each column.

0xD3 (211) TDS_ALTROW

One aggregate row.

00 1 D3 Packet type (TDS_ALTROW)
01 2 01 00 Unknown (probably some count)
XX X XX XX XX ... Column data (size and format depend on the column's data type)

Marked fields are repeated for each column.

0xE3 (226) TDS_ENVCHANGE

Environment change information.

00 1 E3 Packet type (TDS_ENVCHANGE)
01 2 XX XX Packet size
03 1 XX Envchange type (01=Database, 02=Language 03=Charset, 04=Blocksize, 05=Unicode locale id, 06=Unicode comparison style)
04 X XX XX XX ... Envchange info

Envchange type 01=Database change

03 1 01 Database change
04 1 XX New database name length
05 X XX XX XX ... New database name
XX 1 XX Old database name length
XX X XX XX XX ... Old database name

Envchange type 03=Charset change

03 1 03 Charset change
04 1 XX Charset length
05 X XX XX XX ... Charset
XX 2 XX XX Unknown (maybe charset code)
XX X XX XX XX ... Probably old charset (length, then value)

Envchange type 04=Blocksize change

03 1 03 Blocksize change
04 1 XX Blocksize length
05 X XX XX XX ... Blocksize (as string)
XX X XX XX XX ... Probably old blocksize (length, then value)

0xFD (253) TDS_DONE
0xFE (254) TDS_DONEPROC
0xFF (255) TDS_DONEINPROC

End of query execution outside stored procedure (TDS_DONE), end of stored procedure (TDS_DONEPROC) or end of query inside a stored procedure (TDS_DONEINPROC).

00 1 FD/FE/FF Packet type (TDS_DONE/TDS_DONEPROC/TDS_DONEINPROC)
01 2 XX XX Status flags (0x01=more results, 0x02=error, 0x10=valid update count, 0x20=cancel ack)
03 2 XX XX Operation (see below)
05 4 XX XX XX XX Row count (number of rows affected by query)

Values for Operation field (incomplete, uncertain)

B9 IMPLICIT TRANSACTIONS ON
BA IMPLICIT TRANSACTIONS OFF
C0 IF (block start) (?)
C1 SELECT
C3 INSERT
C4 DELETE
C5 UPDATE
C6 CREATE TABLE
C7 DROP TABLE failed
CA ENDIF (block end) (?)
D2 ROLLBACK
D5 COMMIT
D8 ALTER TABLE
DE CREATE PROCEDURE
DF DROP PROCEDURE
E0 END PROCEDURE (the only value for TDS_DONEPROC, but can also be a value for TDS_DONEINPROC if the procedure was called inside another procedure)
E2 USE (database change)
F9 SET (transaction isolation level, language, ...)
FD Syntax error or batch execution interrupted (really not sure)