1use crate::{
2 AsValue, DynQuery, Error, Expression, GenericSqlWriter, Result, TableRef, interval::Interval,
3};
4use proc_macro2::TokenStream;
5use quote::{ToTokens, quote};
6use rust_decimal::Decimal;
7use serde_json::Value as JsonValue;
8use std::{
9 borrow::Cow,
10 collections::HashMap,
11 fmt::{self, Display},
12 hash::Hash,
13 mem::discriminant,
14};
15use time::{Date, OffsetDateTime, PrimitiveDateTime, Time};
16use uuid::Uuid;
17
18#[derive(Default, Debug, Clone)]
22pub enum Value {
23 #[default]
25 Null,
26 Boolean(Option<bool>),
27 Int8(Option<i8>),
28 Int16(Option<i16>),
29 Int32(Option<i32>),
30 Int64(Option<i64>),
31 Int128(Option<i128>),
32 UInt8(Option<u8>),
33 UInt16(Option<u16>),
34 UInt32(Option<u32>),
35 UInt64(Option<u64>),
36 UInt128(Option<u128>),
37 Float32(Option<f32>),
38 Float64(Option<f64>),
39 Decimal(Option<Decimal>, u8, u8),
41 Char(Option<char>),
42 Varchar(Option<Cow<'static, str>>),
43 Blob(Option<Box<[u8]>>),
44 Date(Option<Date>),
45 Time(Option<Time>),
46 Timestamp(Option<PrimitiveDateTime>),
47 TimestampWithTimezone(Option<OffsetDateTime>),
48 Interval(Option<Interval>),
49 Uuid(Option<Uuid>),
50 Array(Option<Box<[Value]>>, Box<Value>, u32),
52 List(Option<Vec<Value>>, Box<Value>),
54 Map(Option<HashMap<Value, Value>>, Box<Value>, Box<Value>),
56 Json(Option<JsonValue>),
57 Struct(Option<Vec<(String, Value)>>, Vec<(String, Value)>, TableRef),
59 Unknown(Option<String>),
61}
62
63impl Value {
64 pub fn same_type(&self, other: &Self) -> bool {
65 match (self, other) {
66 (Self::Decimal(.., l_width, l_scale), Self::Decimal(.., r_width, r_scale)) => {
67 (*l_width == 0 || *r_width == 0 || l_width == r_width)
68 && (*l_scale == 0 || *r_scale == 0 || l_scale == r_scale)
69 }
70 (Self::Array(.., l_type, l_len), Self::Array(.., r_type, r_len)) => {
71 l_len == r_len && l_type.same_type(&r_type)
72 }
73 (Self::List(.., l), Self::List(.., r)) => l.same_type(r),
74 (Self::Map(.., l_key, l_value), Self::Map(.., r_key, r_value)) => {
75 l_key.same_type(r_key) && l_value.same_type(&r_value)
76 }
77 _ => discriminant(self) == discriminant(other),
78 }
79 }
80
81 pub fn is_null(&self) -> bool {
82 match self {
83 Value::Null
84 | Value::Boolean(None, ..)
85 | Value::Int8(None, ..)
86 | Value::Int16(None, ..)
87 | Value::Int32(None, ..)
88 | Value::Int64(None, ..)
89 | Value::Int128(None, ..)
90 | Value::UInt8(None, ..)
91 | Value::UInt16(None, ..)
92 | Value::UInt32(None, ..)
93 | Value::UInt64(None, ..)
94 | Value::UInt128(None, ..)
95 | Value::Float32(None, ..)
96 | Value::Float64(None, ..)
97 | Value::Decimal(None, ..)
98 | Value::Char(None, ..)
99 | Value::Varchar(None, ..)
100 | Value::Blob(None, ..)
101 | Value::Date(None, ..)
102 | Value::Time(None, ..)
103 | Value::Timestamp(None, ..)
104 | Value::TimestampWithTimezone(None, ..)
105 | Value::Interval(None, ..)
106 | Value::Uuid(None, ..)
107 | Value::Array(None, ..)
108 | Value::List(None, ..)
109 | Value::Map(None, ..)
110 | Value::Json(None, ..)
111 | Value::Json(Some(serde_json::Value::Null), ..)
112 | Value::Struct(None, ..)
113 | Value::Unknown(None, ..) => true,
114 _ => false,
115 }
116 }
117
118 pub fn as_null(&self) -> Value {
119 match self {
120 Value::Null => Value::Null,
121 Value::Boolean(..) => Value::Boolean(None),
122 Value::Int8(..) => Value::Int8(None),
123 Value::Int16(..) => Value::Int16(None),
124 Value::Int32(..) => Value::Int32(None),
125 Value::Int64(..) => Value::Int64(None),
126 Value::Int128(..) => Value::Int128(None),
127 Value::UInt8(..) => Value::UInt8(None),
128 Value::UInt16(..) => Value::UInt16(None),
129 Value::UInt32(..) => Value::UInt32(None),
130 Value::UInt64(..) => Value::UInt64(None),
131 Value::UInt128(..) => Value::UInt128(None),
132 Value::Float32(..) => Value::Float32(None),
133 Value::Float64(..) => Value::Float64(None),
134 Value::Decimal(.., w, s) => Value::Decimal(None, *w, *s),
135 Value::Char(..) => Value::Char(None),
136 Value::Varchar(..) => Value::Varchar(None),
137 Value::Blob(..) => Value::Blob(None),
138 Value::Date(..) => Value::Date(None),
139 Value::Time(..) => Value::Time(None),
140 Value::Timestamp(..) => Value::Timestamp(None),
141 Value::TimestampWithTimezone(..) => Value::TimestampWithTimezone(None),
142 Value::Interval(..) => Value::Interval(None),
143 Value::Uuid(..) => Value::Uuid(None),
144 Value::Array(.., t, len) => Value::Array(None, t.clone(), *len),
145 Value::List(.., t) => Value::List(None, t.clone()),
146 Value::Map(.., k, v) => Value::Map(None, k.clone(), v.clone()),
147 Value::Json(..) => Value::Json(None),
148 Value::Struct(.., ty, name) => Value::Struct(None, ty.clone(), name.clone()),
149 Value::Unknown(..) => Value::Unknown(None),
150 }
151 }
152
153 pub fn try_as(self, value: &Value) -> Result<Value> {
154 if self.same_type(value) {
155 return Ok(self);
156 }
157 match value {
158 Value::Boolean(..) => bool::try_from_value(self).map(AsValue::as_value),
159 Value::Int8(..) => i8::try_from_value(self).map(AsValue::as_value),
160 Value::Int16(..) => i16::try_from_value(self).map(AsValue::as_value),
161 Value::Int32(..) => i32::try_from_value(self).map(AsValue::as_value),
162 Value::Int64(..) => i64::try_from_value(self).map(AsValue::as_value),
163 Value::Int128(..) => i128::try_from_value(self).map(AsValue::as_value),
164 Value::UInt8(..) => u8::try_from_value(self).map(AsValue::as_value),
165 Value::UInt16(..) => u16::try_from_value(self).map(AsValue::as_value),
166 Value::UInt32(..) => u32::try_from_value(self).map(AsValue::as_value),
167 Value::UInt64(..) => u64::try_from_value(self).map(AsValue::as_value),
168 Value::UInt128(..) => u128::try_from_value(self).map(AsValue::as_value),
169 Value::Float32(..) => f32::try_from_value(self).map(AsValue::as_value),
170 Value::Float64(..) => f64::try_from_value(self).map(AsValue::as_value),
171 Value::Decimal(..) => Decimal::try_from_value(self).map(AsValue::as_value),
172 Value::Char(..) => char::try_from_value(self).map(AsValue::as_value),
173 Value::Varchar(..) => String::try_from_value(self).map(AsValue::as_value),
174 Value::Blob(..) => Box::<[u8]>::try_from_value(self).map(AsValue::as_value),
175 Value::Date(..) => Date::try_from_value(self).map(AsValue::as_value),
176 Value::Time(..) => Time::try_from_value(self).map(AsValue::as_value),
177 Value::Timestamp(..) => PrimitiveDateTime::try_from_value(self).map(AsValue::as_value),
178 Value::TimestampWithTimezone(..) => {
179 OffsetDateTime::try_from_value(self).map(AsValue::as_value)
180 }
181 Value::Interval(..) => Interval::try_from_value(self).map(AsValue::as_value),
182 Value::Uuid(..) => Uuid::try_from_value(self).map(AsValue::as_value),
183 _ => {
189 return Err(Error::msg(format!(
190 "Cannot convert value {:?} into value {:?}",
191 self, value
192 )));
193 }
194 }
195 }
196
197 pub fn is_scalar(&self) -> bool {
198 match self {
199 Value::Boolean(..)
200 | Value::Int8(..)
201 | Value::Int16(..)
202 | Value::Int32(..)
203 | Value::Int64(..)
204 | Value::Int128(..)
205 | Value::UInt8(..)
206 | Value::UInt16(..)
207 | Value::UInt32(..)
208 | Value::UInt64(..)
209 | Value::UInt128(..)
210 | Value::Float32(..)
211 | Value::Float64(..)
212 | Value::Decimal(..)
213 | Value::Char(..)
214 | Value::Varchar(..)
215 | Value::Blob(..)
216 | Value::Date(..)
217 | Value::Time(..)
218 | Value::Timestamp(..)
219 | Value::TimestampWithTimezone(..)
220 | Value::Interval(..)
221 | Value::Uuid(..)
222 | Value::Unknown(..) => true,
223 _ => false,
224 }
225 }
226}
227
228impl PartialEq for Value {
229 fn eq(&self, other: &Self) -> bool {
230 match (self, other) {
231 (Self::Boolean(l), Self::Boolean(r)) => l == r,
232 (Self::Int8(l), Self::Int8(r)) => l == r,
233 (Self::Int16(l), Self::Int16(r)) => l == r,
234 (Self::Int32(l), Self::Int32(r)) => l == r,
235 (Self::Int64(l), Self::Int64(r)) => l == r,
236 (Self::Int128(l), Self::Int128(r)) => l == r,
237 (Self::UInt8(l), Self::UInt8(r)) => l == r,
238 (Self::UInt16(l), Self::UInt16(r)) => l == r,
239 (Self::UInt32(l), Self::UInt32(r)) => l == r,
240 (Self::UInt64(l), Self::UInt64(r)) => l == r,
241 (Self::UInt128(l), Self::UInt128(r)) => l == r,
242 (Self::Float32(l), Self::Float32(r)) => {
243 l == r
244 || l.and_then(|l| r.and_then(|r| Some(l.is_nan() && r.is_nan())))
245 .unwrap_or_default()
246 }
247 (Self::Float64(l), Self::Float64(r)) => {
248 l == r
249 || l.and_then(|l| r.and_then(|r| Some(l.is_nan() && r.is_nan())))
250 .unwrap_or_default()
251 }
252 (Self::Decimal(l, l_width, l_scale), Self::Decimal(r, r_width, r_scale)) => {
253 l == r && l_width == r_width && l_scale == r_scale
254 }
255 (Self::Char(l), Self::Char(r)) => l == r,
256 (Self::Varchar(l), Self::Varchar(r)) => l == r,
257 (Self::Blob(l), Self::Blob(r)) => l == r,
258 (Self::Date(l), Self::Date(r)) => l == r,
259 (Self::Time(l), Self::Time(r)) => l == r,
260 (Self::Timestamp(l), Self::Timestamp(r)) => l == r,
261 (Self::TimestampWithTimezone(l), Self::TimestampWithTimezone(r)) => l == r,
262 (Self::Interval(l), Self::Interval(r)) => l == r,
263 (Self::Uuid(l), Self::Uuid(r)) => l == r,
264 (Self::Array(l, ..), Self::Array(r, ..)) => l == r && self.same_type(other),
265 (Self::List(l, ..), Self::List(r, ..)) => l == r && self.same_type(other),
266 (Self::Map(None, ..), Self::Map(None, ..)) => self.same_type(other),
267 (Self::Map(Some(l), ..), Self::Map(Some(r), ..)) => {
268 l.is_empty() == r.is_empty() && self.same_type(other)
269 }
270 (Self::Map(..), Self::Map(..)) => self.same_type(other),
271 (Self::Json(l), Self::Json(r)) => l == r,
272 (Self::Struct(l, l_ty, l_name), Self::Struct(r, r_ty, r_name)) => {
273 l_name == r_name && l == r && l_ty == r_ty
274 }
275 (Self::Unknown(..), Self::Unknown(..)) => false,
276 _ => false,
277 }
278 }
279}
280
281impl Eq for Value {}
282
283impl Hash for Value {
284 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
285 use Value::*;
286 discriminant(self).hash(state);
287 match self {
288 Null => {}
289 Boolean(v) => v.hash(state),
290 Int8(v) => v.hash(state),
291 Int16(v) => v.hash(state),
292 Int32(v) => v.hash(state),
293 Int64(v) => v.hash(state),
294 Int128(v) => v.hash(state),
295
296 UInt8(v) => v.hash(state),
297 UInt16(v) => v.hash(state),
298 UInt32(v) => v.hash(state),
299 UInt64(v) => v.hash(state),
300 UInt128(v) => v.hash(state),
301 Float32(Some(v)) => {
302 v.to_bits().hash(state);
303 }
304 Float32(None) => None::<u32>.hash(state),
305 Float64(Some(v)) => {
306 v.to_bits().hash(state);
307 }
308 Float64(None) => None::<u64>.hash(state),
309 Decimal(v, width, scale) => {
310 v.hash(state);
311 width.hash(state);
312 scale.hash(state);
313 }
314 Char(v) => v.hash(state),
315 Varchar(v) => v.hash(state),
316 Blob(v) => v.hash(state),
317 Date(v) => v.hash(state),
318 Time(v) => v.hash(state),
319 Timestamp(v) => v.hash(state),
320 TimestampWithTimezone(v) => v.hash(state),
321 Interval(v) => v.hash(state),
322 Uuid(v) => v.hash(state),
323 Array(v, typ, len) => {
324 v.hash(state);
325 typ.hash(state);
326 len.hash(state);
327 }
328 List(v, typ) => {
329 v.hash(state);
330 typ.hash(state);
331 }
332 Map(v, key, val) => {
333 match v {
334 Some(map) => {
335 for (key, val) in map {
336 key.hash(state);
337 val.hash(state);
338 }
339 }
340 None => {}
341 }
342 key.hash(state);
343 val.hash(state);
344 }
345 Json(v) => v.hash(state),
346 Struct(v, t, name) => {
347 match v {
348 Some(v) => v.hash(state),
349 None => {}
350 }
351 t.hash(state);
352 name.hash(state);
353 }
354 Unknown(v) => v.hash(state),
355 }
356 }
357}
358
359impl Display for Value {
360 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361 let mut out = DynQuery::default();
362 self.write_query(&GenericSqlWriter::new(), &mut Default::default(), &mut out);
363 let _ = f.write_str(out.buffer());
364 Ok(())
365 }
366}
367
368#[derive(Default)]
370pub struct TypeDecoded {
371 pub value: Value,
373 pub nullable: bool,
375 pub passive: bool,
377}
378
379pub type CheckPassive = Box<dyn Fn(TokenStream) -> TokenStream>;
380
381impl ToTokens for Value {
382 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
383 let ts = match self {
384 Value::Null => quote!(::tank::Value::Null),
385 Value::Boolean(..) => quote!(::tank::Value::Boolean(None)),
386 Value::Int8(..) => quote!(::tank::Value::Int8(None)),
387 Value::Int16(..) => quote!(::tank::Value::Int16(None)),
388 Value::Int32(..) => quote!(::tank::Value::Int32(None)),
389 Value::Int64(..) => quote!(::tank::Value::Int64(None)),
390 Value::Int128(..) => quote!(::tank::Value::Int128(None)),
391 Value::UInt8(..) => quote!(::tank::Value::UInt8(None)),
392 Value::UInt16(..) => quote!(::tank::Value::UInt16(None)),
393 Value::UInt32(..) => quote!(::tank::Value::UInt32(None)),
394 Value::UInt64(..) => quote!(::tank::Value::UInt64(None)),
395 Value::UInt128(..) => quote!(::tank::Value::UInt128(None)),
396 Value::Float32(..) => quote!(::tank::Value::Float32(None)),
397 Value::Float64(..) => quote!(::tank::Value::Float64(None)),
398 Value::Decimal(.., width, scale) => {
399 quote!(::tank::Value::Decimal(None, #width, #scale))
400 }
401 Value::Char(..) => quote!(tank::Value::Char(None)),
402 Value::Varchar(..) => quote!(::tank::Value::Varchar(None)),
403 Value::Blob(..) => quote!(::tank::Value::Blob(None)),
404 Value::Date(..) => quote!(::tank::Value::Date(None)),
405 Value::Time(..) => quote!(::tank::Value::Time(None)),
406 Value::Timestamp(..) => quote!(::tank::Value::Timestamp(None)),
407 Value::TimestampWithTimezone(..) => quote!(::tank::Value::TimestampWithTimezone(None)),
408 Value::Interval(..) => quote!(::tank::Value::Interval(None)),
409 Value::Uuid(..) => quote!(::tank::Value::Uuid(None)),
410 Value::Array(.., inner, size) => {
411 quote!(::tank::Value::Array(None, Box::new(#inner), #size))
412 }
413 Value::List(.., inner) => {
414 let inner = inner.as_ref().to_token_stream();
415 quote!(::tank::Value::List(None, Box::new(#inner)))
416 }
417 Value::Map(.., key, value) => {
418 let key = key.as_ref().to_token_stream();
419 let value = value.as_ref().to_token_stream();
420 quote!(::tank::Value::Map(None, Box::new(#key), Box::new(#value)))
421 }
422 Value::Json(..) => quote!(::tank::Value::Json(None)),
423 Value::Struct(.., ty, name) => {
424 let values = ty.into_iter().map(|(k, v)| quote!((#k.into(), #v)));
425 quote!(::tank::Value::Struct(None, vec!(#(#values),*), #name))
426 }
427 Value::Unknown(..) => quote!(::tank::Value::Unknown(None)),
428 };
429 tokens.extend(ts);
430 }
431}