sea_query/
value.rs

1//! Container for all SQL value types.
2
3use std::borrow::Cow;
4use std::sync::Arc;
5
6#[cfg(feature = "with-chrono")]
7use chrono::{DateTime, FixedOffset, Local, NaiveDate, NaiveDateTime, NaiveTime, Utc};
8#[cfg(feature = "with-json")]
9use serde_json::Value as Json;
10
11#[cfg(feature = "with-time")]
12use time::{OffsetDateTime, PrimitiveDateTime};
13
14#[cfg(feature = "with-jiff")]
15use jiff::{Timestamp, Zoned};
16
17#[cfg(feature = "with-rust_decimal")]
18use rust_decimal::Decimal;
19
20#[cfg(feature = "with-bigdecimal")]
21use bigdecimal::BigDecimal;
22
23#[cfg(feature = "with-uuid")]
24use uuid::Uuid;
25
26#[cfg(feature = "with-ipnetwork")]
27use ipnetwork::IpNetwork;
28
29#[cfg(feature = "with-ipnetwork")]
30use std::net::IpAddr;
31
32#[cfg(feature = "with-mac_address")]
33use mac_address::MacAddress;
34
35#[cfg(feature = "postgres-array")]
36#[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
37mod array;
38
39use crate::{ColumnType, CommonSqlQueryBuilder, DynIden, QueryBuilder, StringLen};
40#[cfg(feature = "postgres-array")]
41pub use array::{Array, ArrayElement, ArrayValue};
42
43#[cfg(test)]
44mod tests;
45
46pub mod prelude;
47#[allow(unused_imports)]
48use prelude::*;
49
50#[cfg(feature = "hashable-value")]
51mod hashable_value;
52
53mod value_class;
54pub use value_class::*;
55
56mod value_tuple;
57pub use value_tuple::*;
58
59#[cfg(feature = "with-json")]
60#[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
61mod with_json;
62
63#[cfg(feature = "with-json")]
64#[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
65pub use with_json::sea_value_to_json_value;
66
67#[cfg(feature = "with-chrono")]
68#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
69mod with_chrono;
70
71#[cfg(feature = "with-time")]
72#[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
73pub mod time_format;
74
75#[cfg(feature = "with-time")]
76#[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
77mod with_time;
78
79#[cfg(feature = "with-jiff")]
80#[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
81pub(crate) mod with_jiff;
82
83#[cfg(feature = "with-rust_decimal")]
84#[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
85mod with_rust_decimal;
86
87#[cfg(feature = "with-bigdecimal")]
88#[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
89mod with_bigdecimal;
90
91#[cfg(feature = "with-uuid")]
92#[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
93mod with_uuid;
94
95#[cfg(feature = "with-ipnetwork")]
96#[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
97mod with_ipnetwork;
98
99#[cfg(feature = "with-mac_address")]
100#[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
101mod with_mac_address;
102
103#[cfg(feature = "postgres-array")]
104#[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
105pub mod with_array;
106
107#[cfg(feature = "postgres-vector")]
108#[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))]
109mod with_pgvector;
110
111#[cfg(all(test, feature = "serde", feature = "with-json"))]
112mod serde_tests;
113
114/// [`Value`] types variant for Postgres array
115#[derive(Clone, Debug, Eq, PartialEq, Hash)]
116#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
117pub enum ArrayType {
118    Bool,
119    TinyInt,
120    SmallInt,
121    Int,
122    BigInt,
123    TinyUnsigned,
124    SmallUnsigned,
125    Unsigned,
126    BigUnsigned,
127    Float,
128    Double,
129    String,
130    Char,
131    Bytes,
132    /// The type name of the enum
133    Enum(Arc<str>),
134
135    #[cfg(feature = "with-json")]
136    #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
137    Json,
138
139    #[cfg(feature = "with-chrono")]
140    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
141    ChronoDate,
142
143    #[cfg(feature = "with-chrono")]
144    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
145    ChronoTime,
146
147    #[cfg(feature = "with-chrono")]
148    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
149    ChronoDateTime,
150
151    #[cfg(feature = "with-chrono")]
152    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
153    ChronoDateTimeUtc,
154
155    #[cfg(feature = "with-chrono")]
156    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
157    ChronoDateTimeLocal,
158
159    #[cfg(feature = "with-chrono")]
160    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
161    ChronoDateTimeWithTimeZone,
162
163    #[cfg(feature = "with-time")]
164    #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
165    TimeDate,
166
167    #[cfg(feature = "with-time")]
168    #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
169    TimeTime,
170
171    #[cfg(feature = "with-time")]
172    #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
173    TimeDateTime,
174
175    #[cfg(feature = "with-time")]
176    #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
177    TimeDateTimeWithTimeZone,
178
179    #[cfg(feature = "with-jiff")]
180    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
181    JiffDate,
182
183    #[cfg(feature = "with-jiff")]
184    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
185    JiffTime,
186
187    #[cfg(feature = "with-jiff")]
188    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
189    JiffDateTime,
190
191    #[cfg(feature = "with-jiff")]
192    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
193    JiffTimestamp,
194
195    #[cfg(feature = "with-jiff")]
196    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
197    JiffZoned,
198
199    #[cfg(feature = "with-uuid")]
200    #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
201    Uuid,
202
203    #[cfg(feature = "with-rust_decimal")]
204    #[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
205    Decimal,
206
207    #[cfg(feature = "with-bigdecimal")]
208    #[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
209    BigDecimal,
210
211    #[cfg(feature = "with-ipnetwork")]
212    #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
213    IpNetwork,
214
215    #[cfg(feature = "with-mac_address")]
216    #[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
217    MacAddress,
218}
219
220/// Value variants
221///
222/// We want the inner Value to be exactly 1 pointer sized, so anything larger should be boxed.
223///
224/// If the `hashable-value` feature is enabled, NaN == NaN, which contradicts Rust's built-in
225/// implementation of NaN != NaN.
226#[derive(Clone, Debug)]
227#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
228#[cfg_attr(not(feature = "hashable-value"), derive(PartialEq))]
229pub enum Value {
230    Bool(Option<bool>),
231    TinyInt(Option<i8>),
232    SmallInt(Option<i16>),
233    Int(Option<i32>),
234    BigInt(Option<i64>),
235    TinyUnsigned(Option<u8>),
236    SmallUnsigned(Option<u16>),
237    Unsigned(Option<u32>),
238    BigUnsigned(Option<u64>),
239    Float(Option<f32>),
240    Double(Option<f64>),
241    String(Option<String>),
242    Char(Option<char>),
243    /// In most cases, the values of enums are staticly known,
244    /// so we use Arc to save space
245    Enum(Option<Arc<Enum>>),
246
247    Bytes(Option<Vec<u8>>),
248
249    #[cfg(feature = "with-json")]
250    #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
251    Json(Option<Json>),
252
253    #[cfg(feature = "with-chrono")]
254    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
255    ChronoDate(Option<NaiveDate>),
256
257    #[cfg(feature = "with-chrono")]
258    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
259    ChronoTime(Option<NaiveTime>),
260
261    #[cfg(feature = "with-chrono")]
262    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
263    ChronoDateTime(Option<NaiveDateTime>),
264
265    #[cfg(feature = "with-chrono")]
266    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
267    ChronoDateTimeUtc(Option<DateTime<Utc>>),
268
269    #[cfg(feature = "with-chrono")]
270    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
271    ChronoDateTimeLocal(Option<DateTime<Local>>),
272
273    #[cfg(feature = "with-chrono")]
274    #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
275    ChronoDateTimeWithTimeZone(Option<DateTime<FixedOffset>>),
276
277    #[cfg(feature = "with-time")]
278    #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
279    TimeDate(Option<time::Date>),
280
281    #[cfg(feature = "with-time")]
282    #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
283    TimeTime(Option<time::Time>),
284
285    #[cfg(feature = "with-time")]
286    #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
287    TimeDateTime(Option<PrimitiveDateTime>),
288
289    #[cfg(feature = "with-time")]
290    #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
291    TimeDateTimeWithTimeZone(Option<OffsetDateTime>),
292
293    #[cfg(feature = "with-jiff")]
294    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
295    JiffDate(Option<jiff::civil::Date>),
296
297    #[cfg(feature = "with-jiff")]
298    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
299    JiffTime(Option<jiff::civil::Time>),
300
301    #[cfg(feature = "with-jiff")]
302    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
303    JiffDateTime(Option<jiff::civil::DateTime>),
304
305    #[cfg(feature = "with-jiff")]
306    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
307    JiffTimestamp(Option<Timestamp>),
308
309    #[cfg(feature = "with-jiff")]
310    #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
311    JiffZoned(Option<Zoned>),
312
313    #[cfg(feature = "with-uuid")]
314    #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
315    Uuid(Option<Uuid>),
316
317    #[cfg(feature = "with-rust_decimal")]
318    #[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
319    Decimal(Option<Decimal>),
320
321    #[cfg(feature = "with-bigdecimal")]
322    #[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
323    BigDecimal(Option<BigDecimal>),
324
325    #[cfg(feature = "postgres-array")]
326    #[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
327    Array(Array),
328
329    #[cfg(feature = "postgres-vector")]
330    #[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))]
331    Vector(Option<pgvector::Vector>),
332
333    #[cfg(feature = "with-ipnetwork")]
334    #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
335    IpNetwork(Option<IpNetwork>),
336
337    #[cfg(feature = "with-mac_address")]
338    #[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
339    MacAddress(Option<MacAddress>),
340
341    #[cfg(feature = "postgres-range")]
342    #[cfg_attr(docsrs, doc(cfg(feature = "postgres-range")))]
343    Range(Option<Box<RangeType>>),
344}
345
346#[derive(Debug, Clone, PartialEq, Eq, Hash)]
347#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
348pub struct Enum {
349    /// The type_name is only used for the Postgres
350    ///
351    /// In most cases, the enum type name is staticly known,
352    /// we wrap it in an [`Arc<str>`] to save space.
353    pub(crate) type_name: Option<Arc<str>>,
354    pub(crate) value: DynIden,
355}
356
357impl Enum {
358    /// Create a new [`Enum`]
359    pub fn new(type_name: impl Into<Option<Arc<str>>>, value: DynIden) -> Self {
360        Self {
361            type_name: type_name.into(),
362            value,
363        }
364    }
365
366    /// Get the string value of the enum
367    pub fn as_str(&self) -> &str {
368        self.value.as_ref()
369    }
370}
371
372/// This test is to check if the size of [`Value`] exceeds the limit.
373///
374/// If the size exceeds the limit, you should box the variant.
375/// Previously, the size was 24. We bumped it to 32 such that `String`
376/// can be unboxed.
377///
378/// When the `with-json` feature is enabled, the size of `Value` may
379/// exceed 32 bytes to 72 bytes if serde_json feature `preserve_order`
380/// is enabled as different Map implementation can be used.
381pub const VALUE_SIZE: usize = check_value_size();
382const MAX_VALUE_SIZE: usize = 32;
383
384#[allow(unused)]
385const EXPECTED_VALUE_SIZE: usize = {
386    #[allow(unused_mut)]
387    let mut max = MAX_VALUE_SIZE;
388
389    macro_rules! max_mut {
390        ($expr:expr) => {
391            let tmp = $expr;
392            if max < tmp {
393                max = tmp;
394            }
395        };
396    }
397
398    #[cfg(all(feature = "with-json", feature = "postgres-array"))]
399    // size of vec + discriminant (8)
400    max_mut!(40);
401
402    // If some crate enabled indexmap feature, the size of Json will be 72 or larger.
403    #[cfg(feature = "with-json")]
404    max_mut!(size_of::<Option<Json>>());
405
406    // If bigdecimal is enabled and its size is larger, we make the limit to be bigdecimal's size
407    #[cfg(feature = "with-bigdecimal")]
408    max_mut!(size_of::<Option<BigDecimal>>());
409
410    // Jiff has extra size in debug mode. Skip size check in that case.
411    #[cfg(feature = "with-jiff")]
412    max_mut!(size_of::<Option<jiff::Zoned>>());
413
414    max
415};
416
417const fn check_value_size() -> usize {
418    if std::mem::size_of::<Value>() > EXPECTED_VALUE_SIZE {
419        panic!(
420            "the size of Value shouldn't be greater than the expected MAX_VALUE_SIZE (32 bytes by default)"
421        )
422    }
423    std::mem::size_of::<Value>()
424}
425
426impl Value {
427    pub fn unwrap<T>(self) -> T
428    where
429        T: ValueType,
430    {
431        T::unwrap(self)
432    }
433
434    pub fn expect<T>(self, msg: &str) -> T
435    where
436        T: ValueType,
437    {
438        T::expect(self, msg)
439    }
440
441    /// Get the null variant of self
442    ///
443    /// ```
444    /// use sea_query::Value;
445    ///
446    /// let v = Value::Int(Some(2));
447    /// let n = v.as_null();
448    ///
449    /// assert_eq!(n, Value::Int(None));
450    ///
451    /// // one liner:
452    /// assert_eq!(Into::<Value>::into(2.2).as_null(), Value::Double(None));
453    /// ```
454    pub fn as_null(&self) -> Self {
455        match self {
456            Self::Bool(_) => Self::Bool(None),
457            Self::TinyInt(_) => Self::TinyInt(None),
458            Self::SmallInt(_) => Self::SmallInt(None),
459            Self::Int(_) => Self::Int(None),
460            Self::BigInt(_) => Self::BigInt(None),
461            Self::TinyUnsigned(_) => Self::TinyUnsigned(None),
462            Self::SmallUnsigned(_) => Self::SmallUnsigned(None),
463            Self::Unsigned(_) => Self::Unsigned(None),
464            Self::BigUnsigned(_) => Self::BigUnsigned(None),
465            Self::Float(_) => Self::Float(None),
466            Self::Double(_) => Self::Double(None),
467            Self::String(_) => Self::String(None),
468            Self::Char(_) => Self::Char(None),
469            Self::Bytes(_) => Self::Bytes(None),
470            Self::Enum(_) => Self::Enum(None),
471
472            #[cfg(feature = "with-json")]
473            #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
474            Self::Json(_) => Self::Json(None),
475
476            #[cfg(feature = "with-chrono")]
477            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
478            Self::ChronoDate(_) => Self::ChronoDate(None),
479
480            #[cfg(feature = "with-chrono")]
481            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
482            Self::ChronoTime(_) => Self::ChronoTime(None),
483
484            #[cfg(feature = "with-chrono")]
485            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
486            Self::ChronoDateTime(_) => Self::ChronoDateTime(None),
487
488            #[cfg(feature = "with-chrono")]
489            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
490            Self::ChronoDateTimeUtc(_) => Self::ChronoDateTimeUtc(None),
491
492            #[cfg(feature = "with-chrono")]
493            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
494            Self::ChronoDateTimeLocal(_) => Self::ChronoDateTimeLocal(None),
495
496            #[cfg(feature = "with-chrono")]
497            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
498            Self::ChronoDateTimeWithTimeZone(_) => Self::ChronoDateTimeWithTimeZone(None),
499
500            #[cfg(feature = "with-time")]
501            #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
502            Self::TimeDate(_) => Self::TimeDate(None),
503
504            #[cfg(feature = "with-time")]
505            #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
506            Self::TimeTime(_) => Self::TimeTime(None),
507
508            #[cfg(feature = "with-time")]
509            #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
510            Self::TimeDateTime(_) => Self::TimeDateTime(None),
511
512            #[cfg(feature = "with-time")]
513            #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
514            Self::TimeDateTimeWithTimeZone(_) => Self::TimeDateTimeWithTimeZone(None),
515
516            #[cfg(feature = "with-jiff")]
517            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
518            Self::JiffDate(_) => Self::JiffDate(None),
519
520            #[cfg(feature = "with-jiff")]
521            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
522            Self::JiffTime(_) => Self::JiffTime(None),
523
524            #[cfg(feature = "with-jiff")]
525            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
526            Self::JiffDateTime(_) => Self::JiffDateTime(None),
527
528            #[cfg(feature = "with-jiff")]
529            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
530            Self::JiffTimestamp(_) => Self::JiffTimestamp(None),
531
532            #[cfg(feature = "with-jiff")]
533            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
534            Self::JiffZoned(_) => Self::JiffZoned(None),
535
536            #[cfg(feature = "with-uuid")]
537            #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
538            Self::Uuid(_) => Self::Uuid(None),
539
540            #[cfg(feature = "with-rust_decimal")]
541            #[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
542            Self::Decimal(_) => Self::Decimal(None),
543
544            #[cfg(feature = "with-bigdecimal")]
545            #[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
546            Self::BigDecimal(_) => Self::BigDecimal(None),
547
548            #[cfg(feature = "postgres-array")]
549            #[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
550            Self::Array(arr) => Self::Array(Array::Null(arr.array_type())),
551
552            #[cfg(feature = "postgres-vector")]
553            #[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))]
554            Self::Vector(_) => Self::Vector(None),
555
556            #[cfg(feature = "with-ipnetwork")]
557            #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
558            Self::IpNetwork(_) => Self::IpNetwork(None),
559
560            #[cfg(feature = "with-mac_address")]
561            #[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
562            Self::MacAddress(_) => Self::MacAddress(None),
563
564            #[cfg(feature = "postgres-range")]
565            #[cfg_attr(docsrs, doc(cfg(feature = "postgres-range")))]
566            Self::Range(_) => Self::Range(None),
567        }
568    }
569
570    /// Get a default value of self's type
571    ///
572    /// ```
573    /// use sea_query::Value;
574    ///
575    /// let v = Value::Int(None);
576    /// let n = v.dummy_value();
577    /// assert_eq!(n, Value::Int(Some(0)));
578    /// ```
579    pub fn dummy_value(&self) -> Self {
580        match self {
581            Self::Bool(_) => Self::Bool(Some(Default::default())),
582            Self::TinyInt(_) => Self::TinyInt(Some(Default::default())),
583            Self::SmallInt(_) => Self::SmallInt(Some(Default::default())),
584            Self::Int(_) => Self::Int(Some(Default::default())),
585            Self::BigInt(_) => Self::BigInt(Some(Default::default())),
586            Self::TinyUnsigned(_) => Self::TinyUnsigned(Some(Default::default())),
587            Self::SmallUnsigned(_) => Self::SmallUnsigned(Some(Default::default())),
588            Self::Unsigned(_) => Self::Unsigned(Some(Default::default())),
589            Self::BigUnsigned(_) => Self::BigUnsigned(Some(Default::default())),
590            Self::Float(_) => Self::Float(Some(Default::default())),
591            Self::Double(_) => Self::Double(Some(Default::default())),
592            Self::String(_) => Self::String(Some(Default::default())),
593            Self::Char(_) => Self::Char(Some(Default::default())),
594            Self::Enum(value) => Self::Enum(value.clone()),
595            Self::Bytes(_) => Self::Bytes(Some(Default::default())),
596
597            #[cfg(feature = "with-json")]
598            #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
599            Self::Json(_) => Self::Json(Some(Default::default())),
600
601            #[cfg(feature = "with-chrono")]
602            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
603            Self::ChronoDate(_) => Self::ChronoDate(Some(Default::default())),
604
605            #[cfg(feature = "with-chrono")]
606            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
607            Self::ChronoTime(_) => Self::ChronoTime(Some(Default::default())),
608
609            #[cfg(feature = "with-chrono")]
610            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
611            Self::ChronoDateTime(_) => Self::ChronoDateTime(Some(Default::default())),
612
613            #[cfg(feature = "with-chrono")]
614            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
615            Self::ChronoDateTimeUtc(_) => Self::ChronoDateTimeUtc(Some(Default::default())),
616
617            #[cfg(feature = "with-chrono")]
618            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
619            Self::ChronoDateTimeLocal(_) => Self::ChronoDateTimeLocal(Some(Default::default())),
620
621            #[cfg(feature = "with-chrono")]
622            #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
623            Self::ChronoDateTimeWithTimeZone(_) => {
624                Self::ChronoDateTimeWithTimeZone(Some(Default::default()))
625            }
626
627            #[cfg(feature = "with-time")]
628            #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
629            Self::TimeDate(_) => Self::TimeDate(Some(time::Date::MIN)),
630
631            #[cfg(feature = "with-time")]
632            #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
633            Self::TimeTime(_) => Self::TimeTime(Some(time::Time::MIDNIGHT)),
634
635            #[cfg(feature = "with-time")]
636            #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
637            Self::TimeDateTime(_) => Self::TimeDateTime(Some(PrimitiveDateTime::MIN)),
638
639            #[cfg(feature = "with-time")]
640            #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
641            Self::TimeDateTimeWithTimeZone(_) => {
642                Self::TimeDateTimeWithTimeZone(Some(OffsetDateTime::UNIX_EPOCH))
643            }
644
645            #[cfg(feature = "with-jiff")]
646            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
647            Self::JiffDate(_) => Self::JiffDate(Some(jiff::civil::date(1970, 1, 1))),
648
649            #[cfg(feature = "with-jiff")]
650            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
651            Self::JiffTime(_) => Self::JiffTime(Some(jiff::civil::time(0, 0, 0, 0))),
652
653            #[cfg(feature = "with-jiff")]
654            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
655            Self::JiffDateTime(_) => {
656                Self::JiffDateTime(Some(jiff::civil::date(1970, 1, 1).at(0, 0, 0, 0)))
657            }
658
659            #[cfg(feature = "with-jiff")]
660            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
661            Self::JiffTimestamp(_) => Self::JiffTimestamp(Some(Timestamp::UNIX_EPOCH)),
662
663            #[cfg(feature = "with-jiff")]
664            #[cfg_attr(docsrs, doc(cfg(feature = "with-jiff")))]
665            Self::JiffZoned(_) => Self::JiffZoned(Some(
666                Timestamp::UNIX_EPOCH.to_zoned(jiff::tz::TimeZone::UTC),
667            )),
668
669            #[cfg(feature = "with-uuid")]
670            #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
671            Self::Uuid(_) => Self::Uuid(Some(Default::default())),
672
673            #[cfg(feature = "with-rust_decimal")]
674            #[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
675            Self::Decimal(_) => Self::Decimal(Some(Default::default())),
676
677            #[cfg(feature = "with-bigdecimal")]
678            #[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
679            Self::BigDecimal(_) => Self::BigDecimal(Some(Default::default())),
680
681            #[cfg(feature = "postgres-array")]
682            #[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
683            Self::Array(arr) => Self::Array(arr.dummy_value()),
684
685            #[cfg(feature = "postgres-vector")]
686            #[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))]
687            Self::Vector(_) => Self::Vector(Some(vec![].into())),
688
689            #[cfg(feature = "with-ipnetwork")]
690            #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
691            Self::IpNetwork(_) => Self::IpNetwork(Some("0.0.0.0".parse().unwrap())),
692
693            #[cfg(feature = "with-mac_address")]
694            #[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
695            Self::MacAddress(_) => Self::MacAddress(Some(Default::default())),
696
697            #[cfg(feature = "postgres-range")]
698            #[cfg_attr(docsrs, doc(cfg(feature = "postgres-range")))]
699            Self::Range(_) => Self::Range(Some(Default::default())),
700        }
701    }
702}
703
704impl From<&[u8]> for Value {
705    fn from(x: &[u8]) -> Value {
706        Value::Bytes(Some(x.into()))
707    }
708}
709
710impl From<&str> for Value {
711    fn from(x: &str) -> Value {
712        Value::String(Some(x.to_owned()))
713    }
714}
715
716impl From<&String> for Value {
717    fn from(x: &String) -> Value {
718        Value::String(Some(x.clone()))
719    }
720}
721
722impl<T> From<Option<T>> for Value
723where
724    T: Into<Value> + Nullable,
725{
726    fn from(x: Option<T>) -> Value {
727        match x {
728            Some(v) => v.into(),
729            None => T::null(),
730        }
731    }
732}
733
734impl From<Cow<'_, str>> for Value {
735    fn from(x: Cow<'_, str>) -> Value {
736        x.into_owned().into()
737    }
738}
739
740impl IntoIterator for Values {
741    type Item = Value;
742    type IntoIter = std::vec::IntoIter<Self::Item>;
743
744    fn into_iter(self) -> Self::IntoIter {
745        self.0.into_iter()
746    }
747}
748
749impl std::fmt::Display for Value {
750    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
751        CommonSqlQueryBuilder.write_value(f, self)
752    }
753}
754
755pub trait ValueType: Sized {
756    fn try_from(v: Value) -> Result<Self, ValueTypeErr>;
757
758    fn unwrap(v: Value) -> Self {
759        Self::try_from(v).unwrap()
760    }
761
762    fn expect(v: Value, msg: &str) -> Self {
763        Self::try_from(v).expect(msg)
764    }
765
766    fn is_option() -> bool {
767        false
768    }
769
770    fn type_name() -> String;
771
772    fn array_type() -> ArrayType;
773
774    fn column_type() -> ColumnType;
775
776    fn enum_type_name() -> Option<&'static str> {
777        None
778    }
779}
780
781impl<T> ValueType for Option<T>
782where
783    T: ValueType + Nullable,
784{
785    fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
786        if v == T::null() {
787            Ok(None)
788        } else {
789            Ok(Some(T::try_from(v)?))
790        }
791    }
792
793    fn is_option() -> bool {
794        true
795    }
796
797    fn type_name() -> String {
798        format!("Option<{}>", T::type_name())
799    }
800
801    fn array_type() -> ArrayType {
802        T::array_type()
803    }
804
805    fn column_type() -> ColumnType {
806        T::column_type()
807    }
808}
809
810impl ValueType for Cow<'_, str> {
811    fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
812        match v {
813            Value::String(Some(x)) => Ok((x).into()),
814            _ => Err(ValueTypeErr),
815        }
816    }
817
818    fn type_name() -> String {
819        "Cow<str>".into()
820    }
821
822    fn array_type() -> ArrayType {
823        ArrayType::String
824    }
825
826    fn column_type() -> ColumnType {
827        ColumnType::String(StringLen::None)
828    }
829}
830
831#[derive(Debug)]
832pub struct ValueTypeErr;
833
834impl std::error::Error for ValueTypeErr {}
835
836impl std::fmt::Display for ValueTypeErr {
837    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
838        f.write_str("Value type mismatch")
839    }
840}
841
842#[derive(Clone, Debug, PartialEq)]
843pub struct Values(pub Vec<Value>);
844
845impl Values {
846    pub fn iter(&self) -> impl Iterator<Item = &Value> {
847        self.0.iter()
848    }
849}
850
851pub trait Nullable {
852    fn null() -> Value;
853}
854
855impl Nullable for &str {
856    fn null() -> Value {
857        Value::String(None)
858    }
859}
860
861macro_rules! type_to_value {
862    ( $type: ty, $name: ident, $col_type: expr ) => {
863        impl From<$type> for Value {
864            fn from(x: $type) -> Value {
865                Value::$name(Some(x))
866            }
867        }
868
869        impl Nullable for $type {
870            fn null() -> Value {
871                Value::$name(None)
872            }
873        }
874
875        impl ValueType for $type {
876            fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
877                match v {
878                    Value::$name(Some(x)) => Ok(x),
879                    _ => Err(ValueTypeErr),
880                }
881            }
882
883            fn type_name() -> String {
884                stringify!($type).to_owned()
885            }
886
887            fn array_type() -> ArrayType {
888                ArrayType::$name
889            }
890
891            fn column_type() -> ColumnType {
892                use ColumnType::*;
893                $col_type
894            }
895        }
896    };
897}
898use type_to_value;
899
900type_to_value!(bool, Bool, Boolean);
901type_to_value!(i8, TinyInt, TinyInteger);
902type_to_value!(i16, SmallInt, SmallInteger);
903type_to_value!(i32, Int, Integer);
904type_to_value!(i64, BigInt, BigInteger);
905type_to_value!(u8, TinyUnsigned, TinyUnsigned);
906type_to_value!(u16, SmallUnsigned, SmallUnsigned);
907type_to_value!(u32, Unsigned, Unsigned);
908type_to_value!(u64, BigUnsigned, BigUnsigned);
909type_to_value!(f32, Float, Float);
910type_to_value!(f64, Double, Double);
911type_to_value!(char, Char, Char(None));
912type_to_value!(Vec<u8>, Bytes, VarBinary(StringLen::None));
913type_to_value!(String, String, String(StringLen::None));
914
915#[cfg(any(feature = "with-bigdecimal", feature = "with-jiff"))]
916#[allow(unused_macros)]
917macro_rules! type_to_box_value {
918    ( $type: ty, $name: ident, $col_type: expr ) => {
919        impl From<$type> for Value {
920            fn from(x: $type) -> Value {
921                Value::$name(Some(Box::new(x)))
922            }
923        }
924
925        impl Nullable for $type {
926            fn null() -> Value {
927                Value::$name(None)
928            }
929        }
930
931        impl ValueType for $type {
932            fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
933                match v {
934                    Value::$name(Some(x)) => Ok(*x),
935                    _ => Err(ValueTypeErr),
936                }
937            }
938
939            fn type_name() -> String {
940                stringify!($type).to_owned()
941            }
942
943            fn array_type() -> ArrayType {
944                ArrayType::$name
945            }
946
947            fn column_type() -> ColumnType {
948                use ColumnType::*;
949                $col_type
950            }
951        }
952    };
953}
954
955#[cfg(any(feature = "with-bigdecimal", feature = "with-jiff"))]
956#[allow(unused_imports)]
957use type_to_box_value;