Skip to main content

diesel/mysql/types/
mod.rs

1//! MySQL specific types
2
3pub(super) mod date_and_time;
4#[cfg(feature = "serde_json")]
5mod json;
6mod numeric;
7mod primitives;
8
9use crate::deserialize::{self, FromSql};
10use crate::mysql::{Mysql, MysqlType, MysqlValue, NumericRepresentation};
11use crate::query_builder::QueryId;
12use crate::serialize::{self, IsNull, Output, ToSql};
13use crate::sql_types::ops::*;
14use crate::sql_types::*;
15use crate::sql_types::{self};
16use byteorder::{NativeEndian, WriteBytesExt};
17use primitives::{decimal_to_integer, f32_to_i64, f64_to_i64, narrow};
18
19#[cfg(feature = "mysql_backend")]
20impl ToSql<TinyInt, Mysql> for i8 {
21    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
22        out.write_i8(*self).map(|_| IsNull::No).map_err(Into::into)
23    }
24}
25
26#[cfg(feature = "mysql_backend")]
27impl FromSql<TinyInt, Mysql> for i8 {
28    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
29        match value.numeric_value()? {
30            NumericRepresentation::Tiny(x) => Ok(x),
31            NumericRepresentation::UnsignedTiny(x) => narrow(x),
32            NumericRepresentation::Small(x) => narrow(x),
33            NumericRepresentation::UnsignedSmall(x) => narrow(x),
34            NumericRepresentation::Medium(x) => narrow(x),
35            NumericRepresentation::UnsignedMedium(x) => narrow(x),
36            NumericRepresentation::Big(x) => narrow(x),
37            NumericRepresentation::UnsignedBig(x) => narrow(x),
38            NumericRepresentation::Float(x) => narrow(f32_to_i64(x)?),
39            NumericRepresentation::Double(x) => narrow(f64_to_i64(x)?),
40            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
41        }
42    }
43}
44
45/// Represents the MySQL unsigned type.
46#[derive(#[automatically_derived]
impl<ST: ::core::fmt::Debug + 'static> ::core::fmt::Debug for Unsigned<ST> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unsigned",
            &&self.0)
    }
}Debug, #[automatically_derived]
impl<ST: ::core::clone::Clone + 'static> ::core::clone::Clone for Unsigned<ST>
    {
    #[inline]
    fn clone(&self) -> Unsigned<ST> {
        Unsigned(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]
impl<ST: ::core::marker::Copy + 'static> ::core::marker::Copy for Unsigned<ST>
    {
}Copy, #[automatically_derived]
impl<ST: ::core::default::Default + 'static> ::core::default::Default for
    Unsigned<ST> {
    #[inline]
    fn default() -> Unsigned<ST> {
        Unsigned(::core::default::Default::default())
    }
}Default, const _: () =
    {
        use diesel;
        impl<ST: 'static> diesel::sql_types::SqlType for Unsigned<ST> {
            type IsNull = diesel::sql_types::is_nullable::NotNull;
            const IS_ARRAY: bool = false;
        }
        impl<ST: 'static> diesel::sql_types::SingleValue for Unsigned<ST> {}
    };SqlType, const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl<ST: 'static + diesel::query_builder::QueryId>
            diesel::query_builder::QueryId for Unsigned<ST> {
            type QueryId =
                Unsigned<<ST as diesel::query_builder::QueryId>::QueryId>;
            const HAS_STATIC_QUERY_ID: bool =
                <ST as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                    true;
            const IS_WINDOW_FUNCTION: bool =
                <ST as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                    false;
        }
    };QueryId)]
47#[cfg(feature = "mysql_backend")]
48pub struct Unsigned<ST: 'static>(ST);
49
50impl<T> Add for Unsigned<T>
51where
52    T: Add,
53{
54    type Rhs = Unsigned<T::Rhs>;
55    type Output = Unsigned<T::Output>;
56}
57
58impl<T> Sub for Unsigned<T>
59where
60    T: Sub,
61{
62    type Rhs = Unsigned<T::Rhs>;
63    type Output = Unsigned<T::Output>;
64}
65
66impl<T> Mul for Unsigned<T>
67where
68    T: Mul,
69{
70    type Rhs = Unsigned<T::Rhs>;
71    type Output = Unsigned<T::Output>;
72}
73
74impl<T> Div for Unsigned<T>
75where
76    T: Div,
77{
78    type Rhs = Unsigned<T::Rhs>;
79    type Output = Unsigned<T::Output>;
80}
81
82#[cfg(feature = "mysql_backend")]
83impl ToSql<Unsigned<TinyInt>, Mysql> for u8 {
84    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
85        out.write_u8(*self)?;
86        Ok(IsNull::No)
87    }
88}
89
90#[cfg(feature = "mysql_backend")]
91impl FromSql<Unsigned<TinyInt>, Mysql> for u8 {
92    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
93        match value.numeric_value()? {
94            NumericRepresentation::Tiny(x) => narrow(x),
95            NumericRepresentation::UnsignedTiny(x) => Ok(x),
96            NumericRepresentation::Small(x) => narrow(x),
97            NumericRepresentation::UnsignedSmall(x) => narrow(x),
98            NumericRepresentation::Medium(x) => narrow(x),
99            NumericRepresentation::UnsignedMedium(x) => narrow(x),
100            NumericRepresentation::Big(x) => narrow(x),
101            NumericRepresentation::UnsignedBig(x) => narrow(x),
102            NumericRepresentation::Float(x) => narrow(f32_to_i64(x)?),
103            NumericRepresentation::Double(x) => narrow(f64_to_i64(x)?),
104            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
105        }
106    }
107}
108
109#[cfg(feature = "mysql_backend")]
110impl ToSql<Unsigned<SmallInt>, Mysql> for u16 {
111    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
112        out.write_u16::<NativeEndian>(*self)?;
113        Ok(IsNull::No)
114    }
115}
116
117#[cfg(feature = "mysql_backend")]
118impl FromSql<Unsigned<SmallInt>, Mysql> for u16 {
119    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
120        match value.numeric_value()? {
121            NumericRepresentation::Tiny(x) => narrow(x),
122            NumericRepresentation::UnsignedTiny(x) => Ok(x.into()),
123            NumericRepresentation::Small(x) => narrow(x),
124            NumericRepresentation::UnsignedSmall(x) => Ok(x),
125            NumericRepresentation::Medium(x) => narrow(x),
126            NumericRepresentation::UnsignedMedium(x) => narrow(x),
127            NumericRepresentation::Big(x) => narrow(x),
128            NumericRepresentation::UnsignedBig(x) => narrow(x),
129            NumericRepresentation::Float(x) => narrow(f32_to_i64(x)?),
130            NumericRepresentation::Double(x) => narrow(f64_to_i64(x)?),
131            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
132        }
133    }
134}
135
136#[cfg(feature = "mysql_backend")]
137impl ToSql<Unsigned<Integer>, Mysql> for u32 {
138    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
139        out.write_u32::<NativeEndian>(*self)?;
140        Ok(IsNull::No)
141    }
142}
143
144#[cfg(feature = "mysql_backend")]
145impl FromSql<Unsigned<Integer>, Mysql> for u32 {
146    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
147        match value.numeric_value()? {
148            NumericRepresentation::Tiny(x) => narrow(x),
149            NumericRepresentation::UnsignedTiny(x) => Ok(x.into()),
150            NumericRepresentation::Small(x) => narrow(x),
151            NumericRepresentation::UnsignedSmall(x) => Ok(x.into()),
152            NumericRepresentation::Medium(x) => narrow(x),
153            NumericRepresentation::UnsignedMedium(x) => Ok(x),
154            NumericRepresentation::Big(x) => narrow(x),
155            NumericRepresentation::UnsignedBig(x) => narrow(x),
156            NumericRepresentation::Float(x) => narrow(f32_to_i64(x)?),
157            NumericRepresentation::Double(x) => narrow(f64_to_i64(x)?),
158            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
159        }
160    }
161}
162
163#[cfg(feature = "mysql_backend")]
164impl ToSql<Unsigned<BigInt>, Mysql> for u64 {
165    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
166        out.write_u64::<NativeEndian>(*self)?;
167        Ok(IsNull::No)
168    }
169}
170
171#[cfg(feature = "mysql_backend")]
172impl FromSql<Unsigned<BigInt>, Mysql> for u64 {
173    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
174        // No signed type covers the whole unsigned range, unlike the narrower widths.
175        match value.numeric_value()? {
176            NumericRepresentation::Tiny(x) => narrow(x),
177            NumericRepresentation::UnsignedTiny(x) => Ok(x.into()),
178            NumericRepresentation::Small(x) => narrow(x),
179            NumericRepresentation::UnsignedSmall(x) => Ok(x.into()),
180            NumericRepresentation::Medium(x) => narrow(x),
181            NumericRepresentation::UnsignedMedium(x) => Ok(x.into()),
182            NumericRepresentation::Big(x) => narrow(x),
183            NumericRepresentation::UnsignedBig(x) => Ok(x),
184            NumericRepresentation::Float(x) => narrow(f32_to_i64(x)?),
185            NumericRepresentation::Double(x) => narrow(f64_to_i64(x)?),
186            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
187        }
188    }
189}
190
191#[cfg(feature = "mysql_backend")]
192impl ToSql<Bool, Mysql> for bool {
193    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
194        let int_value = i32::from(*self);
195        <i32 as ToSql<Integer, Mysql>>::to_sql(&int_value, &mut out.reborrow())
196    }
197}
198
199#[cfg(feature = "mysql_backend")]
200impl FromSql<Bool, Mysql> for bool {
201    fn from_sql(bytes: MysqlValue<'_>) -> deserialize::Result<Self> {
202        Ok(bytes.as_bytes().iter().any(|x| *x != 0))
203    }
204}
205
206#[cfg(feature = "mysql_backend")]
207impl ToSql<sql_types::SmallInt, Mysql> for i16 {
208    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
209        out.write_i16::<NativeEndian>(*self)
210            .map(|_| IsNull::No)
211            .map_err(|e| Box::new(e) as Box<_>)
212    }
213}
214
215#[cfg(feature = "mysql_backend")]
216impl ToSql<sql_types::Integer, Mysql> for i32 {
217    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
218        out.write_i32::<NativeEndian>(*self)
219            .map(|_| IsNull::No)
220            .map_err(|e| Box::new(e) as Box<_>)
221    }
222}
223
224#[cfg(feature = "mysql_backend")]
225impl ToSql<sql_types::BigInt, Mysql> for i64 {
226    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
227        out.write_i64::<NativeEndian>(*self)
228            .map(|_| IsNull::No)
229            .map_err(|e| Box::new(e) as Box<_>)
230    }
231}
232
233#[cfg(feature = "mysql_backend")]
234impl ToSql<sql_types::Double, Mysql> for f64 {
235    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
236        out.write_f64::<NativeEndian>(*self)
237            .map(|_| IsNull::No)
238            .map_err(|e| Box::new(e) as Box<_>)
239    }
240}
241
242#[cfg(feature = "mysql_backend")]
243impl ToSql<sql_types::Float, Mysql> for f32 {
244    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
245        out.write_f32::<NativeEndian>(*self)
246            .map(|_| IsNull::No)
247            .map_err(|e| Box::new(e) as Box<_>)
248    }
249}
250
251#[cfg(feature = "mysql_backend")]
252impl HasSqlType<Unsigned<TinyInt>> for Mysql {
253    fn metadata(_lookup: &mut ()) -> MysqlType {
254        MysqlType::UnsignedTiny
255    }
256}
257
258#[cfg(feature = "mysql_backend")]
259impl HasSqlType<Unsigned<SmallInt>> for Mysql {
260    fn metadata(_lookup: &mut ()) -> MysqlType {
261        MysqlType::UnsignedShort
262    }
263}
264
265#[cfg(feature = "mysql_backend")]
266impl HasSqlType<Unsigned<Integer>> for Mysql {
267    fn metadata(_lookup: &mut ()) -> MysqlType {
268        MysqlType::UnsignedLong
269    }
270}
271
272#[cfg(feature = "mysql_backend")]
273impl HasSqlType<Unsigned<BigInt>> for Mysql {
274    fn metadata(_lookup: &mut ()) -> MysqlType {
275        MysqlType::UnsignedLongLong
276    }
277}
278
279/// Represents the MySQL datetime type.
280///
281/// ### [`ToSql`] impls
282///
283/// - [`chrono::NaiveDateTime`] with `feature = "chrono"`
284/// - [`time::PrimitiveDateTime`] with `feature = "time"`
285/// - [`time::OffsetDateTime`] with `feature = "time"`
286///
287/// ### [`FromSql`] impls
288///
289/// - [`chrono::NaiveDateTime`] with `feature = "chrono"`
290/// - [`time::PrimitiveDateTime`] with `feature = "time"`
291/// - [`time::OffsetDateTime`] with `feature = "time"`
292///
293/// [`ToSql`]: crate::serialize::ToSql
294/// [`FromSql`]: crate::deserialize::FromSql
295#[cfg_attr(
296    feature = "chrono",
297    doc = " [`chrono::NaiveDateTime`]: chrono::naive::NaiveDateTime"
298)]
299#[cfg_attr(
300    not(feature = "chrono"),
301    doc = " [`chrono::NaiveDateTime`]: https://docs.rs/chrono/0.4.19/chrono/naive/struct.NaiveDateTime.html"
302)]
303#[cfg_attr(
304    feature = "time",
305    doc = " [`time::PrimitiveDateTime`]: time::PrimitiveDateTime"
306)]
307#[cfg_attr(
308    not(feature = "time"),
309    doc = " [`time::PrimitiveDateTime`]: https://docs.rs/time/0.3.9/time/struct.PrimitiveDateTime.html"
310)]
311#[cfg_attr(
312    feature = "time",
313    doc = " [`time::OffsetDateTime`]: time::OffsetDateTime"
314)]
315#[cfg_attr(
316    not(feature = "time"),
317    doc = " [`time::OffsetDateTime`]: https://docs.rs/time/0.3.9/time/struct.OffsetDateTime.html"
318)]
319#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Datetime {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Datetime")
    }
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Datetime { }
#[automatically_derived]
impl ::core::clone::Clone for Datetime {
    #[inline]
    fn clone(&self) -> Datetime { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Datetime { }Copy, #[automatically_derived]
impl ::core::default::Default for Datetime {
    #[inline]
    fn default() -> Datetime { Datetime {} }
}Default, const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for Datetime {
            type QueryId = Datetime<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };QueryId, const _: () =
    {
        use diesel;
        impl diesel::sql_types::SqlType for Datetime {
            type IsNull = diesel::sql_types::is_nullable::NotNull;
            const IS_ARRAY: bool = false;
        }
        impl diesel::sql_types::SingleValue for Datetime {}
        impl diesel::sql_types::HasSqlType<Datetime> for diesel::mysql::Mysql
            {
            fn metadata(_: &mut ()) -> diesel::mysql::MysqlType {
                diesel::mysql::MysqlType::DateTime
            }
        }
    };SqlType)]
320#[diesel(mysql_type(name = "DateTime"))]
321pub struct Datetime;
322
323#[cfg(test)]
324mod tests {
325    use super::*;
326
327    #[cfg(feature = "mysql")]
328    type DB = crate::mysql::Mysql;
329
330    #[diesel_test_helper::test]
331    fn empty_tiny_buffer_is_an_error() {
332        let empty = MysqlValue::new_internal(&[], MysqlType::Tiny);
333        assert!(<i8 as FromSql<TinyInt, DB>>::from_sql(empty).is_err());
334
335        let empty = MysqlValue::new_internal(&[], MysqlType::UnsignedTiny);
336        assert!(<u8 as FromSql<Unsigned<TinyInt>, DB>>::from_sql(empty).is_err());
337    }
338
339    #[diesel_test_helper::test]
340    fn tiny_buffers_keep_their_signedness() {
341        let signed = MysqlValue::new_internal(&[0xFF], MysqlType::Tiny);
342        assert_eq!(<i8 as FromSql<TinyInt, DB>>::from_sql(signed).unwrap(), -1);
343
344        let unsigned = MysqlValue::new_internal(&[200], MysqlType::UnsignedTiny);
345        assert_eq!(
346            <u8 as FromSql<Unsigned<TinyInt>, DB>>::from_sql(unsigned).unwrap(),
347            200
348        );
349    }
350
351    #[diesel_test_helper::test]
352    fn unsigned_tiny_above_i8_max_through_a_signed_sql_type() {
353        let raw = [200];
354
355        // Used to reinterpret the byte as -56.
356        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedTiny);
357        assert!(<i8 as FromSql<TinyInt, DB>>::from_sql(v).is_err());
358
359        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedTiny);
360        assert_eq!(<i16 as FromSql<SmallInt, DB>>::from_sql(v).unwrap(), 200);
361    }
362
363    // Both used to return those bits reinterpreted under the wrong sign.
364    #[diesel_test_helper::test]
365    fn signed_value_through_an_unsigned_sql_type_is_an_error() {
366        let raw = [0xFF];
367        let v = MysqlValue::new_internal(&raw, MysqlType::Tiny);
368        assert!(<u8 as FromSql<Unsigned<TinyInt>, DB>>::from_sql(v).is_err());
369
370        let raw = (-1i16).to_ne_bytes();
371        let v = MysqlValue::new_internal(&raw, MysqlType::Short);
372        assert!(<u16 as FromSql<Unsigned<SmallInt>, DB>>::from_sql(v).is_err());
373
374        let raw = (-1i32).to_ne_bytes();
375        let v = MysqlValue::new_internal(&raw, MysqlType::Long);
376        assert!(<u32 as FromSql<Unsigned<Integer>, DB>>::from_sql(v).is_err());
377
378        let raw = (-1i64).to_ne_bytes();
379        let v = MysqlValue::new_internal(&raw, MysqlType::LongLong);
380        assert!(<u64 as FromSql<Unsigned<BigInt>, DB>>::from_sql(v).is_err());
381    }
382
383    #[diesel_test_helper::test]
384    fn unsigned_bigint_beyond_i64_through_a_signed_sql_type_is_an_error() {
385        let raw = u64::MAX.to_ne_bytes();
386        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLongLong);
387        assert!(<i64 as FromSql<BigInt, DB>>::from_sql(v).is_err());
388
389        // The same buffer read as what it actually is still decodes.
390        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLongLong);
391        assert_eq!(
392            <u64 as FromSql<Unsigned<BigInt>, DB>>::from_sql(v).unwrap(),
393            u64::MAX
394        );
395    }
396
397    #[diesel_test_helper::test]
398    fn unsigned_bigint_at_i64_max_boundary() {
399        // i64::MAX (9223372036854775807) fits in i64 and must succeed.
400        let raw = i64::MAX.to_ne_bytes();
401        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLongLong);
402        assert_eq!(<i64 as FromSql<BigInt, DB>>::from_sql(v).unwrap(), i64::MAX);
403
404        // i64::MAX + 1 (9223372036854775808) does not fit in i64 and must fail.
405        let raw = (i64::MAX as u64 + 1).to_ne_bytes();
406        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLongLong);
407        assert!(<i64 as FromSql<BigInt, DB>>::from_sql(v).is_err());
408    }
409
410    #[diesel_test_helper::test]
411    fn unsigned_bigint_beyond_i64_arriving_as_a_decimal() {
412        let v = MysqlValue::new_internal(b"18446744073709551615", MysqlType::Numeric);
413        assert_eq!(
414            <u64 as FromSql<Unsigned<BigInt>, DB>>::from_sql(v).unwrap(),
415            u64::MAX
416        );
417    }
418
419    #[diesel_test_helper::test]
420    fn unsigned_values_reaching_the_float_readers() {
421        let raw = 200u8.to_ne_bytes();
422        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedTiny);
423        assert_eq!(<f32 as FromSql<Float, DB>>::from_sql(v).unwrap(), 200.0);
424
425        let raw = 40000u16.to_ne_bytes();
426        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedShort);
427        assert_eq!(<f64 as FromSql<Double, DB>>::from_sql(v).unwrap(), 40000.0);
428
429        let raw = u32::MAX.to_ne_bytes();
430        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLong);
431        assert_eq!(
432            <f64 as FromSql<Double, DB>>::from_sql(v).unwrap(),
433            4_294_967_295.0
434        );
435        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLong);
436        assert_eq!(
437            <f32 as FromSql<Float, DB>>::from_sql(v).unwrap(),
438            4_294_967_296.0
439        );
440
441        let raw = u64::MAX.to_ne_bytes();
442        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLongLong);
443        assert_eq!(
444            <f64 as FromSql<Double, DB>>::from_sql(v).unwrap(),
445            18_446_744_073_709_551_616.0
446        );
447        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLongLong);
448        assert_eq!(
449            <f32 as FromSql<Float, DB>>::from_sql(v).unwrap(),
450            18_446_744_073_709_551_616.0
451        );
452    }
453
454    #[cfg(feature = "numeric")]
455    #[diesel_test_helper::test]
456    fn unsigned_values_reaching_the_decimal_reader() {
457        use bigdecimal::BigDecimal;
458
459        let raw = 200u8.to_ne_bytes();
460        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedTiny);
461        assert_eq!(
462            <BigDecimal as FromSql<Numeric, DB>>::from_sql(v).unwrap(),
463            BigDecimal::from(200u8)
464        );
465
466        let raw = 40000u16.to_ne_bytes();
467        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedShort);
468        assert_eq!(
469            <BigDecimal as FromSql<Numeric, DB>>::from_sql(v).unwrap(),
470            BigDecimal::from(40000u16)
471        );
472
473        let raw = u32::MAX.to_ne_bytes();
474        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLong);
475        assert_eq!(
476            <BigDecimal as FromSql<Numeric, DB>>::from_sql(v).unwrap(),
477            BigDecimal::from(u32::MAX)
478        );
479
480        let raw = u64::MAX.to_ne_bytes();
481        let v = MysqlValue::new_internal(&raw, MysqlType::UnsignedLongLong);
482        assert_eq!(
483            <BigDecimal as FromSql<Numeric, DB>>::from_sql(v).unwrap(),
484            BigDecimal::from(u64::MAX)
485        );
486    }
487}