sea_query/
value.rs

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