klickhouse/convert/
std_serialize.rs1use std::{
2 any::TypeId,
3 collections::{BTreeMap, HashMap},
4};
5
6use indexmap::IndexMap;
7
8use super::*;
9
10impl ToSql for u8 {
11 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
12 Ok(Value::UInt8(self))
13 }
14}
15
16impl ToSql for bool {
17 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
18 Ok(Value::UInt8(self as u8))
19 }
20}
21
22impl ToSql for u16 {
23 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
24 Ok(Value::UInt16(self))
25 }
26}
27
28impl ToSql for u32 {
29 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
30 Ok(Value::UInt32(self))
31 }
32}
33
34impl ToSql for u64 {
35 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
36 Ok(Value::UInt64(self))
37 }
38}
39
40impl ToSql for u128 {
41 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
42 Ok(Value::UInt128(self))
43 }
44}
45
46impl ToSql for i8 {
47 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
48 Ok(Value::Int8(self))
49 }
50}
51
52impl ToSql for i16 {
53 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
54 Ok(Value::Int16(self))
55 }
56}
57
58impl ToSql for i32 {
59 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
60 Ok(Value::Int32(self))
61 }
62}
63
64impl ToSql for i64 {
65 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
66 Ok(Value::Int64(self))
67 }
68}
69
70impl ToSql for i128 {
71 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
72 Ok(Value::Int128(self))
73 }
74}
75
76impl ToSql for f32 {
77 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
78 Ok(Value::Float32(self))
79 }
80}
81
82impl ToSql for f64 {
83 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
84 Ok(Value::Float64(self))
85 }
86}
87
88impl ToSql for String {
89 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
90 Ok(Value::String(self.into_bytes()))
91 }
92}
93
94impl ToSql for &str {
95 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
96 Ok(Value::String(self.as_bytes().to_vec()))
97 }
98}
99
100impl<T: ToSql + 'static> ToSql for Vec<T> {
101 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
102 let type_hint = type_hint
103 .and_then(|x| x.unarray())
104 .map(|x| x.strip_low_cardinality());
105 if matches!(type_hint, Some(Type::String) | Some(Type::FixedString(_))) {
106 let type_id = TypeId::of::<T>();
107 if type_id == TypeId::of::<u8>() || type_id == TypeId::of::<i8>() {
108 assert_eq!(std::mem::size_of::<T>(), 1);
109 return Ok(Value::String(unsafe {
110 std::mem::transmute::<Vec<T>, Vec<u8>>(self)
111 }));
112 }
113 }
114 Ok(Value::Array(
115 self.into_iter()
116 .map(|x| x.to_sql(type_hint))
117 .collect::<Result<Vec<_>>>()?,
118 ))
119 }
120}
121
122impl<T: ToSql, Y: ToSql> ToSql for HashMap<T, Y> {
123 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
124 let mut keys = Vec::with_capacity(self.len());
125 let mut values = Vec::with_capacity(self.len());
126 let type_hint = type_hint.and_then(|x| x.unmap());
127 for (key, value) in self {
128 keys.push(key.to_sql(type_hint.map(|x| x.0))?);
129 values.push(value.to_sql(type_hint.map(|x| x.1))?);
130 }
131 Ok(Value::Map(keys, values))
132 }
133}
134
135impl<T: ToSql, Y: ToSql> ToSql for BTreeMap<T, Y> {
136 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
137 let mut keys = Vec::with_capacity(self.len());
138 let mut values = Vec::with_capacity(self.len());
139 let type_hint = type_hint.and_then(|x| x.unmap());
140 for (key, value) in self {
141 keys.push(key.to_sql(type_hint.map(|x| x.0))?);
142 values.push(value.to_sql(type_hint.map(|x| x.1))?);
143 }
144 Ok(Value::Map(keys, values))
145 }
146}
147
148impl<T: ToSql, Y: ToSql> ToSql for IndexMap<T, Y> {
149 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
150 let mut keys = Vec::with_capacity(self.len());
151 let mut values = Vec::with_capacity(self.len());
152 let type_hint = type_hint.and_then(|x| x.unmap());
153 for (key, value) in self {
154 keys.push(key.to_sql(type_hint.map(|x| x.0))?);
155 values.push(value.to_sql(type_hint.map(|x| x.1))?);
156 }
157 Ok(Value::Map(keys, values))
158 }
159}
160
161impl<T: ToSql> ToSql for Option<T> {
162 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
163 match self {
164 Some(x) => Ok(x.to_sql(type_hint.and_then(|x| x.unnull()))?),
165 None => Ok(Value::Null),
166 }
167 }
168}
169
170impl<T: ToSql, const N: usize> ToSql for [T; N] {
171 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
172 let type_hint = type_hint
173 .and_then(|x| x.unarray())
174 .map(|x| x.strip_low_cardinality());
175 Ok(Value::Array(
176 IntoIterator::into_iter(self)
177 .map(|x| x.to_sql(type_hint))
178 .collect::<Result<Vec<_>>>()?,
179 ))
180 }
181}
182
183impl<T: ToSql + Clone> ToSql for &T {
184 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
185 self.clone().to_sql(type_hint)
186 }
187}
188
189impl<T: ToSql + Clone> ToSql for &mut T {
190 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
191 self.clone().to_sql(type_hint)
192 }
193}
194
195impl<T: ToSql> ToSql for Box<T> {
196 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
197 (*self).to_sql(type_hint)
198 }
199}
200
201macro_rules! tuple_impls {
202 ($($len:expr => ($($n:tt $name:ident)+))+) => {
203 $(
204 impl<$($name: ToSql),+> ToSql for ($($name,)+) {
205 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
206 let type_hint = type_hint.and_then(|x| x.untuple());
207
208 Ok(Value::Tuple(vec![
209 $(
210 self.$n.to_sql(type_hint.and_then(|x| x.get($n)))?,
211 )+
212 ]))
213 }
214 }
215 )+
216 }
217}
218
219tuple_impls! {
220 1 => (0 T0)
221 2 => (0 T0 1 T1)
222 3 => (0 T0 1 T1 2 T2)
223 4 => (0 T0 1 T1 2 T2 3 T3)
224 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
225 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
226 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
227 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
228 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
229 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
230 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
231 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
232 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
233 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
234 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
235 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
236}