Closed
Conversation
Introduces a new `sqlx-mssql` crate that wraps the tiberius TDS protocol driver (v0.12) behind sqlx's trait system, enabling SQL Server connectivity with the same ergonomic API as the existing MySQL, PostgreSQL, and SQLite drivers. Key implementation details: - Full Database/Connection/Executor/Row/Value trait implementations - Connection via tiberius::Client with runtime-agnostic socket bridging - Eager result collection (tiberius QueryStream borrows &mut Client) - Transaction support with MSSQL-specific savepoint syntax - Type mappings: bool, u8, i8, i16, i32, i64, f32, f64, String, Vec<u8> - Any driver integration and migration support - Test infrastructure with TestSupport for #[sqlx::test] - sp_describe_first_result_set for statement metadata and nullability - Fixes to existing MSSQL test files (imports, placeholders, lifetimes) Author: Pablo Carrera <pabloce@poscye.com>
Enable native chrono type handling for MSSQL datetime columns, eliminating the need for CONVERT(VARCHAR) workarounds. Supports NaiveDateTime, NaiveDate, NaiveTime, and DateTime<Utc> by converting between tiberius internal datetime structs and chrono types. Author: Pablo Carrera <pabloce@poscye.com>
Enable UNIQUEIDENTIFIER columns via uuid::Uuid and DECIMAL/NUMERIC/MONEY columns via rust_decimal::Decimal, both feature-gated behind their respective cargo features. Author: Pablo Carrera <pabloce@poscye.com>
Wire up tiberius/time and tiberius/bigdecimal feature flags and implement
Type/Encode/Decode for time::{Date, Time, PrimitiveDateTime, OffsetDateTime},
bigdecimal::BigDecimal, and Json<T>. Uses a ColumnDataWrapper newtype to
bridge tiberius's IntoSql gap for time types and BigDecimal (version mismatch).
JSON is stored as NVARCHAR since SQL Server has no native JSON column type.
Author: Pablo Carrera <pabloce@poscye.com>
…erives, and test attributes Add tests for all implemented Encode/Decode types (uuid, chrono, time, rust_decimal, bigdecimal, json, bytes), error kind mapping, derive macros (weak enums, transparent types), and #[sqlx::test] attribute with migrations and fixtures. Author: Pablo Carrera <pabloce@poscye.com>
…lx-mssql Add MssqlSslMode with 4 variants (Disabled, LoginOnly, Preferred, Required) mapping to all tiberius EncryptionLevel options. Add MssqlAdvisoryLock API using sp_getapplock/sp_releaseapplock for application-level distributed locking. Enable f64/Decimal/BigDecimal decoding from MONEY/SMALLMONEY columns. Author: Pablo Carrera <pabloce@poscye.com>
…lx-mssql Add MssqlIsolationLevel enum with begin_with_isolation() for typed transaction isolation control. Surface tiberius application_intent (read-only routing) and trust_cert_ca options in MssqlConnectOptions. Wrap tiberius BulkLoadRequest as MssqlBulkInsert for high-performance data loading via the TDS INSERT BULK protocol. Author: Pablo Carrera <pabloce@poscye.com>
… sqlx-mssql - Add Windows, Integrated, and AAD token authentication support with cfg-gated features matching tiberius (winauth, integrated-auth-gssapi) - Override format_placeholder to produce @p1, @p2, ... instead of ? so QueryBuilder works correctly with MSSQL parameterized queries - Add MssqlXml newtype wrapper for SQL Server XML columns with Type, Encode, and Decode implementations - Add URL parsing for auth and token query parameters with roundtrip tests Author: Pablo Carrera <pabloce@poscye.com>
Register MSSQL in the macro system (cfg gate, impl_database_ext, FOSS_DRIVERS) so query!()/query_as!() work with MSSQL databases. Add missing Any driver type mappings for NULL, BIT, MONEY, SMALLMONEY, and DECIMAL/NUMERIC to prevent AnyDriverError at runtime. Author: Pablo Carrera <pabloce@poscye.com>
…ECIMAL precision for MSSQL Wire MSSQL into docker-compose and CI workflow, support no_tx migrations following the Postgres pattern, extract column origin from sp_describe_first_result_set, map date/time/UUID types to Text in the Any driver, and preserve DECIMAL precision/scale by using a base_name() helper for type matching. Author: Pablo Carrera <pabloce@poscye.com>
…d MSSQL examples Add MssqlAdvisoryLockGuard with Deref/DerefMut, release_now(), and leak() methods, mirroring the Postgres advisory lock guard pattern. The guard logs a warning on drop if not explicitly released, since MSSQL connections cannot queue deferred commands. Add chrono::DateTime<FixedOffset> Type/Encode/Decode for DATETIMEOFFSET columns, preserving timezone offset information instead of converting to UTC. Existing NaiveDateTime and DateTime<Utc> decoders remain backward compatible by handling the new internal variant. Add examples/mssql/todos/ with a CLI app demonstrating basic CRUD operations using MSSQL parameter syntax and OUTPUT INSERTED. Author: Pablo Carrera <pabloce@poscye.com>
… _persistent flag for MSSQL Fix Money4 (SMALLMONEY) being incorrectly mapped to "MONEY" instead of "SMALLMONEY", enabling the Any driver's existing SMALLMONEY handling. Add comprehensive type tests (integer edge cases, Unicode, large strings, binary, NULL, XML, DateTime<FixedOffset>, SMALLMONEY) and integration tests (multiple result sets, column metadata, error recovery, many parameters, isolation levels, advisory lock guard). Author: Pablo Carrera <pabloce@poscye.com>
…ion lock - Escape `]` and `'` in database/schema names interpolated into DDL in migrate.rs and testing/mod.rs to prevent SQL injection - Add SMALLMONEY to compatible() for rust_decimal and bigdecimal types - Wrap sp_getapplock in DECLARE/THROW to surface lock failures as SQL errors - Add compatible() overrides for DATE, TIME, and UNIQUEIDENTIFIER types - Fix swapped Real/Double null type mappings in Any arguments - Replace panicking expects with proper Error returns in executor - Add migration test harness and sample migrations for MSSQL Author: Pablo Carrera <pabloce@poscye.com>
…alculation Closes #1 Author: Pablo Carrera <pabloce@poscye.com>
Author: Pablo Carrera <pabloce@poscye.com>
…conversion Dates before the TDS epoch (0001-01-01) produced negative day counts that silently wrapped via `as u32`, causing corrupt data or a panic inside `tiberius::time::Date::new()`. Add `days_since_epoch_to_u32()` helper that returns `Error::Encode` for negative or out-of-range values, and replace all four unsafe cast sites. Closes #2 Author: Pablo Carrera <pabloce@poscye.com>
…validated conversion Adds offset_minutes_to_i16 helper that validates the offset fits within SQL Server's -840..=840 minute range, returning Error::Encode instead of silently truncating. Follows the same pattern as days_since_epoch_to_u32. Author: Pablo Carrera <pabloce@poscye.com>
Apply bracket-quoting for identifier contexts and single-quote escaping for string literal contexts across all 6 interpolation sites, consistent with existing escaping in create_database, drop_database, and create_schema_if_not_exists. Closes #4 Author: Pablo Carrera <pabloce@poscye.com>
…_if_not_exists
Split the single `escaped` variable into separate variables for each SQL
quoting context, preventing cross-contamination between bracket-quoted
identifiers ([...]) and single-quoted string literals ('...').
Closes #5
Author: Pablo Carrera <pabloce@poscye.com>
…ta with Result propagation Return Result<MssqlData, Error> instead of panicking on invalid data from tiberius. Fixes and_local_timezone().unwrap() panic on ambiguous/invalid DateTimeOffset, and guards against silent u8 truncation in time_from_sec_fragments with an upfront bounds check. All helper functions (chrono_date_from_days, time_date_from_days, time_from_sec_fragments) now return Result and use checked arithmetic. Author: Pablo Carrera <pabloce@poscye.com>
…terized queries + QUOTENAME() Replace fragile client-side .replace() escaping in create_database, drop_database, and create_schema_if_not_exists with parameterized queries (@p1) and SQL Server's built-in QUOTENAME() function for server-side identifier escaping via sp_executesql. Author: Pablo Carrera <pabloce@poscye.com>
…column_data_to_mssql_data The wildcard `_ => Ok(MssqlData::Null)` silently coerced unhandled `Some(...)` variants (e.g. Xml, Guid without uuid, Numeric without rust_decimal) to NULL, causing silent data loss. Enumerate all 18 `None` variants explicitly and error on unhandled `Some(...)` values. Author: Pablo Carrera <pabloce@poscye.com>
…ation Closes #9 Author: Pablo Carrera <pabloce@poscye.com>
…check Extract bigdecimal_to_numeric() helper that normalizes negative exponents via with_scale(0) (matching tiberius's own to_sql! pattern) and tightens the scale limit from >38 to >37 to match tiberius's assert!(scale < 38). Add 10 unit tests covering negative exponents, boundary values, silent truncation at scale=256, and the off-by-one at scale=38. Author: Pablo Carrera <pabloce@poscye.com>
Replace string-interpolated SQL with tiberius::Query parameterized bindings in prepare_with/describe to eliminate Unicode homoglyph injection edge case. Also log sp_describe_undeclared_parameters errors instead of silently swallowing them. Closes #10 Author: Pablo Carrera <pabloce@poscye.com>
…SQL escaping in test harness
- Map Datetime4 to SMALLDATETIME instead of DATETIMEOFFSET
- Validate rust_decimal scale <= 37 before u8 cast to prevent silent truncation
- Replace client-side .replace(']',"]]") escaping with parameterized QUOTENAME(@p1) + sp_executesql in testing/mod.rs
Author: Pablo Carrera <pabloce@poscye.com>
…arnings - Add #[allow] annotations with SAFETY comments for all guarded integer casts that violated crate-level deny lints (cast_possible_truncation, cast_possible_wrap, cast_sign_loss) - Parameterize advisory lock mode via @p2 instead of string interpolation - Parameterize migrate table existence check via @p1 while preserving atomic single-statement DDL - Change time_date_from_days to accept i64 with i64::from() at call sites to eliminate cast_sign_loss under --features time - Remove unnecessary as u64 casts on Time::increments() calls - Remove useless .into() on Error::Protocol(format!(...)) calls - Extract build_columns_from_describe_rows helper to deduplicate prepare_with/describe column-building logic - Fix minor issues: needless_borrow, needless_lifetimes, doc-test reborrows, todo!() -> error, uuid encode simplification, unused atoi dep, incorrect doc comment, redundant .into_iter() Author: Pablo Carrera <pabloce@poscye.com>
… lossless casts - Fix panic on multi-byte UTF-8 in catch-all error truncation by using is_char_boundary to retreat to a valid boundary - Handle ColumnData::Xml(Some(...)) explicitly, converting to MssqlData::String via XmlData::into_string() - Take ColumnData by value instead of by reference, eliminating allocations for String/Binary/Xml variants (into_owned + move instead of to_string/to_vec) - Replace `as u64` with u64::from() for lossless widening casts in time encoding - Extract repeated .time() calls into local bindings for clarity Author: Pablo Carrera <pabloce@poscye.com>
Transform the feature overview into a self-contained guide covering connection pooling, query patterns, FromRow/derive macros, error handling, OUTPUT INSERTED, stored procedures, nested transactions, and pool callbacks. Restructure sections to follow a developer's learning path, add recommended feature flag sets, and correct begin_with_isolation usage and advisory lock drop behavior. Author: Pablo Carrera <pabloce@poscye.com>
Return Result from build_url(), document expect() invariants for UTC offsets and epoch dates, safe UTF-8 truncation, lossless numeric casts, parameterized sp_describe calls, and resolve all clippy deny violations. Author: Pablo Carrera <pabloce@poscye.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Does your PR solve an issue?
Delete this text and add "fixes #(issue number)".
Do not just list issue numbers here as they will not be automatically closed on merging this pull request unless prefixed with "fixes" or "closes".
Is this a breaking change?
Delete this text and answer yes/no and explain.
If yes, this pull request will need to wait for the next major release (
0.{x + 1}.0)Behavior changes can be breaking if significant enough.
Consider Hyrum's Law: