sea_query/
value.rs

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