opensrv_clickhouse/types/
value.rs

1// Copyright 2021 Datafuse Labs.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::convert;
16use std::fmt;
17use std::mem;
18use std::net::Ipv4Addr;
19use std::net::Ipv6Addr;
20use std::str;
21use std::sync::Arc;
22
23use chrono::prelude::*;
24use chrono_tz::Tz;
25use uuid::Uuid;
26
27use crate::types::column::datetime64::to_datetime;
28use crate::types::column::Either;
29use crate::types::decimal::Decimal;
30use crate::types::decimal::NoBits;
31use crate::types::DateConverter;
32use crate::types::DateTimeType;
33use crate::types::Enum16;
34use crate::types::Enum8;
35use crate::types::HasSqlType;
36use crate::types::SqlType;
37use crate::types::UNIX_EPOCH_DAY;
38
39pub(crate) type AppDateTime = DateTime<Tz>;
40pub(crate) type AppDate = NaiveDate;
41
42/// Client side representation of a value of Clickhouse column.
43#[derive(Clone, Debug)]
44pub enum Value {
45    UInt8(u8),
46    UInt16(u16),
47    UInt32(u32),
48    UInt64(u64),
49    Int8(i8),
50    Int16(i16),
51    Int32(i32),
52    Int64(i64),
53    String(Arc<Vec<u8>>),
54    Float32(f32),
55    Float64(f64),
56    Date(u16),
57    DateTime(u32, Tz),
58    DateTime64(i64, (u32, Tz)),
59    Ipv4([u8; 4]),
60    Ipv6([u8; 16]),
61    Uuid([u8; 16]),
62    Nullable(Either<&'static SqlType, Box<Value>>),
63    Array(&'static SqlType, Arc<Vec<Value>>),
64    Decimal(Decimal),
65    Enum8(Vec<(String, i8)>, Enum8),
66    Enum16(Vec<(String, i16)>, Enum16),
67    Tuple(Arc<Vec<Value>>),
68}
69
70impl PartialEq for Value {
71    fn eq(&self, other: &Self) -> bool {
72        match (self, other) {
73            (Value::UInt8(a), Value::UInt8(b)) => *a == *b,
74            (Value::UInt16(a), Value::UInt16(b)) => *a == *b,
75            (Value::UInt32(a), Value::UInt32(b)) => *a == *b,
76            (Value::UInt64(a), Value::UInt64(b)) => *a == *b,
77            (Value::Int8(a), Value::Int8(b)) => *a == *b,
78            (Value::Int16(a), Value::Int16(b)) => *a == *b,
79            (Value::Int32(a), Value::Int32(b)) => *a == *b,
80            (Value::Int64(a), Value::Int64(b)) => *a == *b,
81            (Value::String(a), Value::String(b)) => *a == *b,
82            (Value::Float32(a), Value::Float32(b)) => *a == *b,
83            (Value::Float64(a), Value::Float64(b)) => *a == *b,
84            (Value::Date(a), Value::Date(b)) => *a == *b,
85            (Value::DateTime(a, tz_a), Value::DateTime(b, tz_b)) => {
86                let time_a = tz_a.timestamp_opt(i64::from(*a), 0).unwrap();
87                let time_b = tz_b.timestamp_opt(i64::from(*b), 0).unwrap();
88                time_a == time_b
89            }
90            (Value::Nullable(a), Value::Nullable(b)) => *a == *b,
91            (Value::Array(ta, a), Value::Array(tb, b)) => *ta == *tb && *a == *b,
92            (Value::Decimal(a), Value::Decimal(b)) => *a == *b,
93            (Value::Enum16(values_a, val_a), Value::Enum16(values_b, val_b)) => {
94                *values_a == *values_b && *val_a == *val_b
95            }
96            (Value::Tuple(a), Value::Tuple(b)) => *a == *b,
97            _ => false,
98        }
99    }
100}
101
102impl Value {
103    pub fn default(sql_type: SqlType) -> Value {
104        match sql_type {
105            SqlType::UInt8 => Value::UInt8(0),
106            SqlType::UInt16 => Value::UInt16(0),
107            SqlType::UInt32 => Value::UInt32(0),
108            SqlType::UInt64 => Value::UInt64(0),
109            SqlType::Int8 => Value::Int8(0),
110            SqlType::Int16 => Value::Int16(0),
111            SqlType::Int32 => Value::Int32(0),
112            SqlType::Int64 => Value::Int64(0),
113            SqlType::String => Value::String(Arc::new(Vec::default())),
114            SqlType::FixedString(str_len) => Value::String(Arc::new(vec![0_u8; str_len])),
115            SqlType::Float32 => Value::Float32(0.0),
116            SqlType::Float64 => Value::Float64(0.0),
117            SqlType::Date => 0_u16.to_date(Tz::Zulu).into(),
118            SqlType::DateTime(DateTimeType::DateTime64(_, _)) => {
119                Value::DateTime64(0, (1, Tz::Zulu))
120            }
121            SqlType::DateTime(_) => 0_u32.to_date(Tz::Zulu).into(),
122            SqlType::Nullable(inner) => Value::Nullable(Either::Left(inner)),
123            SqlType::Array(inner) => Value::Array(inner, Arc::new(Vec::default())),
124            SqlType::Decimal(precision, scale) => Value::Decimal(Decimal {
125                underlying: 0,
126                precision,
127                scale,
128                nobits: NoBits::N64,
129            }),
130            SqlType::Ipv4 => Value::Ipv4([0_u8; 4]),
131            SqlType::Ipv6 => Value::Ipv6([0_u8; 16]),
132            SqlType::Uuid => Value::Uuid([0_u8; 16]),
133            SqlType::Enum8(values) => Value::Enum8(values, Enum8(0)),
134            SqlType::Enum16(values) => Value::Enum16(values, Enum16(0)),
135            SqlType::Tuple(types) => Value::Tuple(Arc::new(
136                types
137                    .into_iter()
138                    .map(|t| Value::default(t.clone()))
139                    .collect(),
140            )),
141        }
142    }
143}
144
145impl fmt::Display for Value {
146    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147        match self {
148            Value::UInt8(ref v) => fmt::Display::fmt(v, f),
149            Value::UInt16(ref v) => fmt::Display::fmt(v, f),
150            Value::UInt32(ref v) => fmt::Display::fmt(v, f),
151            Value::UInt64(ref v) => fmt::Display::fmt(v, f),
152            Value::Int8(ref v) => fmt::Display::fmt(v, f),
153            Value::Int16(ref v) => fmt::Display::fmt(v, f),
154            Value::Int32(ref v) => fmt::Display::fmt(v, f),
155            Value::Int64(ref v) => fmt::Display::fmt(v, f),
156            Value::String(ref v) => match str::from_utf8(v) {
157                Ok(s) => fmt::Display::fmt(s, f),
158                Err(_) => write!(f, "{:?}", v),
159            },
160            Value::Float32(ref v) => fmt::Display::fmt(v, f),
161            Value::Float64(ref v) => fmt::Display::fmt(v, f),
162            Value::DateTime(u, tz) if f.alternate() => {
163                let time = tz.timestamp_opt(i64::from(*u), 0).unwrap();
164                fmt::Display::fmt(&time, f)
165            }
166            Value::DateTime(u, tz) => {
167                let time = tz.timestamp_opt(i64::from(*u), 0).unwrap();
168                write!(f, "{}", time.to_rfc2822())
169            }
170            Value::DateTime64(value, params) => {
171                let (precision, tz) = params;
172                let time = to_datetime(*value, *precision, *tz);
173                write!(f, "{}", time.to_rfc2822())
174            }
175            Value::Date(v) if f.alternate() => {
176                let date =
177                    NaiveDate::from_num_days_from_ce_opt((*v as i64 + UNIX_EPOCH_DAY) as i32)
178                        .unwrap();
179                fmt::Display::fmt(&date, f)
180            }
181            Value::Date(v) => {
182                let date =
183                    NaiveDate::from_num_days_from_ce_opt((*v as i64 + UNIX_EPOCH_DAY) as i32)
184                        .unwrap();
185                fmt::Display::fmt(&date.format("%Y-%m-%d"), f)
186            }
187            Value::Nullable(v) => match v {
188                Either::Left(_) => write!(f, "NULL"),
189                Either::Right(data) => data.fmt(f),
190            },
191            Value::Array(_, vs) => {
192                let cells: Vec<String> = vs.iter().map(|v| format!("{}", v)).collect();
193                write!(f, "[{}]", cells.join(", "))
194            }
195            Value::Decimal(v) => fmt::Display::fmt(v, f),
196            Value::Ipv4(v) => {
197                write!(f, "{}", decode_ipv4(v))
198            }
199            Value::Ipv6(v) => {
200                write!(f, "{}", decode_ipv6(v))
201            }
202            Value::Uuid(v) => {
203                let mut buffer = *v;
204                buffer[..8].reverse();
205                buffer[8..].reverse();
206                match Uuid::from_slice(&buffer) {
207                    Ok(uuid) => write!(f, "{}", uuid),
208                    Err(e) => write!(f, "{}", e),
209                }
210            }
211            Value::Enum8(ref _v1, ref v2) => write!(f, "Enum8, {}", v2),
212            Value::Enum16(ref _v1, ref v2) => write!(f, "Enum16, {}", v2),
213            Value::Tuple(v) => {
214                let cells: Vec<String> = v.iter().map(|v| format!("{}", v)).collect();
215                write!(f, "({})", cells.join(", "))
216            }
217        }
218    }
219}
220
221impl convert::From<Value> for SqlType {
222    fn from(source: Value) -> Self {
223        match source {
224            Value::UInt8(_) => SqlType::UInt8,
225            Value::UInt16(_) => SqlType::UInt16,
226            Value::UInt32(_) => SqlType::UInt32,
227            Value::UInt64(_) => SqlType::UInt64,
228            Value::Int8(_) => SqlType::Int8,
229            Value::Int16(_) => SqlType::Int16,
230            Value::Int32(_) => SqlType::Int32,
231            Value::Int64(_) => SqlType::Int64,
232            Value::String(_) => SqlType::String,
233            Value::Float32(_) => SqlType::Float32,
234            Value::Float64(_) => SqlType::Float64,
235            Value::Date(_) => SqlType::Date,
236            Value::DateTime(_, _) => SqlType::DateTime(DateTimeType::DateTime32),
237            Value::Nullable(d) => match d {
238                Either::Left(t) => SqlType::Nullable(t),
239                Either::Right(inner) => {
240                    let sql_type = SqlType::from(inner.as_ref().to_owned());
241                    SqlType::Nullable(sql_type.into())
242                }
243            },
244            Value::Array(t, _) => SqlType::Array(t),
245            Value::Decimal(v) => SqlType::Decimal(v.precision, v.scale),
246            Value::Ipv4(_) => SqlType::Ipv4,
247            Value::Ipv6(_) => SqlType::Ipv6,
248            Value::Uuid(_) => SqlType::Uuid,
249            Value::Enum8(values, _) => SqlType::Enum8(values),
250            Value::Enum16(values, _) => SqlType::Enum16(values),
251            Value::DateTime64(_, params) => {
252                let (precision, tz) = params;
253                SqlType::DateTime(DateTimeType::DateTime64(precision, tz))
254            }
255            Value::Tuple(values) => {
256                let types: Vec<&'static SqlType> = values
257                    .iter()
258                    .map(|v| SqlType::from(v.to_owned()).into())
259                    .collect();
260                SqlType::Tuple(types)
261            }
262        }
263    }
264}
265
266impl<T> convert::From<Option<T>> for Value
267where
268    Value: convert::From<T>,
269    T: HasSqlType,
270{
271    fn from(value: Option<T>) -> Value {
272        match value {
273            None => {
274                let default_type: SqlType = T::get_sql_type();
275                Value::Nullable(Either::Left(default_type.into()))
276            }
277            Some(inner) => Value::Nullable(Either::Right(Box::new(inner.into()))),
278        }
279    }
280}
281
282macro_rules! value_from {
283    ( $( $t:ty : $k:ident ),* ) => {
284        $(
285            impl convert::From<$t> for Value {
286                fn from(v: $t) -> Value {
287                    Value::$k(v.into())
288                }
289            }
290        )*
291    };
292}
293
294impl convert::From<AppDate> for Value {
295    fn from(v: AppDate) -> Value {
296        Value::Date(u16::get_days(v))
297    }
298}
299
300impl convert::From<Enum8> for Value {
301    fn from(v: Enum8) -> Value {
302        Value::Enum8(vec![], v)
303    }
304}
305
306impl convert::From<Enum16> for Value {
307    fn from(v: Enum16) -> Value {
308        Value::Enum16(vec![], v)
309    }
310}
311
312impl convert::From<AppDateTime> for Value {
313    fn from(v: AppDateTime) -> Value {
314        Value::DateTime(v.timestamp() as u32, v.timezone())
315    }
316}
317
318impl convert::From<String> for Value {
319    fn from(v: String) -> Value {
320        Value::String(Arc::new(v.into_bytes()))
321    }
322}
323
324impl convert::From<Vec<u8>> for Value {
325    fn from(v: Vec<u8>) -> Value {
326        Value::String(Arc::new(v))
327    }
328}
329
330impl convert::From<&[u8]> for Value {
331    fn from(v: &[u8]) -> Value {
332        Value::String(Arc::new(v.to_vec()))
333    }
334}
335
336value_from! {
337    u8: UInt8,
338    u16: UInt16,
339    u32: UInt32,
340    u64: UInt64,
341
342    i8: Int8,
343    i16: Int16,
344    i32: Int32,
345    i64: Int64,
346
347    f32: Float32,
348    f64: Float64,
349
350    Decimal: Decimal
351}
352
353impl<'a> convert::From<&'a str> for Value {
354    fn from(v: &'a str) -> Self {
355        let bytes: Vec<u8> = v.as_bytes().into();
356        Value::String(Arc::new(bytes))
357    }
358}
359
360impl convert::From<Value> for String {
361    fn from(mut v: Value) -> Self {
362        if let Value::String(ref mut x) = &mut v {
363            let mut tmp = Arc::new(Vec::new());
364            mem::swap(x, &mut tmp);
365            if let Ok(result) = str::from_utf8(tmp.as_ref()) {
366                return result.into();
367            }
368        }
369        let from = SqlType::from(v);
370        panic!("Can't convert Value::{} into String.", from);
371    }
372}
373
374impl convert::From<Value> for Vec<u8> {
375    fn from(v: Value) -> Self {
376        match v {
377            Value::String(bs) => bs.to_vec(),
378            _ => {
379                let from = SqlType::from(v);
380                panic!("Can't convert Value::{} into Vec<u8>.", from)
381            }
382        }
383    }
384}
385
386macro_rules! from_value {
387    ( $( $t:ty : $k:ident ),* ) => {
388        $(
389            impl convert::From<Value> for $t {
390                fn from(v: Value) -> $t {
391                    if let Value::$k(x) = v {
392                        return x;
393                    }
394                    let from = SqlType::from(v);
395                    panic!("Can't convert Value::{} into {}", from, stringify!($t))
396                }
397            }
398        )*
399    };
400}
401
402impl convert::From<Value> for AppDate {
403    fn from(v: Value) -> AppDate {
404        if let Value::Date(x) = v {
405            let date =
406                NaiveDate::from_num_days_from_ce_opt((x as i64 + UNIX_EPOCH_DAY) as i32).unwrap();
407            return date;
408        }
409        let from = SqlType::from(v);
410        panic!("Can't convert Value::{} into {}", from, "AppDate")
411    }
412}
413
414impl convert::From<Value> for AppDateTime {
415    fn from(v: Value) -> AppDateTime {
416        match v {
417            Value::DateTime(u, tz) => tz.timestamp_opt(i64::from(u), 0).unwrap(),
418            Value::DateTime64(u, params) => {
419                let (precision, tz) = params;
420                to_datetime(u, precision, tz)
421            }
422            _ => {
423                let from = SqlType::from(v);
424                panic!("Can't convert Value::{} into {}", from, "DateTime<Tz>")
425            }
426        }
427    }
428}
429
430from_value! {
431    u8: UInt8,
432    u16: UInt16,
433    u32: UInt32,
434    u64: UInt64,
435    i8: Int8,
436    i16: Int16,
437    i32: Int32,
438    i64: Int64,
439    f32: Float32,
440    f64: Float64
441}
442
443pub(crate) fn decode_ipv4(octets: &[u8; 4]) -> Ipv4Addr {
444    let mut buffer = *octets;
445    buffer.reverse();
446    Ipv4Addr::from(buffer)
447}
448
449pub(crate) fn decode_ipv6(octets: &[u8; 16]) -> Ipv6Addr {
450    Ipv6Addr::from(*octets)
451}