1use crate::{
2 AsValue, DynQuery, Expression, GenericSqlWriter, Result, TableRef, interval::Interval,
3};
4use anyhow::anyhow;
5use quote::{ToTokens, quote};
6use rust_decimal::Decimal;
7use serde_json::Value as JsonValue;
8use std::{
9 borrow::Cow,
10 collections::{HashMap, hash_map::DefaultHasher},
11 fmt::{self, Display},
12 hash::{Hash, Hasher},
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>),
28 Int8(Option<i8>),
30 Int16(Option<i16>),
32 Int32(Option<i32>),
34 Int64(Option<i64>),
36 Int128(Option<i128>),
38 UInt8(Option<u8>),
40 UInt16(Option<u16>),
42 UInt32(Option<u32>),
44 UInt64(Option<u64>),
46 UInt128(Option<u128>),
48 Float32(Option<f32>),
50 Float64(Option<f64>),
52 Decimal(Option<Decimal>, u8, u8),
54 Char(Option<char>),
56 Varchar(Option<Cow<'static, str>>),
58 Blob(Option<Box<[u8]>>),
60 Date(Option<Date>),
62 Time(Option<Time>),
64 Timestamp(Option<PrimitiveDateTime>),
66 TimestampWithTimezone(Option<OffsetDateTime>),
68 Interval(Option<Interval>),
70 Uuid(Option<Uuid>),
72 Array(Option<Box<[Value]>>, Box<Value>, u32),
74 List(Option<Vec<Value>>, Box<Value>),
76 Map(Option<HashMap<Value, Value>>, Box<Value>, Box<Value>),
78 Json(Option<JsonValue>),
80 Struct(Option<Vec<(String, Value)>>, Vec<(String, Value)>, TableRef),
82 Unknown(Option<String>),
84}
85
86impl Value {
87 pub fn same_type(&self, other: &Self) -> bool {
89 match (self, other) {
90 (Self::Decimal(.., l_width, l_scale), Self::Decimal(.., r_width, r_scale)) => {
91 (*l_width == 0 || *r_width == 0 || l_width == r_width)
92 && (*l_scale == 0 || *r_scale == 0 || l_scale == r_scale)
93 }
94 (Self::Array(.., l_type, l_len), Self::Array(.., r_type, r_len)) => {
95 l_len == r_len && l_type.same_type(&r_type)
96 }
97 (Self::List(.., l), Self::List(.., r)) => l.same_type(r),
98 (Self::Map(.., l_key, l_value), Self::Map(.., r_key, r_value)) => {
99 l_key.same_type(r_key) && l_value.same_type(&r_value)
100 }
101 _ => discriminant(self) == discriminant(other),
102 }
103 }
104
105 pub fn is_null(&self) -> bool {
107 match self {
108 Value::Null
109 | Value::Boolean(None, ..)
110 | Value::Int8(None, ..)
111 | Value::Int16(None, ..)
112 | Value::Int32(None, ..)
113 | Value::Int64(None, ..)
114 | Value::Int128(None, ..)
115 | Value::UInt8(None, ..)
116 | Value::UInt16(None, ..)
117 | Value::UInt32(None, ..)
118 | Value::UInt64(None, ..)
119 | Value::UInt128(None, ..)
120 | Value::Float32(None, ..)
121 | Value::Float64(None, ..)
122 | Value::Decimal(None, ..)
123 | Value::Char(None, ..)
124 | Value::Varchar(None, ..)
125 | Value::Blob(None, ..)
126 | Value::Date(None, ..)
127 | Value::Time(None, ..)
128 | Value::Timestamp(None, ..)
129 | Value::TimestampWithTimezone(None, ..)
130 | Value::Interval(None, ..)
131 | Value::Uuid(None, ..)
132 | Value::Array(None, ..)
133 | Value::List(None, ..)
134 | Value::Map(None, ..)
135 | Value::Json(None, ..)
136 | Value::Json(Some(serde_json::Value::Null), ..)
137 | Value::Struct(None, ..)
138 | Value::Unknown(None, ..) => true,
139 _ => false,
140 }
141 }
142
143 pub fn as_null(&self) -> Value {
145 match self {
146 Value::Null => Value::Null,
147 Value::Boolean(..) => Value::Boolean(None),
148 Value::Int8(..) => Value::Int8(None),
149 Value::Int16(..) => Value::Int16(None),
150 Value::Int32(..) => Value::Int32(None),
151 Value::Int64(..) => Value::Int64(None),
152 Value::Int128(..) => Value::Int128(None),
153 Value::UInt8(..) => Value::UInt8(None),
154 Value::UInt16(..) => Value::UInt16(None),
155 Value::UInt32(..) => Value::UInt32(None),
156 Value::UInt64(..) => Value::UInt64(None),
157 Value::UInt128(..) => Value::UInt128(None),
158 Value::Float32(..) => Value::Float32(None),
159 Value::Float64(..) => Value::Float64(None),
160 Value::Decimal(.., w, s) => Value::Decimal(None, *w, *s),
161 Value::Char(..) => Value::Char(None),
162 Value::Varchar(..) => Value::Varchar(None),
163 Value::Blob(..) => Value::Blob(None),
164 Value::Date(..) => Value::Date(None),
165 Value::Time(..) => Value::Time(None),
166 Value::Timestamp(..) => Value::Timestamp(None),
167 Value::TimestampWithTimezone(..) => Value::TimestampWithTimezone(None),
168 Value::Interval(..) => Value::Interval(None),
169 Value::Uuid(..) => Value::Uuid(None),
170 Value::Array(.., t, len) => Value::Array(None, t.clone(), *len),
171 Value::List(.., t) => Value::List(None, t.clone()),
172 Value::Map(.., k, v) => Value::Map(None, k.clone(), v.clone()),
173 Value::Json(..) => Value::Json(None),
174 Value::Struct(.., ty, name) => Value::Struct(None, ty.clone(), name.clone()),
175 Value::Unknown(..) => Value::Unknown(None),
176 }
177 }
178
179 pub fn try_as(self, target_type: &Value) -> Result<Value> {
181 if self.same_type(target_type) {
182 return Ok(self);
183 }
184 match target_type {
185 Value::Boolean(..) => bool::try_from_value(self).map(AsValue::as_value),
186 Value::Int8(..) => i8::try_from_value(self).map(AsValue::as_value),
187 Value::Int16(..) => i16::try_from_value(self).map(AsValue::as_value),
188 Value::Int32(..) => i32::try_from_value(self).map(AsValue::as_value),
189 Value::Int64(..) => i64::try_from_value(self).map(AsValue::as_value),
190 Value::Int128(..) => i128::try_from_value(self).map(AsValue::as_value),
191 Value::UInt8(..) => u8::try_from_value(self).map(AsValue::as_value),
192 Value::UInt16(..) => u16::try_from_value(self).map(AsValue::as_value),
193 Value::UInt32(..) => u32::try_from_value(self).map(AsValue::as_value),
194 Value::UInt64(..) => u64::try_from_value(self).map(AsValue::as_value),
195 Value::UInt128(..) => u128::try_from_value(self).map(AsValue::as_value),
196 Value::Float32(..) => f32::try_from_value(self).map(AsValue::as_value),
197 Value::Float64(..) => f64::try_from_value(self).map(AsValue::as_value),
198 Value::Decimal(..) => Decimal::try_from_value(self).map(AsValue::as_value),
199 Value::Char(..) => char::try_from_value(self).map(AsValue::as_value),
200 Value::Varchar(..) => String::try_from_value(self).map(AsValue::as_value),
201 Value::Blob(..) => Box::<[u8]>::try_from_value(self).map(AsValue::as_value),
202 Value::Date(..) => Date::try_from_value(self).map(AsValue::as_value),
203 Value::Time(..) => Time::try_from_value(self).map(AsValue::as_value),
204 Value::Timestamp(..) => PrimitiveDateTime::try_from_value(self).map(AsValue::as_value),
205 Value::TimestampWithTimezone(..) => {
206 OffsetDateTime::try_from_value(self).map(AsValue::as_value)
207 }
208 Value::Interval(..) => Interval::try_from_value(self).map(AsValue::as_value),
209 Value::Uuid(..) => Uuid::try_from_value(self).map(AsValue::as_value),
210 _ => {
216 return Err(anyhow!(
217 "Cannot convert value {:?} to {:?}",
218 self,
219 target_type
220 ));
221 }
222 }
223 }
224
225 pub fn is_scalar(&self) -> bool {
227 match self {
228 Value::Boolean(..)
229 | Value::Int8(..)
230 | Value::Int16(..)
231 | Value::Int32(..)
232 | Value::Int64(..)
233 | Value::Int128(..)
234 | Value::UInt8(..)
235 | Value::UInt16(..)
236 | Value::UInt32(..)
237 | Value::UInt64(..)
238 | Value::UInt128(..)
239 | Value::Float32(..)
240 | Value::Float64(..)
241 | Value::Decimal(..)
242 | Value::Char(..)
243 | Value::Varchar(..)
244 | Value::Blob(..)
245 | Value::Date(..)
246 | Value::Time(..)
247 | Value::Timestamp(..)
248 | Value::TimestampWithTimezone(..)
249 | Value::Interval(..)
250 | Value::Uuid(..)
251 | Value::Unknown(..) => true,
252 _ => false,
253 }
254 }
255}
256
257impl PartialEq for Value {
258 fn eq(&self, other: &Self) -> bool {
259 match (self, other) {
260 (Self::Null, Self::Null) => true,
261 (Self::Boolean(l), Self::Boolean(r)) => l == r,
262 (Self::Int8(l), Self::Int8(r)) => l == r,
263 (Self::Int16(l), Self::Int16(r)) => l == r,
264 (Self::Int32(l), Self::Int32(r)) => l == r,
265 (Self::Int64(l), Self::Int64(r)) => l == r,
266 (Self::Int128(l), Self::Int128(r)) => l == r,
267 (Self::UInt8(l), Self::UInt8(r)) => l == r,
268 (Self::UInt16(l), Self::UInt16(r)) => l == r,
269 (Self::UInt32(l), Self::UInt32(r)) => l == r,
270 (Self::UInt64(l), Self::UInt64(r)) => l == r,
271 (Self::UInt128(l), Self::UInt128(r)) => l == r,
272 (Self::Float32(l), Self::Float32(r)) => {
273 l == r
274 || l.and_then(|l| r.and_then(|r| Some(l.is_nan() && r.is_nan())))
275 .unwrap_or_default()
276 }
277 (Self::Float64(l), Self::Float64(r)) => {
278 l == r
279 || l.and_then(|l| r.and_then(|r| Some(l.is_nan() && r.is_nan())))
280 .unwrap_or_default()
281 }
282 (Self::Decimal(l, l_width, l_scale), Self::Decimal(r, r_width, r_scale)) => {
283 l == r && l_width == r_width && l_scale == r_scale
284 }
285 (Self::Char(l), Self::Char(r)) => l == r,
286 (Self::Varchar(l), Self::Varchar(r)) => l == r,
287 (Self::Blob(l), Self::Blob(r)) => l == r,
288 (Self::Date(l), Self::Date(r)) => l == r,
289 (Self::Time(l), Self::Time(r)) => l == r,
290 (Self::Timestamp(l), Self::Timestamp(r)) => l == r,
291 (Self::TimestampWithTimezone(l), Self::TimestampWithTimezone(r)) => l == r,
292 (Self::Interval(l), Self::Interval(r)) => l == r,
293 (Self::Uuid(l), Self::Uuid(r)) => l == r,
294 (Self::Array(l, l_ty, l_len), Self::Array(r, r_ty, r_len)) => {
295 l_len == r_len && l_ty == r_ty && l == r
296 }
297 (Self::List(l, l_ty), Self::List(r, r_ty)) => l_ty == r_ty && l == r,
298 (Self::Map(None, l_k, l_v), Self::Map(None, r_k, r_v)) => l_k == r_k && l_v == r_v,
299 (Self::Map(Some(l), l_k, l_v), Self::Map(Some(r), r_k, r_v)) => {
300 l_k == r_k && l_v == r_v && l == r
301 }
302 (Self::Map(..), Self::Map(..)) => false,
303 (Self::Json(l), Self::Json(r)) => l == r,
304 (Self::Struct(l, l_ty, l_name), Self::Struct(r, r_ty, r_name)) => {
305 l_name == r_name && l == r && l_ty == r_ty
306 }
307 (Self::Unknown(l), Self::Unknown(r)) => l == r,
308 _ => false,
309 }
310 }
311}
312
313impl Eq for Value {}
314
315fn hash_f32_value<H: std::hash::Hasher>(value: f32, state: &mut H) {
316 let bits = if value == 0.0 {
317 0.0f32.to_bits()
318 } else if value.is_nan() {
319 f32::NAN.to_bits()
320 } else {
321 value.to_bits()
322 };
323 bits.hash(state);
324}
325
326fn hash_f64_value<H: std::hash::Hasher>(value: f64, state: &mut H) {
327 let bits = if value == 0.0 {
328 0.0f64.to_bits()
329 } else if value.is_nan() {
330 f64::NAN.to_bits()
331 } else {
332 value.to_bits()
333 };
334 bits.hash(state);
335}
336
337fn hash_map_value<H: std::hash::Hasher>(
338 value: &Option<HashMap<Value, Value>>,
339 key_ty: &Value,
340 value_ty: &Value,
341 state: &mut H,
342) {
343 value.is_some().hash(state);
344 if let Some(map) = value {
345 let mut entry_hashes = map
346 .iter()
347 .map(|(key, value)| {
348 let mut hasher = DefaultHasher::new();
349 key.hash(&mut hasher);
350 value.hash(&mut hasher);
351 hasher.finish()
352 })
353 .collect::<Vec<_>>();
354 entry_hashes.sort_unstable();
355 entry_hashes.hash(state);
356 }
357 key_ty.hash(state);
358 value_ty.hash(state);
359}
360
361impl Hash for Value {
362 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
363 use Value::*;
364 discriminant(self).hash(state);
365 match self {
366 Null => {}
367 Boolean(v) => v.hash(state),
368 Int8(v) => v.hash(state),
369 Int16(v) => v.hash(state),
370 Int32(v) => v.hash(state),
371 Int64(v) => v.hash(state),
372 Int128(v) => v.hash(state),
373
374 UInt8(v) => v.hash(state),
375 UInt16(v) => v.hash(state),
376 UInt32(v) => v.hash(state),
377 UInt64(v) => v.hash(state),
378 UInt128(v) => v.hash(state),
379 Float32(Some(v)) => hash_f32_value(*v, state),
380 Float32(None) => None::<u32>.hash(state),
381 Float64(Some(v)) => hash_f64_value(*v, state),
382 Float64(None) => None::<u64>.hash(state),
383 Decimal(v, width, scale) => {
384 v.hash(state);
385 width.hash(state);
386 scale.hash(state);
387 }
388 Char(v) => v.hash(state),
389 Varchar(v) => v.hash(state),
390 Blob(v) => v.hash(state),
391 Date(v) => v.hash(state),
392 Time(v) => v.hash(state),
393 Timestamp(v) => v.hash(state),
394 TimestampWithTimezone(v) => v.hash(state),
395 Interval(v) => v.hash(state),
396 Uuid(v) => v.hash(state),
397 Array(v, typ, len) => {
398 v.hash(state);
399 typ.hash(state);
400 len.hash(state);
401 }
402 List(v, typ) => {
403 v.hash(state);
404 typ.hash(state);
405 }
406 Map(v, key, val) => hash_map_value(v, key, val, state),
407 Json(v) => v.hash(state),
408 Struct(v, t, name) => {
409 match v {
410 Some(v) => v.hash(state),
411 None => {}
412 }
413 t.hash(state);
414 name.hash(state);
415 }
416 Unknown(v) => v.hash(state),
417 }
418 }
419}
420
421impl Display for Value {
422 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
423 let mut out = DynQuery::default();
424 self.write_query(&GenericSqlWriter::new(), &mut Default::default(), &mut out);
425 let _ = f.write_str(out.buffer());
426 Ok(())
427 }
428}
429
430#[derive(Default)]
432pub struct TypeDecoded {
433 pub value: Value,
435 pub nullable: bool,
437}
438
439impl ToTokens for Value {
440 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
441 let ts = match self {
442 Value::Null => quote!(::tank::Value::Null),
443 Value::Boolean(..) => quote!(::tank::Value::Boolean(None)),
444 Value::Int8(..) => quote!(::tank::Value::Int8(None)),
445 Value::Int16(..) => quote!(::tank::Value::Int16(None)),
446 Value::Int32(..) => quote!(::tank::Value::Int32(None)),
447 Value::Int64(..) => quote!(::tank::Value::Int64(None)),
448 Value::Int128(..) => quote!(::tank::Value::Int128(None)),
449 Value::UInt8(..) => quote!(::tank::Value::UInt8(None)),
450 Value::UInt16(..) => quote!(::tank::Value::UInt16(None)),
451 Value::UInt32(..) => quote!(::tank::Value::UInt32(None)),
452 Value::UInt64(..) => quote!(::tank::Value::UInt64(None)),
453 Value::UInt128(..) => quote!(::tank::Value::UInt128(None)),
454 Value::Float32(..) => quote!(::tank::Value::Float32(None)),
455 Value::Float64(..) => quote!(::tank::Value::Float64(None)),
456 Value::Decimal(.., width, scale) => {
457 quote!(::tank::Value::Decimal(None, #width, #scale))
458 }
459 Value::Char(..) => quote!(::tank::Value::Char(None)),
460 Value::Varchar(..) => quote!(::tank::Value::Varchar(None)),
461 Value::Blob(..) => quote!(::tank::Value::Blob(None)),
462 Value::Date(..) => quote!(::tank::Value::Date(None)),
463 Value::Time(..) => quote!(::tank::Value::Time(None)),
464 Value::Timestamp(..) => quote!(::tank::Value::Timestamp(None)),
465 Value::TimestampWithTimezone(..) => quote!(::tank::Value::TimestampWithTimezone(None)),
466 Value::Interval(..) => quote!(::tank::Value::Interval(None)),
467 Value::Uuid(..) => quote!(::tank::Value::Uuid(None)),
468 Value::Array(.., inner, size) => {
469 quote!(::tank::Value::Array(None, Box::new(#inner), #size))
470 }
471 Value::List(.., inner) => {
472 let inner = inner.as_ref().to_token_stream();
473 quote!(::tank::Value::List(None, Box::new(#inner)))
474 }
475 Value::Map(.., key, value) => {
476 let key = key.as_ref().to_token_stream();
477 let value = value.as_ref().to_token_stream();
478 quote!(::tank::Value::Map(None, Box::new(#key), Box::new(#value)))
479 }
480 Value::Json(..) => quote!(::tank::Value::Json(None)),
481 Value::Struct(.., ty, name) => {
482 let values = ty.into_iter().map(|(k, v)| quote!((#k.into(), #v)));
483 quote!(::tank::Value::Struct(None, vec!(#(#values),*), #name))
484 }
485 Value::Unknown(..) => quote!(::tank::Value::Unknown(None)),
486 };
487 tokens.extend(ts);
488 }
489}