1use chrono::prelude::*;
2use chrono_tz::Tz;
3use std::net::{Ipv4Addr, Ipv6Addr};
4
5use crate::types::{Enum16, Enum8};
6use crate::{
7 errors::{Error, FromSqlError},
8 types::{column::{Either, datetime64::to_datetime}, Decimal, SqlType, ValueRef},
9};
10
11pub type FromSqlResult<T> = Result<T, Error>;
12
13pub trait FromSql<'a>: Sized {
14 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self>;
15}
16
17macro_rules! from_sql_impl {
18 ( $( $t:ident: $k:ident ),* ) => {
19 $(
20 impl<'a> FromSql<'a> for $t {
21 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
22 match value {
23 ValueRef::$k(v) => Ok(v),
24 _ => {
25 let from = SqlType::from(value.clone()).to_string();
26 Err(Error::FromSql(FromSqlError::InvalidType { src: from, dst: stringify!($t).into() }))
27 }
28 }
29 }
30 }
31 )*
32 };
33}
34
35impl<'a> FromSql<'a> for Decimal {
36 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
37 match value {
38 ValueRef::Decimal(v) => Ok(v),
39 _ => {
40 let from = SqlType::from(value.clone()).to_string();
41 Err(Error::FromSql(FromSqlError::InvalidType {
42 src: from,
43 dst: "Decimal".into(),
44 }))
45 }
46 }
47 }
48}
49
50impl<'a> FromSql<'a> for Enum8 {
51 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
52 match value {
53 ValueRef::Enum8(_enum_values, v) => Ok(v),
54 _ => {
55 let from = SqlType::from(value.clone()).to_string();
56
57 Err(Error::FromSql(FromSqlError::InvalidType {
58 src: from,
59 dst: "Enum8".into(),
60 }))
61 }
62 }
63 }
64}
65
66impl<'a> FromSql<'a> for Enum16 {
67 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
68 match value {
69 ValueRef::Enum16(_enum_values, v) => Ok(v),
70 _ => {
71 let from = SqlType::from(value.clone()).to_string();
72
73 Err(Error::FromSql(FromSqlError::InvalidType {
74 src: from,
75 dst: "Enum16".into(),
76 }))
77 }
78 }
79 }
80}
81
82impl<'a> FromSql<'a> for &'a str {
83 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<&'a str> {
84 value.as_str()
85 }
86}
87
88impl<'a> FromSql<'a> for &'a [u8] {
89 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<&'a [u8]> {
90 value.as_bytes()
91 }
92}
93
94impl<'a> FromSql<'a> for String {
95 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
96 value.as_str().map(str::to_string)
97 }
98}
99
100impl<'a> FromSql<'a> for Ipv4Addr {
101 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
102 match value {
103 ValueRef::Ipv4(ip) => Ok(Ipv4Addr::from(ip)),
104 _ => {
105 let from = SqlType::from(value.clone()).to_string();
106 Err(Error::FromSql(FromSqlError::InvalidType {
107 src: from,
108 dst: "Ipv4".into(),
109 }))
110 }
111 }
112 }
113}
114
115impl<'a> FromSql<'a> for Ipv6Addr {
116 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
117 match value {
118 ValueRef::Ipv6(ip) => Ok(Ipv6Addr::from(ip)),
119 _ => {
120 let from = SqlType::from(value.clone()).to_string();
121 Err(Error::FromSql(FromSqlError::InvalidType {
122 src: from,
123 dst: "Ipv6".into(),
124 }))
125 }
126 }
127 }
128}
129
130impl<'a> FromSql<'a> for uuid::Uuid {
131 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
132 match value {
133 ValueRef::Uuid(row) => Ok(uuid::Uuid::from_bytes(row)),
134 _ => {
135 let from = SqlType::from(value.clone()).to_string();
136 Err(Error::FromSql(FromSqlError::InvalidType {
137 src: from,
138 dst: "Uuid".into(),
139 }))
140 }
141 }
142 }
143}
144
145macro_rules! from_sql_vec_impl {
146 ( $( $t:ty: $k:pat => $f:expr ),* ) => {
147 $(
148 impl<'a> FromSql<'a> for Vec<$t> {
149 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
150 match value {
151 ValueRef::Array($k, vs) => {
152 let f: fn(ValueRef<'a>) -> FromSqlResult<$t> = $f;
153 let mut result = Vec::with_capacity(vs.len());
154 for v in vs.iter() {
155 let value: $t = f(v.clone())?;
156 result.push(value);
157 }
158 Ok(result)
159 }
160 _ => {
161 let from = SqlType::from(value.clone()).to_string();
162 Err(Error::FromSql(FromSqlError::InvalidType {
163 src: from,
164 dst: format!("Vec<{}>", stringify!($t)).into(),
165 }))
166 }
167 }
168 }
169 }
170 )*
171 };
172}
173
174from_sql_vec_impl! {
175 &'a str: SqlType::String => |v| v.as_str(),
176 String: SqlType::String => |v| v.as_string(),
177 Date<Tz>: SqlType::Date => |z| Ok(z.into()),
178 DateTime<Tz>: SqlType::DateTime(_) => |z| Ok(z.into())
179}
180
181impl<'a> FromSql<'a> for Vec<u8> {
182 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
183 match value {
184 ValueRef::Array(SqlType::UInt8, vs) => {
185 let mut result = Vec::with_capacity(vs.len());
186 for v in vs.iter() {
187 result.push(v.clone().into());
188 }
189 Ok(result)
190 }
191 _ => value.as_bytes().map(|bs| bs.to_vec()),
192 }
193 }
194}
195
196macro_rules! from_sql_vec_impl {
197 ( $( $t:ident: $k:ident ),* ) => {
198 $(
199 impl<'a> FromSql<'a> for Vec<$t> {
200 fn from_sql(value: ValueRef<'a>) -> Result<Self, Error> {
201 match value {
202 ValueRef::Array(SqlType::$k, vs) => {
203 let mut result = Vec::with_capacity(vs.len());
204 for v in vs.iter() {
205 let val: $t = v.clone().into();
206 result.push(val);
207 }
208 Ok(result)
209 }
210 _ => {
211 let from = SqlType::from(value.clone()).to_string();
212 Err(Error::FromSql(FromSqlError::InvalidType { src: from, dst: stringify!($t).into() }))
213 }
214 }
215 }
216 }
217 )*
218 };
219}
220
221from_sql_vec_impl! {
222 i8: Int8,
223 i16: Int16,
224 i32: Int32,
225 i64: Int64,
226
227 u16: UInt16,
228 u32: UInt32,
229 u64: UInt64,
230
231 f32: Float32,
232 f64: Float64
233}
234
235impl<'a, T> FromSql<'a> for Option<T>
236where
237 T: FromSql<'a>,
238{
239 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
240 match value {
241 ValueRef::Nullable(e) => match e {
242 Either::Left(_) => Ok(None),
243 Either::Right(u) => {
244 let value_ref = u.as_ref().clone();
245 Ok(Some(T::from_sql(value_ref)?))
246 }
247 },
248 _ => {
249 let from = SqlType::from(value.clone()).to_string();
250 Err(Error::FromSql(FromSqlError::InvalidType {
251 src: from,
252 dst: stringify!($t).into(),
253 }))
254 }
255 }
256 }
257}
258
259impl<'a> FromSql<'a> for Date<Tz> {
260 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
261 match value {
262 ValueRef::Date(v, tz) => {
263 let time = tz.timestamp(i64::from(v) * 24 * 3600, 0);
264 Ok(time.date())
265 }
266 _ => {
267 let from = SqlType::from(value).to_string();
268 Err(Error::FromSql(FromSqlError::InvalidType {
269 src: from,
270 dst: "Date<Tz>".into(),
271 }))
272 }
273 }
274 }
275}
276
277impl<'a> FromSql<'a> for DateTime<Tz> {
278 fn from_sql(value: ValueRef<'a>) -> FromSqlResult<Self> {
279 match value {
280 ValueRef::DateTime(v, tz) => {
281 let time = tz.timestamp(i64::from(v), 0);
282 Ok(time)
283 }
284 ValueRef::DateTime64(v, params) => {
285 let (precision, tz) = *params;
286 Ok(to_datetime(v, precision, tz))
287 }
288 _ => {
289 let from = SqlType::from(value).to_string();
290 Err(Error::FromSql(FromSqlError::InvalidType {
291 src: from,
292 dst: "DateTime<Tz>".into(),
293 }))
294 }
295 }
296 }
297}
298
299from_sql_impl! {
300 u8: UInt8,
301 u16: UInt16,
302 u32: UInt32,
303 u64: UInt64,
304
305 i8: Int8,
306 i16: Int16,
307 i32: Int32,
308 i64: Int64,
309
310 f32: Float32,
311 f64: Float64
312}
313
314#[cfg(test)]
315mod test {
316 use crate::types::{from_sql::FromSql, ValueRef};
317
318 #[test]
319 fn test_u8() {
320 let v = ValueRef::from(42_u8);
321 let actual = u8::from_sql(v).unwrap();
322 assert_eq!(actual, 42_u8);
323 }
324
325 #[test]
326 fn test_bad_convert() {
327 let v = ValueRef::from(42_u16);
328 match u32::from_sql(v) {
329 Ok(_) => panic!("should fail"),
330 Err(e) => assert_eq!(
331 "From SQL error: `SqlType::UInt16 cannot be cast to u32.`".to_string(),
332 format!("{}", e)
333 ),
334 }
335 }
336}