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