Skip to content

Add mssql-tds support for incremental PLP parameter write path - #207

Draft
Shiwani Gupta (shiwanigupta0809) wants to merge 4 commits into
mainfrom
dev/shiwanigupta/plp-write
Draft

Add mssql-tds support for incremental PLP parameter write path#207
Shiwani Gupta (shiwanigupta0809) wants to merge 4 commits into
mainfrom
dev/shiwanigupta/plp-write

Conversation

@shiwanigupta0809

@shiwanigupta0809 Shiwani Gupta (shiwanigupta0809) commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Description

Adds a data-at-execution (streamed) PLP parameter write path to mssql-tds for large nvarchar(max) / varchar(max) / varbinary(max) values in sp_executesql. The value is streamed to the server in chunks instead of being materialized up front, mirroring msodbcsql's incremental PLP write. This is the TDS-layer foundation for a later ODBC SQLPutData / SQLParamData. Scope: mssql-tds only.

What this adds
Streaming entry points on TdsClient, mirroring ODBC's begin/put/end:
begin_sp_executesql — sends the RPC prefix (headers, positional args, materialized params) + the first streamed param's header, parks the half-written message, returns NeedData.
write_streamed_chunk — appends one length-prefixed chunk (empty chunks ignored — a zero-length header is the terminator). Writes the unknown-length opener lazily on the first chunk.
write_streamed_null — marks the current param SQL NULL instead of streaming chunks (the SQLPutData(SQL_NULL_DATA) case).
end_streamed_param — closes the value (PLP_NULL, terminator, or opener+terminator for an empty value), then opens the next streamed param (NeedData) or finalizes and positions on the response (Done).
RpcParameter::data_at_exec() marker; PacketWriter::suspend/resume to park a half-written message across calls; SqlRpc::serialize_prefix to serialize up to materialized params without finalizing.

Testing
Unit (offline mock): header serialization, non-MAX/encrypted rejection, single/multi-chunk framing, empty-chunk skip, two-param lifecycle, materialized+streamed mix, multi-packet chunk, streamed-NULL framing + ordering guards, usage-error guards, and two fault-injection tests for the mid-stream abort.
E2E (live SQL Server): round-trips for nvarchar/varbinary/varchar(max), two params, mixed, multi-row, materialized NULL, streamed NULL, empty value, many small chunks, and connection reuse.

Not covered (deferred)
Always Encrypted on the streamed path (rejected); ODBC SQLPutData / SQLParamData (the next layer).

Related Issues

https://sqlclientdrivers.visualstudio.com/mssql-rs/_backlogs/backlog/mssql-rs%20Team/Features?workitem=46139

Checklist

  • cargo bfmt passes
  • cargo bclippy passes
  • cargo btest passes
  • New/changed functionality has tests
  • Public API changes are documented

@shiwanigupta0809 Shiwani Gupta (shiwanigupta0809) changed the title Dev/shiwanigupta/plp write Add mssql-tds dupport for incremental PLP parameter write path Aug 10, 2026
Shiwani Gupta and others added 4 commits August 10, 2026 21:46
Extend the existing sp_executesql serialize flow with a data-at-execution pause point rather than adding a parallel send path. RpcParameter gains a data_at_exec marker; its serialize writes the parameter header and opens an unknown-length PLP value, then stops, reusing the same write_type_info the atomic path uses. begin_sp_executesql takes a single named_params list (some marked data_at_exec, mirroring ODBC SQL_DATA_AT_EXEC), partitions materialized vs streamed, sends materialized params through the normal path, and streams the rest via write_streamed_chunk/end_streamed_param. PacketWriter suspend/resume parks the in-progress message as owned client state, the write analogue of the incremental read pause.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A failed write_streamed_chunk/end_streamed_param leaves a partial message on the wire, so re-parking it as Active let the caller keep appending to a corrupt message. Add abort_streamed_write to drop the message (state -> Idle, not resumable) and flag the connection for reset, matching msodbcsql's DAE teardown on a failed send. Add fault-injecting unit tests for both abort paths and e2e variations (empty value, many small chunks, connection reuse). Migrate the e2e test file to the current execute/ResultSet API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Defer the PLP length field: the data-at-exec serialize now writes only the parameter header (status + TYPE_INFO), and the length field (PLP_UNKNOWN_LEN opener or PLP_NULL) is written lazily by the streaming driver. This lets a streamed parameter resolve to NULL before any data is sent, matching msodbcsql path 2 (SQLPutData(SQL_NULL_DATA)). Add write_streamed_null(); end_streamed_param emits PLP_NULL for a NULL-signalled param, the terminator for a value, or opener+terminator for an untouched (empty) param. Guard both orderings (chunk-after-null, null-after-chunk). Add unit and e2e tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@shiwanigupta0809 Shiwani Gupta (shiwanigupta0809) changed the title Add mssql-tds dupport for incremental PLP parameter write path Add mssql-tds support for incremental PLP parameter write path Aug 10, 2026
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.

1 participant