microsoft / microsoft/mssql-rs

Preserve character output buffers when SQLGetData returns NULL binary values

Open
#555 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Rust
Stars
53
Forks
14
Avg merge
1d 15h
Merged PRs (30d)
137

Description

Describe the bug

SQLGetData on a NULL binary column writes a character terminator into the caller's output buffer in mssql-odbc, while retail msodbcsql leaves the buffer untouched. Both return SQL_SUCCESS and SQL_NULL_DATA. This predates the binary-to-hex conversion in #530 and should be handled separately from that feature.

Steps to reproduce
  1. Connect to a test SQL Server through the ODBC Driver Manager.
  2. Execute SELECT CAST(NULL AS VARBINARY(MAX)) and fetch the row.
  3. Fill a writable 32-byte buffer with 0x7E.
  4. Call SQLGetData for column 1 with SQL_C_CHAR, buffer length 32, and a valid indicator pointer. Repeat on a fresh row with SQL_C_WCHAR.
  5. Compare the return code, indicator, and buffer contents against retail msodbcsql. The same difference was measured with BINARY(3) and VARBINARY(8).
Expected behavior

For intended parity with retail msodbcsql, return SQL_SUCCESS and SQL_NULL_DATA without modifying the character output buffer. Confirm the behavior on the CI-pinned retail 18.6.2.1 build before implementing the follow-up; the runtime comparison below used 18.6.1.1.

Actual behavior

For SQL_C_CHAR, mssql-odbc changes the first byte to zero. For SQL_C_WCHAR, it changes the first two bytes to zero. The remaining bytes retain 0x7E. Retail msodbcsql 18.6.1.1 (SQL_DRIVER_VER=18.06.0001) leaves every byte untouched in both cases. Return code 0 and indicator -1 agree between drivers.

Version

PR #530 at 3b882725, with main through 0d431b71 merged before the measurement. The observed NULL-output behavior is pre-existing, not introduced by the hex conversion.

Affected crate

mssql-odbc

Environment

Windows x64, SQL Server 2025 test container, Windows ODBC Driver Manager. Reference DLL product version 18.6.1.1, SQL_DRIVER_VER=18.06.0001. Rust driver reports SQL_DRIVER_VER=18.6.2.1.

Additional context
  • Raised in https://github.com/microsoft/mssql-rs/pull/530#discussion_r3984006173.
  • Rust: mssql-odbc/src/api/get_data.rs::write_captured_column handles ColumnValues::Null before conversion and calls copy_with_nul for character targets. Audit other NULL delivery branches and bound delivery for consistent behavior before changing anything.
  • Reference source: Sql/Ntdbms/sqlncli/odbc/sqlcdata.h, ColDataRetriever::InternalGetColData: fIsNullData sets SQL_NULL_DATA and jumps to Return2, bypassing character termination under Return3.
  • BinToCharLiveTest.NullVarbinaryMaxReportsNull intentionally asserts only the shared NULL indicator and runs on both drivers. Keep it unskipped; add a targeted buffer-content parity regression with the follow-up fix.
  • This is a deferred implementation gap, not an approved permanent deviation. The repository's deliberate-deviation registry explicitly excludes such gaps.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in mssql-odbc/src/api/get_data.rs at write_captured_column, then audit the other NULL-delivery and bound-delivery branches. Confirm the behavior against the CI-pinned retail 18.6.2.1 driver, keep BinToCharLiveTest.NullVarbinaryMaxReportsNull enabled, and add a targeted regression covering unchanged character buffers for SQL_C_CHAR and SQL_C_WCHAR.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.