Skip to content

Replace tiberius with mssql-tiberius-bridge (Microsoft mssql-tds) - #1

Open
debba wants to merge 6 commits into
mainfrom
feat/mssql-tds-bridge
Open

Replace tiberius with mssql-tiberius-bridge (Microsoft mssql-tds)#1
debba wants to merge 6 commits into
mainfrom
feat/mssql-tds-bridge

Conversation

@debba

@debba debba commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Swaps the TDS client from tiberius to Microsoft's mssql-tds protocol implementation, consumed through its tiberius-compatible bridge API (mssql-tiberius-bridge =0.1.0-preview.3), the same client adopted in Tabularis' feat/sql-server branch.

The SQL surface — introspection, DDL, routines, triggers, value extraction, SHOWPLAN parsing — is unchanged; only the client layer moves.

Client bridge work by @saurabh500, author of mssql-tiberius-bridge and a contributor to mssql-rust.

Client differences handled in the port

  • Connection: Client::connect(&Config) manages its own transport — the manual TcpStream + tokio-util compat layer is gone.
  • Result collection goes through the inner_mut() TdsClient escape hatch, reading result-set metadata directly: the bridge derives columns from rows, which would lose the headers of zero-row result sets (empty SELECTs must keep their grid headers).
  • Affected rows: the bridge's execute().total() counts rows returned, not rows affected, so every DML batch now captures @@ROWCOUNT itself and selects it as a trailing single-cell result set — including the IDENTITY_INSERT path, where the count is captured into a variable before SET IDENTITY_INSERT resets it.
  • No explicit transaction in the identity batch: the TDS client rejects BEGIN TRAN/COMMIT inside an sp_executesql RPC batch (error 3981); a single INSERT is atomic without one, and the TRY/CATCH recovery that clears the session-scoped setting stays.
  • ColumnType normalization: Intn/Floatn/Bitn and the BigVarChar-style names collapse into width-resolved variants (from_tds_with_length); Json and Vector are new; decimals decode through rust_decimal only.
  • Stack size: the TDS client's async call chains produce large futures that overflow tokio's default 2 MiB worker stack in debug builds — workers get a 16 MiB stack and the per-request dispatch future is boxed.

Validation

  • The CI Test job runs cargo build, all 149 unit tests, Clippy with warnings denied, and the formatting check.
  • tests/live_db.rs contains 12 self-seeding JSON-RPC integration tests. The CI Live SQL Server integration job runs them against the SQL Server 2022 service container on every pull-request revision, covering TLS, DDL, CRUD, result-set metadata, affected rows, identity recovery, pagination, error recovery, SHOWPLAN capture, and startup scripts.
  • The CI Security audit job runs RustSec audit checks on its weekly schedule.

Co-authored-by: Saurabh Singh 1623701+saurabh500@users.noreply.github.com

Swap the TDS client to Microsoft's mssql-tds protocol implementation via
its tiberius-compatible bridge API, as adopted in Tabularis'
feat/sql-server branch. The SQL surface (introspection, DDL, routines,
triggers, extraction, showplan parsing) is unchanged.

Client differences handled in the port:

- Connection: Client::connect(&Config) manages its own transport — no
  manual TcpStream / tokio-util compat layer.
- Result collection goes through the inner_mut() TdsClient escape hatch,
  reading result-set metadata directly: the bridge derives columns from
  rows, which would lose the headers of zero-row result sets.
- Affected rows: the bridge's execute().total() counts rows returned,
  not rows affected, so every DML batch now captures @@rowcount itself
  and selects it as a trailing single-cell result set — including the
  IDENTITY_INSERT insert path, where the count is captured into a
  variable before SET IDENTITY_INSERT resets it.
- The IDENTITY_INSERT batch no longer opens an explicit transaction: the
  TDS client rejects BEGIN TRAN / COMMIT inside an sp_executesql RPC
  batch (error 3981), and a single INSERT is atomic without one. The
  TRY/CATCH recovery that clears the session-scoped setting stays.
- ColumnType is normalized by the bridge (Intn/Floatn/Bitn and the
  BigVarChar-style names collapse into width-resolved variants; Json and
  Vector are new); the extraction dispatcher is remapped accordingly and
  decimals now decode through rust_decimal only.
- The TDS client's async call chains produce large futures that overflow
  tokio's default 2 MiB worker stack in debug builds: workers now get a
  16 MiB stack and the per-request dispatch future is boxed.

Validated against a live SQL Server (Azure SQL Edge) over TLS: DDL,
CRUD with identity and composite keys, multi-statement result sets,
empty-result column headers, pagination, DML OUTPUT, error recovery,
and SHOWPLAN_XML parsing.
@debba
debba force-pushed the feat/mssql-tds-bridge branch from c2630d3 to f2afb7b Compare July 29, 2026 20:04
@debba

debba commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Did you check something here: @FabioMalpezzi ?

@debba

debba commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up to the review question: SS-001 reviewed the bridge semantics end to end and hardened fixed-width type normalization, exact numeric/JSON/vector extraction, DML row-count sentinels, identity recovery, and the worker-stack rationale. SS-002 documented the bridge provenance and maintenance/upgrade/fallback policy, pinned its feature set, audited licences and RustSec exposure, and added the scheduled audit job. SS-003 replaced the manual smoke check with 12 self-seeding JSON-RPC tests in tests/live_db.rs and a SQL Server 2022 CI service job covering TLS, DDL, CRUD, result sets and zero-row headers, affected rows, IDENTITY_INSERT recovery, pagination, error/session recovery, SHOWPLAN, and startup scripts. The task validation gate and all 12 live tests are green.

Document the client transition and automated live validation, and record the closing test-count and release-size comparison for PR 1.

Co-authored-by: Saurabh Singh <1623701+saurabh500@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants