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