sea_query/
value.rs

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