Skip to content

Runtime errors in a batch surface as "Expected ColumnMetadata in context" (mssql-tds-preview drain_stream) #37

Description

@egertaia

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

  1. Against any SQL Server, run SELECT 1/0; SELECT 2 through execute_query. It hangs instead of returning error 8134.
  2. 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

  1. 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.
  2. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions