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