Found while testing #34.
Problem
When one statement in a batch fails with a runtime error and a later statement in the same batch returns rows, the driver can't parse the rest of the response. The user sees a misleading error instead of the real SQL error:
SQL Server connection failure: IO error: Expected ColumnMetadata in context
This happens at every compatibility level.
Cause
mssql-tds-preview's drain_stream (src/connection/tds_client.rs) reads every token after an ERROR token with ParserContext::None and doesn't handle COLMETADATA. So when a later statement returns a result set, the ROW tokens that follow can't be parsed, because the parser has no column metadata for them.
The latest release (0.1.0-preview.9) has the same drain_stream. We pin =0.1.0-preview.1.
Where it hits the plugin
update_record / insert_record: the plugin appends SELECT CAST(@@ROWCOUNT AS BIGINT) AS [__tabularis_affected_rows] to the DML (src/driver/helpers.rs). Any runtime error in the DML (arithmetic overflow, constraint violation, etc.) is followed by that SELECT, so it always takes this path and the real error is lost.
execute_query: SELECT 1/0; SELECT 2 hangs.
Repro
- Against any SQL Server, run
SELECT 1/0; SELECT 2 through execute_query. It hangs instead of returning error 8134.
- Update a
REAL column to a value that overflows (for example 3.4028235e38 at compatibility level below 130, Msg 232). It returns Expected ColumnMetadata in context instead of the overflow error.
Options
- Upstream fix in
mssql-tds-preview (https://github.com/saurabh500/mssql-rs): make drain_stream handle COLMETADATA (or skip result sets correctly) after an error.
- Plugin-side workaround: avoid batches where a result set can follow a failing statement. For DML, that could mean getting the row count from the
DONE token instead of a trailing SELECT @@ROWCOUNT, if the crate exposes it.
Option 1 is the real fix; option 2 would at least surface the right error for update_record / insert_record until upstream ships one.
Found while testing #34.
Problem
When one statement in a batch fails with a runtime error and a later statement in the same batch returns rows, the driver can't parse the rest of the response. The user sees a misleading error instead of the real SQL error:
This happens at every compatibility level.
Cause
mssql-tds-preview'sdrain_stream(src/connection/tds_client.rs) reads every token after anERRORtoken withParserContext::Noneand doesn't handleCOLMETADATA. So when a later statement returns a result set, theROWtokens that follow can't be parsed, because the parser has no column metadata for them.The latest release (
0.1.0-preview.9) has the samedrain_stream. We pin=0.1.0-preview.1.Where it hits the plugin
update_record/insert_record: the plugin appendsSELECT CAST(@@ROWCOUNT AS BIGINT) AS [__tabularis_affected_rows]to the DML (src/driver/helpers.rs). Any runtime error in the DML (arithmetic overflow, constraint violation, etc.) is followed by thatSELECT, so it always takes this path and the real error is lost.execute_query:SELECT 1/0; SELECT 2hangs.Repro
SELECT 1/0; SELECT 2throughexecute_query. It hangs instead of returning error 8134.REALcolumn to a value that overflows (for example3.4028235e38at compatibility level below 130,Msg 232). It returnsExpected ColumnMetadata in contextinstead of the overflow error.Options
mssql-tds-preview(https://github.com/saurabh500/mssql-rs): makedrain_streamhandleCOLMETADATA(or skip result sets correctly) after an error.DONEtoken instead of a trailingSELECT @@ROWCOUNT, if the crate exposes it.Option 1 is the real fix; option 2 would at least surface the right error for
update_record/insert_recorduntil upstream ships one.