Skip to main content

sea_query/
value.rs

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