microsoft / microsoft/mssql-rs
Preserve character output buffers when SQLGetData returns NULL binary values
Nobody has claimed this yet.
- 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
- Connect to a test SQL Server through the ODBC Driver Manager.
- Execute
SELECT CAST(NULL AS VARBINARY(MAX))and fetch the row. - Fill a writable 32-byte buffer with
0x7E. - Call
SQLGetDatafor column 1 withSQL_C_CHAR, buffer length 32, and a valid indicator pointer. Repeat on a fresh row withSQL_C_WCHAR. - Compare the return code, indicator, and buffer contents against retail msodbcsql. The same difference was measured with
BINARY(3)andVARBINARY(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_columnhandlesColumnValues::Nullbefore conversion and callscopy_with_nulfor 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:fIsNullDatasetsSQL_NULL_DATAand jumps toReturn2, bypassing character termination underReturn3. BinToCharLiveTest.NullVarbinaryMaxReportsNullintentionally 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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