diesel_async/mysql/
serialize.rs1use diesel::mysql::data_types::MysqlTime;
2use diesel::mysql::MysqlType;
3use diesel::mysql::MysqlValue;
4use diesel::QueryResult;
5use mysql_async::{Params, Value};
6use std::convert::TryInto;
7
8pub(super) struct ToSqlHelper {
9 pub(super) metadata: Vec<MysqlType>,
10 pub(super) binds: Vec<Option<Vec<u8>>>,
11}
12
13fn to_value((metadata, bind): (MysqlType, Option<Vec<u8>>)) -> QueryResult<Value> {
14 let cast_helper = |e| diesel::result::Error::SerializationError(Box::new(e));
15 let v = match bind {
16 Some(bind) => match metadata {
17 MysqlType::Tiny => Value::Int(i8::from_be_bytes([bind[0]]) as i64),
18 MysqlType::Short => Value::Int(i16::from_ne_bytes(bind.try_into().unwrap()) as _),
19 MysqlType::Long => Value::Int(i32::from_ne_bytes(bind.try_into().unwrap()) as _),
20 MysqlType::LongLong => Value::Int(i64::from_ne_bytes(bind.try_into().unwrap())),
21
22 MysqlType::UnsignedTiny => Value::UInt(bind[0] as _),
23 MysqlType::UnsignedShort => {
24 Value::UInt(u16::from_ne_bytes(bind.try_into().unwrap()) as _)
25 }
26 MysqlType::UnsignedLong => {
27 Value::UInt(u32::from_ne_bytes(bind.try_into().unwrap()) as _)
28 }
29 MysqlType::UnsignedLongLong => {
30 Value::UInt(u64::from_ne_bytes(bind.try_into().unwrap()))
31 }
32 MysqlType::Float => Value::Float(f32::from_ne_bytes(bind.try_into().unwrap())),
33 MysqlType::Double => Value::Double(f64::from_ne_bytes(bind.try_into().unwrap())),
34
35 MysqlType::Time => {
36 let time: MysqlTime = diesel::deserialize::FromSql::<
37 diesel::sql_types::Time,
38 diesel::mysql::Mysql,
39 >::from_sql(MysqlValue::new(&bind, metadata))
40 .expect("This does not fail");
41 Value::Time(
42 time.neg,
43 time.day,
44 time.hour.try_into().map_err(cast_helper)?,
45 time.minute.try_into().map_err(cast_helper)?,
46 time.second.try_into().map_err(cast_helper)?,
47 time.second_part.try_into().expect("Cast does not fail"),
48 )
49 }
50 MysqlType::Date | MysqlType::DateTime | MysqlType::Timestamp => {
51 let time: MysqlTime = diesel::deserialize::FromSql::<
52 diesel::sql_types::Timestamp,
53 diesel::mysql::Mysql,
54 >::from_sql(MysqlValue::new(&bind, metadata))
55 .expect("This does not fail");
56 Value::Date(
57 time.year.try_into().map_err(cast_helper)?,
58 time.month.try_into().map_err(cast_helper)?,
59 time.day.try_into().map_err(cast_helper)?,
60 time.hour.try_into().map_err(cast_helper)?,
61 time.minute.try_into().map_err(cast_helper)?,
62 time.second.try_into().map_err(cast_helper)?,
63 time.second_part.try_into().expect("Cast does not fail"),
64 )
65 }
66 MysqlType::Numeric
67 | MysqlType::Set
68 | MysqlType::Enum
69 | MysqlType::String
70 | MysqlType::Blob => Value::Bytes(bind),
71 MysqlType::Bit => unimplemented!(),
72 _ => unreachable!(),
73 },
74 None => Value::NULL,
75 };
76 Ok(v)
77}
78
79impl TryFrom<ToSqlHelper> for Params {
80 type Error = diesel::result::Error;
81
82 fn try_from(ToSqlHelper { metadata, binds }: ToSqlHelper) -> Result<Self, Self::Error> {
83 let values = metadata
84 .into_iter()
85 .zip(binds)
86 .map(to_value)
87 .collect::<Result<Vec<_>, Self::Error>>()?;
88 Ok(Params::Positional(values))
89 }
90}