easy_sqlx_core/sql/utils/
value.rs

1#[derive(Debug, Clone)]
2pub enum Value {
3    Bool(Option<bool>),
4    // Byte(Option<i8>),
5    Binary(Option<Vec<u8>>),
6    Short(Option<i16>),
7    Int(Option<i32>),
8    Long(Option<i64>),
9    Float(Option<f32>),
10    Double(Option<f64>),
11    Text(Option<String>),
12    ChronoDate(Option<chrono::NaiveDateTime>),
13
14    Array(Vec<Self>),
15}
16
17use chrono::NaiveDateTime;
18use sqlx::Database;
19
20impl Value {
21    pub fn len(&self) -> usize {
22        match self {
23            Value::Array(ary) => ary.len(),
24            _ => 1,
25        }
26    }
27
28    pub fn add_param_value(&self, str: &mut String) {
29        if !str.is_empty() {
30            str.push_str(",");
31        }
32        str.push_str(&self.as_string());
33    }
34
35    pub fn as_string(&self) -> String {
36        match self {
37            Value::Int(val) => {
38                if let Some(v) = val {
39                    format!("{}", v)
40                } else {
41                    "null".to_string()
42                }
43            }
44            Value::Long(val) => {
45                if let Some(v) = val {
46                    format!("{}", v)
47                } else {
48                    "null".to_string()
49                }
50            }
51            Value::Double(val) => {
52                if let Some(v) = val {
53                    format!("{}", v)
54                } else {
55                    "null".to_string()
56                }
57            }
58            Value::ChronoDate(val) => {
59                if let Some(v) = val {
60                    format!("{}", v)
61                } else {
62                    "null".to_string()
63                }
64            }
65            Value::Text(val) => {
66                if let Some(v) = val {
67                    format!("{}", v)
68                } else {
69                    "null".to_string()
70                }
71            }
72            Value::Binary(val) => {
73                if let Some(v) = val {
74                    format!("{:?}", v)
75                } else {
76                    "null".to_string()
77                }
78            }
79            Value::Short(val) => {
80                if let Some(v) = val {
81                    format!("{}", v)
82                } else {
83                    "null".to_string()
84                }
85            }
86            Value::Float(val) => {
87                if let Some(v) = val {
88                    format!("{}", v)
89                } else {
90                    "null".to_string()
91                }
92            }
93            Value::Bool(val) => {
94                if let Some(v) = val {
95                    format!("{}", v)
96                } else {
97                    "null".to_string()
98                }
99            }
100            Value::Array(ary) => {
101                let ary_str: Vec<String> = ary.iter().map(|v| v.as_string()).collect();
102                format!("({})", ary_str.join(","))
103                // let mut str = "".to_string();
104                // if !ary.is_empty() {
105                //     for val in ary {
106                //         val.as_string();
107                //     }
108                // }
109                // str
110            }
111        }
112    }
113
114    pub fn bind_to_query<'a, DB: Database>(
115        &self,
116        query: sqlx::query::Query<'a, DB, DB::Arguments<'a>>,
117    ) -> sqlx::query::Query<'a, DB, DB::Arguments<'a>>
118    where
119        Option<bool>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
120        bool: sqlx::Type<DB>,
121        Option<i16>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
122        i16: sqlx::Type<DB>,
123        Option<i32>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
124        i32: sqlx::Type<DB>,
125        Option<i64>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
126        i64: sqlx::Type<DB>,
127        Option<f64>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
128        f64: sqlx::Type<DB>,
129        Option<f32>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
130        f32: sqlx::Type<DB>,
131        Option<NaiveDateTime>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
132        NaiveDateTime: sqlx::Type<DB>,
133        Option<String>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
134        String: sqlx::Type<DB>,
135        Option<Vec<u8>>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
136        Vec<u8>: sqlx::Type<DB>,
137    {
138        return match self {
139            Value::Int(val) => query.bind(*val),
140            Value::Long(val) => query.bind(*val),
141            Value::Double(val) => query.bind(*val),
142            Value::ChronoDate(val) => query.bind(*val),
143            Value::Text(val) => query.bind(val.clone()),
144            Value::Binary(val) => query.bind(val.clone()),
145            Value::Short(val) => query.bind(*val),
146            Value::Float(val) => query.bind(*val),
147            Value::Bool(val) => query.bind(*val),
148            Value::Array(ary) => {
149                let mut qry = query;
150                if !ary.is_empty() {
151                    for val in ary {
152                        qry = val.bind_to_query(qry);
153                    }
154                }
155                qry
156            }
157        };
158    }
159
160    pub fn bind_to_query_as<'a, O, DB: Database>(
161        &self,
162        query: sqlx::query::QueryAs<'a, DB, O, DB::Arguments<'a>>,
163    ) -> sqlx::query::QueryAs<'a, DB, O, DB::Arguments<'a>>
164    where
165        Option<bool>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
166        bool: sqlx::Type<DB>,
167        Option<i16>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
168        i16: sqlx::Type<DB>,
169        Option<i32>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
170        i32: sqlx::Type<DB>,
171        Option<i64>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
172        i64: sqlx::Type<DB>,
173        Option<f64>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
174        f64: sqlx::Type<DB>,
175        Option<f32>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
176        f32: sqlx::Type<DB>,
177        Option<NaiveDateTime>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
178        NaiveDateTime: sqlx::Type<DB>,
179        Option<String>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
180        String: sqlx::Type<DB>,
181        Option<Vec<u8>>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
182        Vec<u8>: sqlx::Type<DB>,
183    {
184        return match self {
185            Value::Int(val) => query.bind(*val),
186            Value::Long(val) => query.bind(*val),
187            Value::Double(val) => query.bind(*val),
188            Value::ChronoDate(val) => query.bind(*val),
189            Value::Text(val) => query.bind(val.clone()),
190            Value::Binary(val) => query.bind(val.clone()),
191            Value::Short(val) => query.bind(*val),
192            Value::Float(val) => query.bind(*val),
193            Value::Bool(val) => query.bind(*val),
194            Value::Array(ary) => {
195                let mut qry = query;
196                if !ary.is_empty() {
197                    for val in ary {
198                        qry = val.bind_to_query_as(qry);
199                    }
200                }
201                qry
202            }
203        };
204    }
205
206    pub fn bind_to_query_scalar<'a, O, DB: Database>(
207        &self,
208        query: sqlx::query::QueryScalar<'a, DB, O, DB::Arguments<'a>>,
209    ) -> sqlx::query::QueryScalar<'a, DB, O, DB::Arguments<'a>>
210    where
211        Option<bool>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
212        bool: sqlx::Type<DB>,
213        Option<i16>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
214        i16: sqlx::Type<DB>,
215        Option<i32>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
216        i32: sqlx::Type<DB>,
217        Option<i64>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
218        i64: sqlx::Type<DB>,
219        Option<f64>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
220        f64: sqlx::Type<DB>,
221        Option<f32>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
222        f32: sqlx::Type<DB>,
223        Option<NaiveDateTime>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
224        NaiveDateTime: sqlx::Type<DB>,
225        Option<String>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
226        String: sqlx::Type<DB>,
227        Option<Vec<u8>>: sqlx::Encode<'a, DB> + sqlx::Decode<'a, DB>,
228        Vec<u8>: sqlx::Type<DB>,
229    {
230        return match self {
231            Value::Int(val) => query.bind(*val),
232            Value::Long(val) => query.bind(*val),
233            Value::Double(val) => query.bind(*val),
234            Value::ChronoDate(val) => query.bind(*val),
235            Value::Text(val) => query.bind(val.clone()),
236            Value::Binary(val) => query.bind(val.clone()),
237            Value::Short(val) => query.bind(*val),
238            Value::Float(val) => query.bind(*val),
239            Value::Bool(val) => query.bind(*val),
240            Value::Array(ary) => {
241                let mut qry = query;
242                if !ary.is_empty() {
243                    for val in ary {
244                        qry = val.bind_to_query_scalar(qry);
245                    }
246                }
247                qry
248            }
249        };
250    }
251}
252
253// impl From<Vec<u8>> for Value {
254//     fn from(value: Vec<u8>) -> Self {
255//         Self::Binary(value)
256//     }
257// }
258
259macro_rules! impl_from_num_for_value {
260    ($t:ty, $v:ident) => {
261        impl From<$t> for Value {
262            fn from(value: $t) -> Self {
263                Value::$v(Some(value))
264            }
265        }
266
267        impl From<&$t> for Value {
268            fn from(value: &$t) -> Self {
269                Value::$v(Some(*value))
270            }
271        }
272
273        impl From<Option<$t>> for Value {
274            fn from(value: Option<$t>) -> Self {
275                Value::$v(value)
276            }
277        }
278    };
279}
280
281macro_rules! impl_from_unsigned_num_for_value {
282    ($t:ty, $v:ident, $target:ty) => {
283        impl From<$t> for Value {
284            fn from(value: $t) -> Self {
285                Value::$v(Some(value as $target))
286            }
287        }
288
289        impl From<&$t> for Value {
290            fn from(value: &$t) -> Self {
291                Value::$v(Some(*value as $target))
292            }
293        }
294
295        impl From<Option<$t>> for Value {
296            fn from(value: Option<$t>) -> Self {
297                if let Some(val) = value {
298                    Value::$v(Some(val as $target))
299                } else {
300                    Value::$v(None)
301                }
302            }
303        }
304    };
305}
306
307macro_rules! impl_from_clone_for_value {
308    ($t:ty, $v:ident) => {
309        impl From<$t> for Value {
310            fn from(value: $t) -> Self {
311                Value::$v(Some(value.to_owned()))
312            }
313        }
314
315        impl From<&$t> for Value {
316            fn from(value: &$t) -> Self {
317                Value::$v(Some(value.clone()))
318            }
319        }
320
321        impl From<Option<$t>> for Value {
322            fn from(value: Option<$t>) -> Self {
323                Value::$v(value.clone())
324            }
325        }
326    };
327}
328
329impl_from_num_for_value!(bool, Bool);
330
331impl_from_num_for_value!(i16, Short);
332impl_from_num_for_value!(i32, Int);
333impl_from_num_for_value!(i64, Long);
334// impl_from_unsigned_num_for_value!(u8, Byte, i8);
335impl_from_unsigned_num_for_value!(u16, Short, i16);
336impl_from_unsigned_num_for_value!(u32, Int, i32);
337impl_from_unsigned_num_for_value!(u64, Long, i64);
338impl_from_clone_for_value!(Vec<u8>, Binary);
339impl_from_num_for_value!(f64, Double);
340impl_from_num_for_value!(f32, Float);
341impl_from_clone_for_value!(chrono::NaiveDateTime, ChronoDate);
342impl_from_clone_for_value!(String, Text);
343
344// impl_from_array_for_value!($($t:ty) *);
345
346// impl From<Vec<i64>> for Value {
347//     fn from(value: Vec<i64>) -> Self {
348//         Self::Array(value.iter().map(|v| Value::from(v)).collect())
349//     }
350// }
351
352macro_rules! impl_from_array_for_value {
353    ( $( $t:ty) * ) => {
354        $(
355            impl From<Vec<$t>> for Value {
356                fn from(value: Vec<$t>) -> Self {
357                    Self::Array(value.iter().map(|v| Value::from(v)).collect())
358                }
359            }
360        )*
361    };
362}
363impl_from_array_for_value!(bool i16 i32 i64 u16 u32 u64 f32 f64 String chrono::NaiveDateTime);
364
365// impl From<Option<i32>> for Value {
366//     fn from(value: Option<i32>) -> Self {
367//         Self::Int(value)
368//     }
369// }
370
371// impl From<&i64> for Value {
372//     fn from(value: &i64) -> Self {
373//         Self::Long(*value)
374//     }
375// }
376
377// impl From<&f64> for Value {
378//     fn from(value: &f64) -> Self {
379//         Self::Float(*value)
380//     }
381// }
382
383// impl From<&String> for Value {
384//     fn from(value: &String) -> Self {
385//         Self::Text(value.clone())
386//     }
387// }
388
389// impl From<&chrono::NaiveDateTime> for Value {
390//     fn from(value: &chrono::NaiveDateTime) -> Self {
391//         Self::ChronoDate(value.clone())
392//     }
393// }