v0.9.0
⚠️ This release has been yanked from crates.iov0.9.0 contains two critical bugs that prevent Always Encrypted from
functioning:
- LOGIN7
ibExtensionpointer indirection — the feature extension
wire format was wrong per MS-TDS §2.2.6.4. SQL Server read garbage as
a u32 offset and dropped the connection with no diagnostic. Affected
every AE-enabled connection attempt in v0.5.x through v0.9.x.EncryptionContextprovider loss underConfigclone —Arc::try_unwrap
fails when refcount > 1 (which happens on every retry/redirect),
silently dropping all registered key store providers. Every CEK lookup
failed asKeyStoreNotFound.Both are fixed in v0.10.0.
If you were using or evaluating Always Encrypted, upgrade to v0.10.0.Non-AE features in v0.9.0 functioned correctly, but upgrading is
recommended regardless for the connection string, performance, and bulk
insert improvements shipped in v0.10.0. See
CHANGELOG
for details.
Added
- Always Encrypted decryption integration — wired CryptoMetadata parsing and AEAD_AES_256_CBC_HMAC_SHA256 decryption into query execution. Encrypted columns are transparently decrypted when
Column Encryption Setting=Enabledis set in the connection string. Decryption is supported across all response readers:query(),call_procedure(), andquery_multiple(). CEK resolution is performed asynchronously at ColMetaData time; per-row decryption is synchronous in the hot path. - Native Windows SSPI authentication — integrated auth (
Integrated Security=true) now uses the native Windows SSPI subsystem (secur32.dll) instead of sspi-rs on Windows, supporting all account types including Microsoft Accounts, domain accounts, and local accounts without explicit credentials (closes #65) - FILESTREAM BLOB access (Windows only,
filestreamfeature) — async read/write access to SQL Server FILESTREAM data viaOpenSqlFilestream.FileStreamimplementsAsyncRead + AsyncWritefor tokio compatibility. Accessed viaClient<InTransaction>::open_filestream()or the low-levelFileStream::open()API. Requires the Microsoft OLE DB Driver for SQL Server at runtime. (closes #67) - 34 new unit tests for tds-protocol token parsing (ReturnValue, ReturnStatus, DoneProc, DoneInProc, ServerError, multi-token streams) and mssql-auth error/provider classification
- ADO.NET connection string conformance — comprehensive parser rewrite:
- Quoted value support —
Password="my;complex;pass"andPassword='it''s complex'now work per ADO.NET spec. Previously, passwords with semicolons were silently truncated. tcp:prefix stripping —Server=tcp:host.database.windows.net,1433(Azure Portal format) now works.np:andlpc:prefixes return clear errors.- New Server aliases —
Addr,Address,Network Addressnow accepted per Microsoft docs Timeoutalias for Connect Timeout per ADO.NET spec- ApplicationIntent —
ReadOnly/ReadWritefor AlwaysOn AG read-only routing, wired to LOGIN7 TypeFlags READONLY_INTENT bit - Workstation ID /
WSID— client machine name for audit trails viasys.dm_exec_sessions.host_name - Current Language /
Language— session language, wired to LOGIN7 Language field - ConnectRetryCount / ConnectRetryInterval — wired to RetryPolicy
- Pool keywords (
Max Pool Size,Min Pool Size,Pooling, etc.) — recognized with info-level guidance to use PoolConfig - 30+ known ADO.NET keywords recognized at info level instead of silently ignored at debug level
- Boolean validation — invalid values like
TrustServerCertificate=banananow return errors instead of silently defaulting to false Encrypt=Mandatory/Optional— Microsoft.Data.SqlClient v5+ aliases fortrue/falsenow accepted- Case-insensitive protocol prefixes —
Tcp:,TCP:,tCp:all stripped correctly (not justtcp:andTCP:) - Empty values reset optional fields —
Database=;now results inNoneinstead ofSome(""), matching ADO.NET reset-to-default behavior
- Quoted value support —
Changed
- unwrap() audit — replaced ~20 production
unwrap()calls withexpect()containing descriptive context strings across library code - panic! audit — audited all panic-family macros (
panic!,unreachable!,unimplemented!,todo!) in library code; converted one unjustifiedunreachable!to proper error propagation - Updated LIMITATIONS.md to reflect v0.8.0+ features (stored procedures, SQL Browser, pool health checks, Always Encrypted)
Fixed
- Always Encrypted in procedures and multi-result queries — decryption was missing from
read_procedure_result()andread_multi_result_response(), causing encrypted columns to return raw ciphertext instead of plaintext when accessed viacall_procedure()orquery_multiple() - windows-certstore compilation errors — resolved 9 compilation errors in the Always Encrypted Windows Certificate Store provider caused by API changes in the
windows0.62 crate (#83) - Silent error swallowing — replaced
filter_map(|r| r.ok())in test code with explicitunwrap()so failures are visible; documented intentional best-effort parsing in bulk insert type resolution (local)host alias —Server=(local)\SQLEXPRESSnow correctly resolves to127.0.0.1, matching ADO.NET behavior. Previously only.was normalized to localhost (#66)- LOGIN7 HostName field — now sends the actual client machine hostname (or
Workstation IDif configured) instead of the server hostname. Previouslysys.dm_exec_sessions.host_nameshowed the server's own name. Per MS-TDS spec, the LOGIN7 HostName field is "the name of the client machine."
What's Changed
Full Changelog: v0.8.0...v0.9.0