Skip to content

Commit 1e49060

Browse files
committed
mssql int with warning on overflow
1 parent 27bd731 commit 1e49060

File tree

1 file changed

+36
-44
lines changed

1 file changed

+36
-44
lines changed

sqlx-core/src/mssql/types/uint.rs

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,116 +7,108 @@ use crate::types::Type;
77

88
impl Type<Mssql> for u8 {
99
fn type_info() -> MssqlTypeInfo {
10-
MssqlTypeInfo(TypeInfo::new(DataType::IntN, 1))
10+
<i8 as Type<Mssql>>::type_info()
1111
}
1212

1313
fn compatible(ty: &MssqlTypeInfo) -> bool {
14-
matches!(ty.0.ty, DataType::TinyInt | DataType::IntN) && ty.0.size == 1
14+
<i8 as Type<Mssql>>::compatible(ty)
1515
}
1616
}
1717

1818
impl Encode<'_, Mssql> for u8 {
1919
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
20-
buf.extend(&self.to_le_bytes());
21-
22-
IsNull::No
20+
let v = i8::try_from(*self).unwrap_or_else(|_e| {
21+
log::warn!("cannot encode {self} as a signed mssql tinyint");
22+
i8::MAX
23+
});
24+
<i8 as Encode<'_, Mssql>>::encode_by_ref(&v, buf)
2325
}
2426
}
2527

2628
impl Decode<'_, Mssql> for u8 {
2729
fn decode(value: MssqlValueRef<'_>) -> Result<Self, BoxDynError> {
28-
Ok(value.as_bytes()?[0])
30+
let v = <i8 as Decode<'_, Mssql>>::decode(value)?;
31+
Ok(u8::try_from(v)?)
2932
}
3033
}
3134

3235
impl Type<Mssql> for u16 {
3336
fn type_info() -> MssqlTypeInfo {
34-
MssqlTypeInfo(TypeInfo::new(DataType::IntN, 4))
37+
<i16 as Type<Mssql>>::type_info()
3538
}
3639

3740
fn compatible(ty: &MssqlTypeInfo) -> bool {
38-
matches!(ty.0.ty, DataType::Int | DataType::IntN) && ty.0.size == 4
41+
<i16 as Type<Mssql>>::compatible(ty)
3942
}
4043
}
4144

4245
impl Encode<'_, Mssql> for u16 {
4346
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
44-
let value = i32::from(*self);
45-
buf.extend(&value.to_le_bytes());
46-
IsNull::No
47+
let v = i16::try_from(*self).unwrap_or_else(|_e| {
48+
log::warn!("cannot encode {self} as a signed mssql smallint");
49+
i16::MAX
50+
});
51+
<i16 as Encode<'_, Mssql>>::encode_by_ref(&v, buf)
4752
}
4853
}
4954

5055
impl Decode<'_, Mssql> for u16 {
5156
fn decode(value: MssqlValueRef<'_>) -> Result<Self, BoxDynError> {
52-
let bytes = value.as_bytes()?;
53-
let val = i32::from_le_bytes(bytes.try_into()?);
54-
u16::try_from(val).map_err(Into::into)
57+
let v = <i16 as Decode<'_, Mssql>>::decode(value)?;
58+
Ok(u16::try_from(v)?)
5559
}
5660
}
5761

5862
impl Type<Mssql> for u32 {
5963
fn type_info() -> MssqlTypeInfo {
60-
MssqlTypeInfo(TypeInfo::new(DataType::IntN, 8))
64+
<i32 as Type<Mssql>>::type_info()
6165
}
6266

6367
fn compatible(ty: &MssqlTypeInfo) -> bool {
64-
matches!(ty.0.ty, DataType::BigInt | DataType::IntN) && ty.0.size == 8
68+
<i32 as Type<Mssql>>::compatible(ty)
6569
}
6670
}
6771

6872
impl Encode<'_, Mssql> for u32 {
6973
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
70-
let value = i64::from(*self);
71-
buf.extend(&value.to_le_bytes());
72-
IsNull::No
74+
let v = i32::try_from(*self).unwrap_or_else(|_e| {
75+
log::warn!("cannot encode {self} as a signed mssql int");
76+
i32::MAX
77+
});
78+
<i32 as Encode<'_, Mssql>>::encode_by_ref(&v, buf)
7379
}
7480
}
7581

7682
impl Decode<'_, Mssql> for u32 {
7783
fn decode(value: MssqlValueRef<'_>) -> Result<Self, BoxDynError> {
78-
let bytes = value.as_bytes()?;
79-
let val = i64::from_le_bytes(bytes.try_into()?);
80-
u32::try_from(val).map_err(Into::into)
84+
let v = <i32 as Decode<'_, Mssql>>::decode(value)?;
85+
Ok(u32::try_from(v)?)
8186
}
8287
}
8388

8489
impl Type<Mssql> for u64 {
8590
fn type_info() -> MssqlTypeInfo {
86-
MssqlTypeInfo(TypeInfo::new(DataType::NumericN, 17))
91+
<i64 as Type<Mssql>>::type_info()
8792
}
8893

8994
fn compatible(ty: &MssqlTypeInfo) -> bool {
90-
matches!(
91-
ty.0.ty,
92-
DataType::Numeric | DataType::NumericN | DataType::Decimal | DataType::DecimalN
93-
) && (ty.0.size == 0 || ty.0.size == 17)
95+
<i64 as Type<Mssql>>::compatible(ty)
9496
}
9597
}
9698

9799
impl Encode<'_, Mssql> for u64 {
98100
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
99-
let bytes = self.to_le_bytes();
100-
let scale = 0i8;
101-
let len = 17u8;
102-
103-
buf.push(len);
104-
buf.push(scale.to_le_bytes()[0]);
105-
buf.extend(&bytes);
106-
buf.extend(&[0u8; 8]);
107-
108-
IsNull::No
101+
let v = i64::try_from(*self).unwrap_or_else(|_e| {
102+
log::warn!("cannot encode {self} as a signed mssql bigint");
103+
i64::MAX
104+
});
105+
<i64 as Encode<'_, Mssql>>::encode_by_ref(&v, buf)
109106
}
110107
}
111108

112109
impl Decode<'_, Mssql> for u64 {
113110
fn decode(value: MssqlValueRef<'_>) -> Result<Self, BoxDynError> {
114-
let bytes = value.as_bytes()?;
115-
if bytes.len() < 17 {
116-
return Err("Invalid numeric value length".into());
117-
}
118-
119-
let value_bytes = &bytes[2..10];
120-
Ok(u64::from_le_bytes(value_bytes.try_into()?))
111+
let v = <i64 as Decode<'_, Mssql>>::decode(value)?;
112+
Ok(u64::try_from(v)?)
121113
}
122114
}

0 commit comments

Comments
 (0)