1mod bytes;
2mod clickhouse_uuid;
3mod date;
4#[cfg(feature = "rust_decimal")]
5mod decimal;
6mod fixed_point;
7mod geo;
8mod int256;
9mod ip;
10#[cfg(feature = "serde")]
11pub mod json;
12pub mod vec_tuple;
13
14#[cfg(test)]
15mod tests;
16
17use std::borrow::Cow;
18use std::fmt;
19use std::hash::Hash;
20
21pub use bytes::*;
22use chrono::{NaiveDate, SecondsFormat};
23use chrono_tz::Tz;
24pub use date::*;
25pub use fixed_point::*;
26pub use geo::*;
27pub use int256::*;
28pub use ip::*;
29
30use super::convert::{FromSql, ToSql, unexpected_type};
31use super::types::Type;
32use crate::Result;
33
34#[derive(Clone)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39pub enum Value {
40 Int8(i8),
41 Int16(i16),
42 Int32(i32),
43 Int64(i64),
44 Int128(i128),
45 Int256(i256),
46
47 UInt8(u8),
48 UInt16(u16),
49 UInt32(u32),
50 UInt64(u64),
51 UInt128(u128),
52 UInt256(u256),
53
54 Float32(f32),
55 Float64(f64),
56
57 Decimal32(usize, i32),
58 Decimal64(usize, i64),
59 Decimal128(usize, i128),
60 Decimal256(usize, i256),
61
62 String(Vec<u8>),
63
64 Uuid(::uuid::Uuid),
65
66 Date(Date),
67 Date32(Date32),
68 DateTime(DateTime),
69 DateTime64(DynDateTime64),
70
71 Enum8(String, i8),
72 Enum16(String, i16),
73 Array(Vec<Value>),
74
75 Tuple(Vec<Value>),
76
77 Null,
78
79 Map(Vec<Value>, Vec<Value>),
80
81 Ipv4(Ipv4),
82 Ipv6(Ipv6),
83
84 Point(Point),
85 Ring(Ring),
86 Polygon(Polygon),
87 MultiPolygon(MultiPolygon),
88
89 Object(Vec<u8>),
90}
91
92impl PartialEq for Value {
93 fn eq(&self, other: &Self) -> bool {
94 #[expect(clippy::match_same_arms)]
95 match (self, other) {
96 (Self::Int8(l0), Self::Int8(r0)) => l0 == r0,
97 (Self::Int16(l0), Self::Int16(r0)) => l0 == r0,
98 (Self::Int32(l0), Self::Int32(r0)) => l0 == r0,
99 (Self::Int64(l0), Self::Int64(r0)) => l0 == r0,
100 (Self::Int128(l0), Self::Int128(r0)) => l0 == r0,
101 (Self::Int256(l0), Self::Int256(r0)) => l0 == r0,
102 (Self::UInt8(l0), Self::UInt8(r0)) => l0 == r0,
103 (Self::UInt16(l0), Self::UInt16(r0)) => l0 == r0,
104 (Self::UInt32(l0), Self::UInt32(r0)) => l0 == r0,
105 (Self::UInt64(l0), Self::UInt64(r0)) => l0 == r0,
106 (Self::UInt128(l0), Self::UInt128(r0)) => l0 == r0,
107 (Self::UInt256(l0), Self::UInt256(r0)) => l0 == r0,
108 (Self::Float32(l0), Self::Float32(r0)) => l0.to_bits() == r0.to_bits(),
109 (Self::Float64(l0), Self::Float64(r0)) => l0.to_bits() == r0.to_bits(),
110 (Self::Decimal32(l0, l1), Self::Decimal32(r0, r1)) => l0 == r0 && l1 == r1,
111 (Self::Decimal64(l0, l1), Self::Decimal64(r0, r1)) => l0 == r0 && l1 == r1,
112 (Self::Decimal128(l0, l1), Self::Decimal128(r0, r1)) => l0 == r0 && l1 == r1,
113 (Self::Decimal256(l0, l1), Self::Decimal256(r0, r1)) => l0 == r0 && l1 == r1,
114 (Self::String(l0), Self::String(r0)) => l0 == r0,
115 (Self::Uuid(l0), Self::Uuid(r0)) => l0 == r0,
116 (Self::Date(l0), Self::Date(r0)) => l0 == r0,
117 (Self::Date32(l0), Self::Date32(r0)) => l0 == r0,
118 (Self::DateTime(l0), Self::DateTime(r0)) => l0 == r0,
119 (Self::DateTime64(l0), Self::DateTime64(r0)) => l0 == r0,
120 (Self::Enum8(v0, l0), Self::Enum8(v1, r0)) => l0 == r0 && v0 == v1,
121 (Self::Enum16(v0, l0), Self::Enum16(v1, r0)) => l0 == r0 && v0 == v1,
122 (Self::Array(l0), Self::Array(r0)) => l0 == r0,
123 (Self::Tuple(l0), Self::Tuple(r0)) => l0 == r0,
124 (Self::Map(l0, l1), Self::Map(r0, r1)) => l0 == r0 && l1 == r1,
125 (Self::Ipv4(l0), Self::Ipv4(r0)) => l0 == r0,
126 (Self::Ipv6(l0), Self::Ipv6(r0)) => l0 == r0,
127 (Self::Point(l0), Self::Point(r0)) => l0 == r0,
128 (Self::Ring(l0), Self::Ring(r0)) => l0 == r0,
129 (Self::Polygon(l0), Self::Polygon(r0)) => l0 == r0,
130 (Self::MultiPolygon(l0), Self::MultiPolygon(r0)) => l0 == r0,
131 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
132 }
133 }
134}
135
136impl Hash for Value {
137 fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
138 Hash::hash(&core::mem::discriminant(self), state);
139 #[expect(clippy::match_same_arms)]
140 match self {
141 Value::Int8(x) => ::core::hash::Hash::hash(x, state),
142 Value::Int16(x) => ::core::hash::Hash::hash(x, state),
143 Value::Int32(x) => ::core::hash::Hash::hash(x, state),
144 Value::Int64(x) => ::core::hash::Hash::hash(x, state),
145 Value::Int128(x) => ::core::hash::Hash::hash(x, state),
146 Value::Int256(x) => ::core::hash::Hash::hash(x, state),
147 Value::UInt8(x) => ::core::hash::Hash::hash(x, state),
148 Value::UInt16(x) => ::core::hash::Hash::hash(x, state),
149 Value::UInt32(x) => ::core::hash::Hash::hash(x, state),
150 Value::UInt64(x) => ::core::hash::Hash::hash(x, state),
151 Value::UInt128(x) => ::core::hash::Hash::hash(x, state),
152 Value::UInt256(x) => ::core::hash::Hash::hash(x, state),
153 Value::Float32(x) => ::core::hash::Hash::hash(&x.to_bits(), state),
154 Value::Float64(x) => ::core::hash::Hash::hash(&x.to_bits(), state),
155 Value::Decimal32(x, __self_1) => {
156 ::core::hash::Hash::hash(x, state);
157 ::core::hash::Hash::hash(__self_1, state);
158 }
159 Value::Decimal64(x, __self_1) => {
160 ::core::hash::Hash::hash(x, state);
161 ::core::hash::Hash::hash(__self_1, state);
162 }
163 Value::Decimal128(x, __self_1) => {
164 ::core::hash::Hash::hash(x, state);
165 ::core::hash::Hash::hash(__self_1, state);
166 }
167 Value::Decimal256(x, __self_1) => {
168 ::core::hash::Hash::hash(x, state);
169 ::core::hash::Hash::hash(__self_1, state);
170 }
171 Value::String(x) => ::core::hash::Hash::hash(x, state),
172 Value::Object(x) => ::core::hash::Hash::hash(x, state),
173 Value::Uuid(x) => ::core::hash::Hash::hash(x, state),
174 Value::Date(x) => ::core::hash::Hash::hash(x, state),
175 Value::Date32(x) => ::core::hash::Hash::hash(x, state),
176 Value::DateTime(x) => ::core::hash::Hash::hash(x, state),
177 Value::DateTime64(x) => {
178 ::core::hash::Hash::hash(x, state);
179 }
180 Value::Enum8(_, x) => ::core::hash::Hash::hash(x, state),
181 Value::Enum16(_, x) => ::core::hash::Hash::hash(x, state),
182 Value::Array(x) => ::core::hash::Hash::hash(x, state),
183 Value::Tuple(x) => ::core::hash::Hash::hash(x, state),
184 Value::Map(x, __self_1) => {
185 ::core::hash::Hash::hash(x, state);
186 ::core::hash::Hash::hash(__self_1, state);
187 }
188 Value::Ipv4(x) => ::core::hash::Hash::hash(x, state),
189 Value::Ipv6(x) => ::core::hash::Hash::hash(x, state),
190
191 Value::Point(x) => ::core::hash::Hash::hash(x, state),
192 Value::Ring(x) => ::core::hash::Hash::hash(x, state),
193 Value::Polygon(x) => ::core::hash::Hash::hash(x, state),
194 Value::MultiPolygon(x) => ::core::hash::Hash::hash(x, state),
195
196 Value::Null => {}
197 }
198 }
199}
200
201impl Eq for Value {}
202
203impl Value {
204 pub fn string(value: impl Into<String>) -> Self { Value::String(value.into().into_bytes()) }
205
206 pub(crate) fn index_value(&self) -> Result<usize> {
209 Ok(match self {
210 Value::UInt8(x) => *x as usize,
211 Value::UInt16(x) => *x as usize,
212 Value::UInt32(x) => *x as usize,
213 #[expect(clippy::cast_possible_truncation)]
214 Value::UInt64(x) => *x as usize,
215 _ => {
216 return Err(crate::errors::Error::Protocol(format!(
217 "Expected integer, got {self}"
218 )));
219 }
220 })
221 }
222
223 pub fn unwrap_array_ref(&self) -> Result<&[Value]> {
226 match self {
227 Value::Array(a) => Ok(&a[..]),
228 _ => Err(crate::errors::Error::Protocol(format!("Expected array, got {self}"))),
229 }
230 }
231
232 pub fn unwrap_array(self) -> Result<Vec<Value>> {
235 match self {
236 Value::Array(a) => Ok(a),
237 _ => Err(crate::errors::Error::Protocol(format!("Expected array, got {self}"))),
238 }
239 }
240
241 pub fn unwrap_tuple(self) -> Result<Vec<Value>> {
244 match self {
245 Value::Tuple(a) => Ok(a),
246 _ => Err(crate::errors::Error::Protocol(format!("Expected tuple, got {self}"))),
247 }
248 }
249
250 pub fn unarray(self) -> Option<Vec<Value>> {
251 match self {
252 Value::Array(a) => Some(a),
253 _ => None,
254 }
255 }
256
257 pub(crate) fn justify_null_ref<'a>(&'a self, type_: &Type) -> Cow<'a, Value> {
258 if self == &Value::Null { Cow::Owned(type_.default_value()) } else { Cow::Borrowed(self) }
259 }
260
261 pub fn to_value<T: FromSql>(self, type_: &Type) -> Result<T> { T::from_sql(type_, self) }
266
267 pub fn from_value<T: ToSql>(value: T) -> Result<Self> { value.to_sql(None) }
272
273 pub fn guess_type(&self) -> Type {
275 match self {
276 Value::Int8(_) => Type::Int8,
277 Value::Int16(_) => Type::Int16,
278 Value::Int32(_) => Type::Int32,
279 Value::Int64(_) => Type::Int64,
280 Value::Int128(_) => Type::Int128,
281 Value::Int256(_) => Type::Int256,
282 Value::UInt8(_) => Type::UInt8,
283 Value::UInt16(_) => Type::UInt16,
284 Value::UInt32(_) => Type::UInt32,
285 Value::UInt64(_) => Type::UInt64,
286 Value::UInt128(_) => Type::UInt128,
287 Value::UInt256(_) => Type::UInt256,
288 Value::Float32(_) => Type::Float32,
289 Value::Float64(_) => Type::Float64,
290 Value::Decimal32(p, _) => Type::Decimal32(*p),
291 Value::Decimal64(p, _) => Type::Decimal64(*p),
292 Value::Decimal128(p, _) => Type::Decimal128(*p),
293 Value::Decimal256(p, _) => Type::Decimal256(*p),
294 Value::String(_) => Type::String,
295 Value::Uuid(_) => Type::Uuid,
296 Value::Date(_) => Type::Date,
297 Value::Date32(_) => Type::Date32,
298 Value::DateTime(time) => Type::DateTime(time.0),
299 Value::DateTime64(x) => Type::DateTime64(x.2, x.0),
300 Value::Enum8(_, i) => Type::Enum8(vec![(String::new(), *i)]),
301 Value::Enum16(_, i) => Type::Enum16(vec![(String::new(), *i)]),
302 Value::Array(x) => {
303 Type::Array(Box::new(x.first().map_or(Type::String, Value::guess_type)))
304 }
305 Value::Tuple(values) => Type::Tuple(values.iter().map(Value::guess_type).collect()),
306 Value::Null => Type::Nullable(Box::new(Type::String)),
307 Value::Map(k, v) => Type::Map(
308 Box::new(k.first().map_or(Type::String, Value::guess_type)),
309 Box::new(v.first().map_or(Type::String, Value::guess_type)),
310 ),
311 Value::Ipv4(_) => Type::Ipv4,
312 Value::Ipv6(_) => Type::Ipv6,
313
314 Value::Point(_) => Type::Point,
315 Value::Ring(_) => Type::Ring,
316 Value::Polygon(_) => Type::Polygon,
317 Value::MultiPolygon(_) => Type::MultiPolygon,
318 Value::Object(_) => Type::Object,
319 }
320 }
321}
322
323fn escape_string(f: &mut fmt::Formatter<'_>, from: impl AsRef<[u8]>) -> fmt::Result {
324 let from = from.as_ref();
325 for byte in from.iter().copied() {
326 if byte < 128 {
327 match byte {
328 b'\\' => write!(f, "\\\\")?,
329 b'\'' => write!(f, "\\'")?,
330 0x08 => write!(f, "\\b")?,
331 0x0C => write!(f, "\\f")?,
332 b'\r' => write!(f, "\\r")?,
333 b'\n' => write!(f, "\\n")?,
334 b'\t' => write!(f, "\\t")?,
335 b'\0' => write!(f, "\\0")?,
336 0x07 => write!(f, "\\a")?,
337 0x0B => write!(f, "\\v")?,
338 _ => write!(f, "{}", Into::<char>::into(byte))?,
339 }
340 } else {
341 write!(f, "\\x{byte:02X}")?;
342 }
343 }
344 Ok(())
345}
346
347impl fmt::Debug for Value {
348 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349 <Self as fmt::Display>::fmt(self, f)
350 }
351}
352
353impl fmt::Display for Value {
354 #[expect(clippy::too_many_lines)]
355 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356 #[expect(clippy::match_same_arms)]
357 match self {
358 Value::Int8(x) => write!(f, "{x}"),
359 Value::Int16(x) => write!(f, "{x}"),
360 Value::Int32(x) => write!(f, "{x}"),
361 Value::Int64(x) => write!(f, "{x}"),
362 Value::Int128(x) => write!(f, "{x}::Int128"),
363 Value::Int256(x) => write!(f, "{x}::Int256"),
364 Value::UInt8(x) => write!(f, "{x}"),
365 Value::UInt16(x) => write!(f, "{x}"),
366 Value::UInt32(x) => write!(f, "{x}"),
367 Value::UInt64(x) => write!(f, "{x}"),
368 Value::UInt128(x) => write!(f, "{x}::UInt128"),
369 Value::UInt256(x) => write!(f, "{x}::UInt256"),
370 Value::Float32(x) => write!(f, "{x}"),
371 Value::Float64(x) => write!(f, "{x}"),
372 Value::Decimal32(scale, value) => {
373 let raw_value = value.to_string();
374 if raw_value.len() < *scale {
375 write!(f, "{raw_value}")
376 } else {
377 let pre = &raw_value[..raw_value.len() - scale];
378 let fraction = &raw_value[raw_value.len() - scale..];
379 write!(f, "{pre}.{fraction}")
380 }
381 }
382 Value::Decimal64(scale, value) => {
383 let raw_value = value.to_string();
384 if raw_value.len() < *scale {
385 write!(f, "{raw_value}")
386 } else {
387 let pre = &raw_value[..raw_value.len() - scale];
388 let fraction = &raw_value[raw_value.len() - scale..];
389 write!(f, "{pre}.{fraction}")
390 }
391 }
392 Value::Decimal128(scale, value) => {
393 let raw_value = value.to_string();
394 if raw_value.len() < *scale {
395 write!(f, "{raw_value}")
396 } else {
397 let pre = &raw_value[..raw_value.len() - scale];
398 let fraction = &raw_value[raw_value.len() - scale..];
399 write!(f, "{pre}.{fraction}")
400 }
401 }
402 Value::Decimal256(scale, value) => {
403 let raw_value = value.to_string();
404 if raw_value.len() < *scale {
405 write!(f, "{raw_value}")
406 } else {
407 let pre = &raw_value[..raw_value.len() - scale];
408 let fraction = &raw_value[raw_value.len() - scale..];
409 write!(f, "{pre}.{fraction}")
410 }
411 }
412 Value::String(string) => {
413 write!(f, "'")?;
414 escape_string(f, string)?;
415 write!(f, "'")
416 }
417 Value::Uuid(uuid) => {
418 write!(f, "'{uuid}'")
419 }
420 Value::Date(date) => {
421 let chrono_date: NaiveDate = (*date).into();
422 write!(f, "'{}'", chrono_date.format("makeDate(%Y-%m-%d)"))
423 }
424 Value::Date32(date) => {
425 let chrono_date: NaiveDate = (*date).into();
426 write!(f, "'{}'", chrono_date.format("makeDate(%Y-%m-%d)"))
427 }
428 Value::DateTime(datetime) => {
429 let chrono_date: chrono::DateTime<Tz> =
430 (*datetime).try_into().map_err(|_| fmt::Error)?;
431 let string = chrono_date.to_rfc3339_opts(SecondsFormat::AutoSi, true);
432 write!(f, "parseDateTimeBestEffort('")?;
433 escape_string(f, &string)?;
434 write!(f, "')")
435 }
436 Value::DateTime64(datetime) => {
437 let chrono_date: chrono::DateTime<Tz> =
438 FromSql::from_sql(&Type::DateTime64(datetime.2, datetime.0), self.clone())
439 .map_err(|_| fmt::Error)?;
440 let string = chrono_date.to_rfc3339_opts(SecondsFormat::AutoSi, true);
441 write!(f, "parseDateTime64BestEffort('")?;
442 escape_string(f, &string)?;
443 write!(f, "', {})", datetime.2)
444 }
445 Value::Enum8(x, _) => write!(f, "{x}"),
446 Value::Enum16(x, _) => write!(f, "{x}"),
447 Value::Array(array) => {
448 write!(f, "[")?;
449 if let Some(item) = array.first() {
450 write!(f, "{item}")?;
451 }
452 for item in array.iter().skip(1) {
453 write!(f, ",{item}")?;
454 }
455 write!(f, "]")
456 }
457 Value::Tuple(tuple) => {
458 write!(f, "(")?;
459 if let Some(item) = tuple.first() {
460 write!(f, "{item}")?;
461 }
462 for item in tuple.iter().skip(1) {
463 write!(f, ",{item}")?;
464 }
465 write!(f, ")")
466 }
467 Value::Null => write!(f, "NULL"),
468 Value::Map(keys, values) => {
469 assert_eq!(keys.len(), values.len());
470 write!(f, "{{")?;
471 let mut iter = keys.iter().zip(values.iter());
472 if let Some((key, value)) = iter.next() {
473 write!(f, "{key}:{value}")?;
474 }
475 for (key, value) in iter {
476 write!(f, ",{key}:{value}")?;
477 }
478 write!(f, "}}")
479 }
480 Value::Ipv4(ipv4) => write!(f, "'{ipv4}'"),
481 Value::Ipv6(ipv6) => write!(f, "'{ipv6}'"),
482 Value::Point(x) => write!(f, "{x:?}"),
483 Value::Ring(x) => write!(f, "{x:?}"),
484 Value::Polygon(x) => write!(f, "{x:?}"),
485 Value::MultiPolygon(x) => write!(f, "{x:?}"),
486 Value::Object(x) => {
487 write!(f, "'")?;
488 let obj_str = std::str::from_utf8(x).ok();
489 #[cfg(not(feature = "serde"))]
490 {
491 if let Some(x) = obj_str {
492 escape_string(f, x)?;
493 }
494 }
495 #[cfg(feature = "serde")]
496 {
497 if let Some(x) = serde_json::from_slice(x).unwrap_or(obj_str) {
498 escape_string(f, x)?;
499 }
500 }
501 write!(f, "'")
502 }
503 }
504 }
505}