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