diff --git a/sqlx-core/src/mssql/arguments.rs b/sqlx-core/src/mssql/arguments.rs index 98e6de84be..23d9ecaa2d 100644 --- a/sqlx-core/src/mssql/arguments.rs +++ b/sqlx-core/src/mssql/arguments.rs @@ -65,6 +65,13 @@ impl MssqlArguments { T: Encode<'q, Mssql> + Type, { let ty = value.produces().unwrap_or_else(T::type_info); + // `DataType::Null` is required in TDS for null values, but the + // `sp_executesql` declaration needs the parameter's Rust type. + let declaration_ty = if ty.0.is_null() { + T::type_info() + } else { + ty.clone() + }; // produce an ordinal parameter name // @p1, @p2, ... @pN @@ -91,7 +98,7 @@ impl MssqlArguments { declarations.push_str(name); declarations.push(' '); - ty.0.fmt(declarations); + declaration_ty.0.fmt(declarations); // write out the parameter diff --git a/sqlx-core/src/mssql/types/bytes.rs b/sqlx-core/src/mssql/types/bytes.rs index 48e0f71318..825d4f6cbe 100644 --- a/sqlx-core/src/mssql/types/bytes.rs +++ b/sqlx-core/src/mssql/types/bytes.rs @@ -8,7 +8,7 @@ use std::borrow::Cow; impl Type for [u8] { fn type_info() -> MssqlTypeInfo { - MssqlTypeInfo(TypeInfo::new(DataType::BigVarBinary, 0)) + MssqlTypeInfo(TypeInfo::new(DataType::BigVarBinary, 0xFF_FF)) } fn compatible(ty: &MssqlTypeInfo) -> bool { diff --git a/sqlx-core/src/mssql/types/json.rs b/sqlx-core/src/mssql/types/json.rs index 1dd67a2132..3f5aa3bfec 100644 --- a/sqlx-core/src/mssql/types/json.rs +++ b/sqlx-core/src/mssql/types/json.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; impl Type for Json { fn type_info() -> MssqlTypeInfo { - MssqlTypeInfo(TypeInfo::new(DataType::BigVarBinary, 0)) + MssqlTypeInfo(TypeInfo::new(DataType::BigVarBinary, 0xFF_FF)) } fn compatible(ty: &MssqlTypeInfo) -> bool { diff --git a/tests/mssql/mssql.rs b/tests/mssql/mssql.rs index 90cc8c81d4..cc4faf5701 100644 --- a/tests/mssql/mssql.rs +++ b/tests/mssql/mssql.rs @@ -193,6 +193,21 @@ async fn it_binds_empty_string_and_null() -> anyhow::Result<()> { Ok(()) } +// Regression test for https://github.com/sqlpage/sqlx-oldapi/issues/58 +#[sqlx_macros::test] +async fn it_binds_null_with_type_in_isnull_expression() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let (val,): (String,) = sqlx_oldapi::query_as("SELECT ISNULL(@p1, N'hello')") + .bind(None::) + .fetch_one(&mut conn) + .await?; + + assert_eq!(val, "hello"); + + Ok(()) +} + #[sqlx_macros::test] async fn it_binds_string_with_special_chars() -> anyhow::Result<()> { let mut conn = new::().await?;