feat: add support for TABNAME and COLINFO tokens - #1770
Conversation
The server sends TABNAME (0xA4) and COLINFO (0xA5) tokens for queries executed in browse mode (a `FOR BROWSE` clause, `SET NO_BROWSETABLE ON`, or the `sp_cursoropen`/`sp_cursorfetch` API cursor procedures). These tokens describe how the columns of a result set map back to their base tables. Previously, receiving either token crashed the token parser with an uncaught "Unknown type" error, rendering browse mode queries unusable. Now both tokens are parsed and surfaced via new `tabName` and `colInfo` events on `Request`. Fixes #242. Fixes #410. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fxv5h4UMCGJEpjgCKcAxug
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
ReviewSolid, well-scoped fix. It follows the existing Nice test coverage too: fragmented single-byte-chunk parsing, both TDS-version branches for Minor / worth a second look
No security or performance concerns — parsing is bounded, synchronous, and doesn't allocate anything unbounded relative to the token's declared length. Overall this looks safe to merge; the one item above is worth a quick sanity check but isn't blocking. |
Add integration tests for the browse mode scenarios legacy applications commonly produce: multi-table joins (multiple TABNAME entries and per-table column mapping), expression columns (including via a parameterised RPC request), and API cursors via `sp_cursoropen`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fxv5h4UMCGJEpjgCKcAxug
- Parse TABNAME table names using the multi-part format on all TDS versions. The single-string format only existed before TDS 7.1 Revision 1, and servers speaking TDS 7.1 or newer always send the multi-part format - the previous version check misparsed TABNAME tokens on TDS 7.1 connections. This also simplifies the `tabName` event's payload type to `string[][]`. - Throw a descriptive error when a TABNAME or COLINFO token's contents overrun the token's declared length, instead of silently desyncing the token stream on malformed data. - Make the browse mode integration tests independent of the negotiated TDS version. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fxv5h4UMCGJEpjgCKcAxug
Review: TABNAME/COLINFO token supportSolid piece of work overall — clean implementation that follows the codebase's existing token-parser conventions closely, well-documented public API, and unusually thorough test coverage (unit tests for fragmented/malformed input, integration tests against real SQL Server across multiple TDS versions). Correctness
Minor nit (non-blocking)
Security / Performance
Tests
Nothing here blocks merging — nice fix for a long-standing crash bug. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1770 +/- ##
==========================================
+ Coverage 80.86% 80.94% +0.07%
==========================================
Files 90 92 +2
Lines 4887 4948 +61
Branches 929 938 +9
==========================================
+ Hits 3952 4005 +53
- Misses 638 646 +8
Partials 297 297 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Use the same spec revision numbering as the other token parsers in this directory, where COLINFO is s2.2.7.3 and TABNAME is s2.2.7.20. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fxv5h4UMCGJEpjgCKcAxug
ReviewNice work — this is a clean, well-scoped fix for a real crash ( Code quality
Correctness
Test coverageThorough on both levels:
Minor observations (non-blocking)
Security / performanceNo concerns — parsing is a single bounded pass per token, all reads are length-checked before use, and malformed data throws a descriptive error instead of desyncing the stream (a real improvement over silently misinterpreting subsequent tokens). Overall this looks solid and ready to merge pending CI. |
TABNAME and COLINFO tokens
|
🎉 This PR is included in version 20.2.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Fixes #242. Fixes #410.
Problem
SQL Server sends
TABNAME(0xA4) andCOLINFO(0xA5) tokens for queries executed in browse mode — aFOR BROWSEclause,SET NO_BROWSETABLE ON, or thesp_cursoropen/sp_cursorfetchAPI cursor procedures (MS-TDS TABNAME, MS-TDS COLINFO). These tokens describe how the columns of a result set map back to their base tables.Previously, tedious had no parsers for either token, so receiving one crashed the token parser with an uncaught
Unknown type: 164/Unknown type: 165error, taking down the whole process. Verified against tedious 20.0.0 and SQL Server 2022:Changes
src/token/tabname-token-parser.ts— parsesTABNAME: the list of base table names referenced by the query, each parsed into its parts (e.g.['dbo', 'employees']). The multi-part format is used on all TDS versions: it was introduced in TDS 7.1 Revision 1, and all servers speaking TDS 7.1 or newer send it (verified against SQL Server 2022 on a TDS 7.1 connection).src/token/colinfo-token-parser.ts— parsesCOLINFO: per-column ordinal, base table number (a one-based index into theTABNAMElist), theEXPRESSION/KEY/HIDDENstatus flags, and the base column name when the column is aliased (DIFFERENT_NAME).NotEnoughDataErrorretry pattern, and surfaced as new documentedtabNameandcolInfoevents onRequest, following the existingorderevent's pattern. All other token handlers treat them as unexpected tokens, same as every other token type.Tests
test/unit/token/tabname-token-parser-test.ts,test/unit/token/colinfo-token-parser-test.ts): one-part/multi-part/multiple table names, TDS 7.1 behavior, all status flag combinations, aliased columns, tokens arriving fragmented in single-byte chunks, and malformed-token rejection.test/integration/browse-mode-test.ts):FOR BROWSEqueries (including the server-appended hidden key columns being reported viacolInfo), multi-table joins (multipleTABNAMEentries and per-table column mapping), expression columns via a parameterised RPC request, API cursors viasp_cursoropen, and the exactSET NO_BROWSETABLE ONscenario from Token parser for TABNAME (0xA4) non-existent #410. Verified passing against a real SQL Server 2022 instance on TDS 7.1, 7.2, and 7.4 connections.Full unit suite, integration suite,
eslint, andtscall pass.🤖 Generated with Claude Code
https://claude.ai/code/session_01Fxv5h4UMCGJEpjgCKcAxug