1use 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-rust_decimal")]
17use rust_decimal::Decimal;
18
19#[cfg(feature = "with-bigdecimal")]
20use bigdecimal::BigDecimal;
21
22#[cfg(feature = "with-uuid")]
23use uuid::Uuid;
24
25#[cfg(feature = "with-ipnetwork")]
26use ipnetwork::IpNetwork;
27
28#[cfg(feature = "with-ipnetwork")]
29use std::net::IpAddr;
30
31#[cfg(feature = "with-mac_address")]
32use mac_address::MacAddress;
33
34use crate::{ColumnType, CommonSqlQueryBuilder, QueryBuilder, StringLen};
35
36#[derive(Clone, Debug, Eq, PartialEq, Hash)]
38pub enum ArrayType {
39 Bool,
40 TinyInt,
41 SmallInt,
42 Int,
43 BigInt,
44 TinyUnsigned,
45 SmallUnsigned,
46 Unsigned,
47 BigUnsigned,
48 Float,
49 Double,
50 String,
51 Char,
52 Bytes,
53
54 #[cfg(feature = "with-json")]
55 #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
56 Json,
57
58 #[cfg(feature = "with-chrono")]
59 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
60 ChronoDate,
61
62 #[cfg(feature = "with-chrono")]
63 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
64 ChronoTime,
65
66 #[cfg(feature = "with-chrono")]
67 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
68 ChronoDateTime,
69
70 #[cfg(feature = "with-chrono")]
71 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
72 ChronoDateTimeUtc,
73
74 #[cfg(feature = "with-chrono")]
75 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
76 ChronoDateTimeLocal,
77
78 #[cfg(feature = "with-chrono")]
79 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
80 ChronoDateTimeWithTimeZone,
81
82 #[cfg(feature = "with-time")]
83 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
84 TimeDate,
85
86 #[cfg(feature = "with-time")]
87 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
88 TimeTime,
89
90 #[cfg(feature = "with-time")]
91 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
92 TimeDateTime,
93
94 #[cfg(feature = "with-time")]
95 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
96 TimeDateTimeWithTimeZone,
97
98 #[cfg(feature = "with-uuid")]
99 #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
100 Uuid,
101
102 #[cfg(feature = "with-rust_decimal")]
103 #[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
104 Decimal,
105
106 #[cfg(feature = "with-bigdecimal")]
107 #[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
108 BigDecimal,
109
110 #[cfg(feature = "with-ipnetwork")]
111 #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
112 IpNetwork,
113
114 #[cfg(feature = "with-mac_address")]
115 #[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
116 MacAddress,
117}
118
119#[derive(Clone, Debug)]
126#[cfg_attr(not(feature = "hashable-value"), derive(PartialEq))]
127pub enum Value {
128 Bool(Option<bool>),
129 TinyInt(Option<i8>),
130 SmallInt(Option<i16>),
131 Int(Option<i32>),
132 BigInt(Option<i64>),
133 TinyUnsigned(Option<u8>),
134 SmallUnsigned(Option<u16>),
135 Unsigned(Option<u32>),
136 BigUnsigned(Option<u64>),
137 Float(Option<f32>),
138 Double(Option<f64>),
139 String(Option<Box<String>>),
140 Char(Option<char>),
141
142 #[allow(clippy::box_collection)]
143 Bytes(Option<Box<Vec<u8>>>),
144
145 #[cfg(feature = "with-json")]
146 #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
147 Json(Option<Box<Json>>),
148
149 #[cfg(feature = "with-chrono")]
150 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
151 ChronoDate(Option<Box<NaiveDate>>),
152
153 #[cfg(feature = "with-chrono")]
154 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
155 ChronoTime(Option<Box<NaiveTime>>),
156
157 #[cfg(feature = "with-chrono")]
158 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
159 ChronoDateTime(Option<Box<NaiveDateTime>>),
160
161 #[cfg(feature = "with-chrono")]
162 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
163 ChronoDateTimeUtc(Option<Box<DateTime<Utc>>>),
164
165 #[cfg(feature = "with-chrono")]
166 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
167 ChronoDateTimeLocal(Option<Box<DateTime<Local>>>),
168
169 #[cfg(feature = "with-chrono")]
170 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
171 ChronoDateTimeWithTimeZone(Option<Box<DateTime<FixedOffset>>>),
172
173 #[cfg(feature = "with-time")]
174 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
175 TimeDate(Option<Box<time::Date>>),
176
177 #[cfg(feature = "with-time")]
178 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
179 TimeTime(Option<Box<time::Time>>),
180
181 #[cfg(feature = "with-time")]
182 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
183 TimeDateTime(Option<Box<PrimitiveDateTime>>),
184
185 #[cfg(feature = "with-time")]
186 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
187 TimeDateTimeWithTimeZone(Option<Box<OffsetDateTime>>),
188
189 #[cfg(feature = "with-uuid")]
190 #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
191 Uuid(Option<Box<Uuid>>),
192
193 #[cfg(feature = "with-rust_decimal")]
194 #[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
195 Decimal(Option<Box<Decimal>>),
196
197 #[cfg(feature = "with-bigdecimal")]
198 #[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
199 BigDecimal(Option<Box<BigDecimal>>),
200
201 #[cfg(feature = "postgres-array")]
202 #[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
203 Array(ArrayType, Option<Box<Vec<Value>>>),
204
205 #[cfg(feature = "postgres-vector")]
206 #[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))]
207 Vector(Option<Box<pgvector::Vector>>),
208
209 #[cfg(feature = "with-ipnetwork")]
210 #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
211 IpNetwork(Option<Box<IpNetwork>>),
212
213 #[cfg(feature = "with-mac_address")]
214 #[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
215 MacAddress(Option<Box<MacAddress>>),
216}
217
218impl std::fmt::Display for Value {
219 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
220 write!(f, "{}", CommonSqlQueryBuilder.value_to_string(self))
221 }
222}
223
224pub trait ValueType: Sized {
225 fn try_from(v: Value) -> Result<Self, ValueTypeErr>;
226
227 fn unwrap(v: Value) -> Self {
228 Self::try_from(v).unwrap()
229 }
230
231 fn expect(v: Value, msg: &str) -> Self {
232 Self::try_from(v).expect(msg)
233 }
234
235 fn is_option() -> bool {
236 false
237 }
238
239 fn type_name() -> String;
240
241 fn array_type() -> ArrayType;
242
243 fn column_type() -> ColumnType;
244
245 fn enum_type_name() -> Option<&'static str> {
246 None
247 }
248}
249
250#[derive(Debug)]
251pub struct ValueTypeErr;
252
253impl std::error::Error for ValueTypeErr {}
254
255impl std::fmt::Display for ValueTypeErr {
256 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
257 write!(f, "Value type mismatch")
258 }
259}
260
261#[derive(Clone, Debug, PartialEq)]
262pub struct Values(pub Vec<Value>);
263
264#[derive(Clone, Debug, PartialEq)]
265#[cfg_attr(feature = "hashable-value", derive(Hash, Eq))]
266pub enum ValueTuple {
267 One(Value),
268 Two(Value, Value),
269 Three(Value, Value, Value),
270 Many(Vec<Value>),
271}
272
273pub trait IntoValueTuple {
274 fn into_value_tuple(self) -> ValueTuple;
275}
276
277pub trait FromValueTuple: Sized {
278 fn from_value_tuple<I>(i: I) -> Self
279 where
280 I: IntoValueTuple;
281}
282
283pub trait Nullable {
284 fn null() -> Value;
285}
286
287impl Value {
288 pub fn unwrap<T>(self) -> T
289 where
290 T: ValueType,
291 {
292 T::unwrap(self)
293 }
294
295 pub fn expect<T>(self, msg: &str) -> T
296 where
297 T: ValueType,
298 {
299 T::expect(self, msg)
300 }
301
302 pub fn as_null(&self) -> Self {
316 match self {
317 Self::Bool(_) => Self::Bool(None),
318 Self::TinyInt(_) => Self::TinyInt(None),
319 Self::SmallInt(_) => Self::SmallInt(None),
320 Self::Int(_) => Self::Int(None),
321 Self::BigInt(_) => Self::BigInt(None),
322 Self::TinyUnsigned(_) => Self::TinyUnsigned(None),
323 Self::SmallUnsigned(_) => Self::SmallUnsigned(None),
324 Self::Unsigned(_) => Self::Unsigned(None),
325 Self::BigUnsigned(_) => Self::BigUnsigned(None),
326 Self::Float(_) => Self::Float(None),
327 Self::Double(_) => Self::Double(None),
328 Self::String(_) => Self::String(None),
329 Self::Char(_) => Self::Char(None),
330 Self::Bytes(_) => Self::Bytes(None),
331
332 #[cfg(feature = "with-json")]
333 #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
334 Self::Json(_) => Self::Json(None),
335
336 #[cfg(feature = "with-chrono")]
337 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
338 Self::ChronoDate(_) => Self::ChronoDate(None),
339
340 #[cfg(feature = "with-chrono")]
341 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
342 Self::ChronoTime(_) => Self::ChronoTime(None),
343
344 #[cfg(feature = "with-chrono")]
345 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
346 Self::ChronoDateTime(_) => Self::ChronoDateTime(None),
347
348 #[cfg(feature = "with-chrono")]
349 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
350 Self::ChronoDateTimeUtc(_) => Self::ChronoDateTimeUtc(None),
351
352 #[cfg(feature = "with-chrono")]
353 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
354 Self::ChronoDateTimeLocal(_) => Self::ChronoDateTimeLocal(None),
355
356 #[cfg(feature = "with-chrono")]
357 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
358 Self::ChronoDateTimeWithTimeZone(_) => Self::ChronoDateTimeWithTimeZone(None),
359
360 #[cfg(feature = "with-time")]
361 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
362 Self::TimeDate(_) => Self::TimeDate(None),
363
364 #[cfg(feature = "with-time")]
365 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
366 Self::TimeTime(_) => Self::TimeTime(None),
367
368 #[cfg(feature = "with-time")]
369 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
370 Self::TimeDateTime(_) => Self::TimeDateTime(None),
371
372 #[cfg(feature = "with-time")]
373 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
374 Self::TimeDateTimeWithTimeZone(_) => Self::TimeDateTimeWithTimeZone(None),
375
376 #[cfg(feature = "with-uuid")]
377 #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
378 Self::Uuid(_) => Self::Uuid(None),
379
380 #[cfg(feature = "with-rust_decimal")]
381 #[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
382 Self::Decimal(_) => Self::Decimal(None),
383
384 #[cfg(feature = "with-bigdecimal")]
385 #[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
386 Self::BigDecimal(_) => Self::BigDecimal(None),
387
388 #[cfg(feature = "postgres-array")]
389 #[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
390 Self::Array(ty, _) => Self::Array(ty.clone(), None),
391
392 #[cfg(feature = "postgres-vector")]
393 #[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))]
394 Self::Vector(_) => Self::Vector(None),
395
396 #[cfg(feature = "with-ipnetwork")]
397 #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
398 Self::IpNetwork(_) => Self::IpNetwork(None),
399
400 #[cfg(feature = "with-mac_address")]
401 #[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
402 Self::MacAddress(_) => Self::MacAddress(None),
403 }
404 }
405
406 pub fn dummy_value(&self) -> Self {
416 match self {
417 Self::Bool(_) => Self::Bool(Some(Default::default())),
418 Self::TinyInt(_) => Self::TinyInt(Some(Default::default())),
419 Self::SmallInt(_) => Self::SmallInt(Some(Default::default())),
420 Self::Int(_) => Self::Int(Some(Default::default())),
421 Self::BigInt(_) => Self::BigInt(Some(Default::default())),
422 Self::TinyUnsigned(_) => Self::TinyUnsigned(Some(Default::default())),
423 Self::SmallUnsigned(_) => Self::SmallUnsigned(Some(Default::default())),
424 Self::Unsigned(_) => Self::Unsigned(Some(Default::default())),
425 Self::BigUnsigned(_) => Self::BigUnsigned(Some(Default::default())),
426 Self::Float(_) => Self::Float(Some(Default::default())),
427 Self::Double(_) => Self::Double(Some(Default::default())),
428 Self::String(_) => Self::String(Some(Default::default())),
429 Self::Char(_) => Self::Char(Some(Default::default())),
430 Self::Bytes(_) => Self::Bytes(Some(Default::default())),
431
432 #[cfg(feature = "with-json")]
433 #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
434 Self::Json(_) => Self::Json(Some(Default::default())),
435
436 #[cfg(feature = "with-chrono")]
437 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
438 Self::ChronoDate(_) => Self::ChronoDate(Some(Default::default())),
439
440 #[cfg(feature = "with-chrono")]
441 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
442 Self::ChronoTime(_) => Self::ChronoTime(Some(Default::default())),
443
444 #[cfg(feature = "with-chrono")]
445 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
446 Self::ChronoDateTime(_) => Self::ChronoDateTime(Some(Default::default())),
447
448 #[cfg(feature = "with-chrono")]
449 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
450 Self::ChronoDateTimeUtc(_) => Self::ChronoDateTimeUtc(Some(Default::default())),
451
452 #[cfg(feature = "with-chrono")]
453 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
454 Self::ChronoDateTimeLocal(_) => Self::ChronoDateTimeLocal(Some(Default::default())),
455
456 #[cfg(feature = "with-chrono")]
457 #[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
458 Self::ChronoDateTimeWithTimeZone(_) => {
459 Self::ChronoDateTimeWithTimeZone(Some(Default::default()))
460 }
461
462 #[cfg(feature = "with-time")]
463 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
464 Self::TimeDate(_) => Self::TimeDate(Some(time::Date::MIN.into())),
465
466 #[cfg(feature = "with-time")]
467 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
468 Self::TimeTime(_) => Self::TimeTime(Some(time::Time::MIDNIGHT.into())),
469
470 #[cfg(feature = "with-time")]
471 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
472 Self::TimeDateTime(_) => Self::TimeDateTime(Some(PrimitiveDateTime::MIN.into())),
473
474 #[cfg(feature = "with-time")]
475 #[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
476 Self::TimeDateTimeWithTimeZone(_) => {
477 Self::TimeDateTimeWithTimeZone(Some(OffsetDateTime::UNIX_EPOCH.into()))
478 }
479
480 #[cfg(feature = "with-uuid")]
481 #[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
482 Self::Uuid(_) => Self::Uuid(Some(Default::default())),
483
484 #[cfg(feature = "with-rust_decimal")]
485 #[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
486 Self::Decimal(_) => Self::Decimal(Some(Default::default())),
487
488 #[cfg(feature = "with-bigdecimal")]
489 #[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
490 Self::BigDecimal(_) => Self::BigDecimal(Some(Default::default())),
491
492 #[cfg(feature = "postgres-array")]
493 #[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
494 Self::Array(ty, _) => Self::Array(ty.clone(), Some(Default::default())),
495
496 #[cfg(feature = "postgres-vector")]
497 #[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))]
498 Self::Vector(_) => Self::Vector(Some(Box::new(vec![].into()))),
499
500 #[cfg(feature = "with-ipnetwork")]
501 #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
502 Self::IpNetwork(_) => Self::IpNetwork(Some(Box::new("0.0.0.0".parse().unwrap()))),
503
504 #[cfg(feature = "with-mac_address")]
505 #[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
506 Self::MacAddress(_) => Self::MacAddress(Some(Default::default())),
507 }
508 }
509}
510
511macro_rules! type_to_value {
512 ( $type: ty, $name: ident, $col_type: expr ) => {
513 impl From<$type> for Value {
514 fn from(x: $type) -> Value {
515 Value::$name(Some(x))
516 }
517 }
518
519 impl Nullable for $type {
520 fn null() -> Value {
521 Value::$name(None)
522 }
523 }
524
525 impl ValueType for $type {
526 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
527 match v {
528 Value::$name(Some(x)) => Ok(x),
529 _ => Err(ValueTypeErr),
530 }
531 }
532
533 fn type_name() -> String {
534 stringify!($type).to_owned()
535 }
536
537 fn array_type() -> ArrayType {
538 ArrayType::$name
539 }
540
541 fn column_type() -> ColumnType {
542 use ColumnType::*;
543 $col_type
544 }
545 }
546 };
547}
548
549macro_rules! type_to_box_value {
550 ( $type: ty, $name: ident, $col_type: expr ) => {
551 impl From<$type> for Value {
552 fn from(x: $type) -> Value {
553 Value::$name(Some(Box::new(x)))
554 }
555 }
556
557 impl Nullable for $type {
558 fn null() -> Value {
559 Value::$name(None)
560 }
561 }
562
563 impl ValueType for $type {
564 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
565 match v {
566 Value::$name(Some(x)) => Ok(*x),
567 _ => Err(ValueTypeErr),
568 }
569 }
570
571 fn type_name() -> String {
572 stringify!($type).to_owned()
573 }
574
575 fn array_type() -> ArrayType {
576 ArrayType::$name
577 }
578
579 fn column_type() -> ColumnType {
580 use ColumnType::*;
581 $col_type
582 }
583 }
584 };
585}
586
587type_to_value!(bool, Bool, Boolean);
588type_to_value!(i8, TinyInt, TinyInteger);
589type_to_value!(i16, SmallInt, SmallInteger);
590type_to_value!(i32, Int, Integer);
591type_to_value!(i64, BigInt, BigInteger);
592type_to_value!(u8, TinyUnsigned, TinyUnsigned);
593type_to_value!(u16, SmallUnsigned, SmallUnsigned);
594type_to_value!(u32, Unsigned, Unsigned);
595type_to_value!(u64, BigUnsigned, BigUnsigned);
596type_to_value!(f32, Float, Float);
597type_to_value!(f64, Double, Double);
598type_to_value!(char, Char, Char(None));
599
600impl From<&[u8]> for Value {
601 fn from(x: &[u8]) -> Value {
602 Value::Bytes(Some(Box::<Vec<u8>>::new(x.into())))
603 }
604}
605
606impl From<&str> for Value {
607 fn from(x: &str) -> Value {
608 let string: String = x.into();
609 Value::String(Some(Box::new(string)))
610 }
611}
612
613impl From<&String> for Value {
614 fn from(x: &String) -> Value {
615 let string: String = x.into();
616 Value::String(Some(Box::new(string)))
617 }
618}
619
620impl Nullable for &str {
621 fn null() -> Value {
622 Value::String(None)
623 }
624}
625
626impl<T> From<Option<T>> for Value
627where
628 T: Into<Value> + Nullable,
629{
630 fn from(x: Option<T>) -> Value {
631 match x {
632 Some(v) => v.into(),
633 None => T::null(),
634 }
635 }
636}
637
638impl<T> ValueType for Option<T>
639where
640 T: ValueType + Nullable,
641{
642 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
643 if v == T::null() {
644 Ok(None)
645 } else {
646 Ok(Some(T::try_from(v)?))
647 }
648 }
649
650 fn is_option() -> bool {
651 true
652 }
653
654 fn type_name() -> String {
655 format!("Option<{}>", T::type_name())
656 }
657
658 fn array_type() -> ArrayType {
659 T::array_type()
660 }
661
662 fn column_type() -> ColumnType {
663 T::column_type()
664 }
665}
666
667impl From<Cow<'_, str>> for Value {
668 fn from(x: Cow<'_, str>) -> Value {
669 x.into_owned().into()
670 }
671}
672
673impl ValueType for Cow<'_, str> {
674 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
675 match v {
676 Value::String(Some(x)) => Ok((*x).into()),
677 _ => Err(ValueTypeErr),
678 }
679 }
680
681 fn type_name() -> String {
682 "Cow<str>".into()
683 }
684
685 fn array_type() -> ArrayType {
686 ArrayType::String
687 }
688
689 fn column_type() -> ColumnType {
690 ColumnType::String(StringLen::None)
691 }
692}
693
694type_to_box_value!(Vec<u8>, Bytes, VarBinary(StringLen::None));
695type_to_box_value!(String, String, String(StringLen::None));
696
697#[cfg(feature = "with-json")]
698#[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
699mod with_json {
700 use super::*;
701
702 type_to_box_value!(Json, Json, Json);
703}
704
705#[cfg(feature = "with-chrono")]
706#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
707mod with_chrono {
708 use super::*;
709 use chrono::{Local, Offset, Utc};
710
711 type_to_box_value!(NaiveDate, ChronoDate, Date);
712 type_to_box_value!(NaiveTime, ChronoTime, Time);
713 type_to_box_value!(NaiveDateTime, ChronoDateTime, DateTime);
714
715 impl From<DateTime<Utc>> for Value {
716 fn from(v: DateTime<Utc>) -> Value {
717 Value::ChronoDateTimeUtc(Some(Box::new(v)))
718 }
719 }
720
721 impl From<DateTime<Local>> for Value {
722 fn from(v: DateTime<Local>) -> Value {
723 Value::ChronoDateTimeLocal(Some(Box::new(v)))
724 }
725 }
726
727 impl From<DateTime<FixedOffset>> for Value {
728 fn from(x: DateTime<FixedOffset>) -> Value {
729 let v =
730 DateTime::<FixedOffset>::from_naive_utc_and_offset(x.naive_utc(), x.offset().fix());
731 Value::ChronoDateTimeWithTimeZone(Some(Box::new(v)))
732 }
733 }
734
735 impl Nullable for DateTime<Utc> {
736 fn null() -> Value {
737 Value::ChronoDateTimeUtc(None)
738 }
739 }
740
741 impl ValueType for DateTime<Utc> {
742 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
743 match v {
744 Value::ChronoDateTimeUtc(Some(x)) => Ok(*x),
745 _ => Err(ValueTypeErr),
746 }
747 }
748
749 fn type_name() -> String {
750 stringify!(DateTime<Utc>).to_owned()
751 }
752
753 fn array_type() -> ArrayType {
754 ArrayType::ChronoDateTimeUtc
755 }
756
757 fn column_type() -> ColumnType {
758 ColumnType::TimestampWithTimeZone
759 }
760 }
761
762 impl Nullable for DateTime<Local> {
763 fn null() -> Value {
764 Value::ChronoDateTimeLocal(None)
765 }
766 }
767
768 impl ValueType for DateTime<Local> {
769 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
770 match v {
771 Value::ChronoDateTimeLocal(Some(x)) => Ok(*x),
772 _ => Err(ValueTypeErr),
773 }
774 }
775
776 fn type_name() -> String {
777 stringify!(DateTime<Local>).to_owned()
778 }
779
780 fn array_type() -> ArrayType {
781 ArrayType::ChronoDateTimeLocal
782 }
783
784 fn column_type() -> ColumnType {
785 ColumnType::TimestampWithTimeZone
786 }
787 }
788
789 impl Nullable for DateTime<FixedOffset> {
790 fn null() -> Value {
791 Value::ChronoDateTimeWithTimeZone(None)
792 }
793 }
794
795 impl ValueType for DateTime<FixedOffset> {
796 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
797 match v {
798 Value::ChronoDateTimeWithTimeZone(Some(x)) => Ok(*x),
799 _ => Err(ValueTypeErr),
800 }
801 }
802
803 fn type_name() -> String {
804 stringify!(DateTime<FixedOffset>).to_owned()
805 }
806
807 fn array_type() -> ArrayType {
808 ArrayType::ChronoDateTimeWithTimeZone
809 }
810
811 fn column_type() -> ColumnType {
812 ColumnType::TimestampWithTimeZone
813 }
814 }
815}
816
817#[cfg(feature = "with-time")]
818#[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
819pub mod time_format {
820 use time::format_description::FormatItem;
821 use time::macros::format_description;
822
823 pub static FORMAT_DATE: &[FormatItem<'static>] = format_description!("[year]-[month]-[day]");
824 pub static FORMAT_TIME: &[FormatItem<'static>] =
825 format_description!("[hour]:[minute]:[second].[subsecond digits:6]");
826 pub static FORMAT_DATETIME: &[FormatItem<'static>] =
827 format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:6]");
828 pub static FORMAT_DATETIME_TZ: &[FormatItem<'static>] = format_description!(
829 "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:6] [offset_hour sign:mandatory]:[offset_minute]"
830 );
831}
832
833#[cfg(feature = "with-time")]
834#[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
835mod with_time {
836 use super::*;
837
838 type_to_box_value!(time::Date, TimeDate, Date);
839 type_to_box_value!(time::Time, TimeTime, Time);
840 type_to_box_value!(PrimitiveDateTime, TimeDateTime, DateTime);
841
842 impl From<OffsetDateTime> for Value {
843 fn from(v: OffsetDateTime) -> Value {
844 Value::TimeDateTimeWithTimeZone(Some(Box::new(v)))
845 }
846 }
847
848 impl Nullable for OffsetDateTime {
849 fn null() -> Value {
850 Value::TimeDateTimeWithTimeZone(None)
851 }
852 }
853
854 impl ValueType for OffsetDateTime {
855 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
856 match v {
857 Value::TimeDateTimeWithTimeZone(Some(x)) => Ok(*x),
858 _ => Err(ValueTypeErr),
859 }
860 }
861
862 fn type_name() -> String {
863 stringify!(OffsetDateTime).to_owned()
864 }
865
866 fn array_type() -> ArrayType {
867 ArrayType::TimeDateTimeWithTimeZone
868 }
869
870 fn column_type() -> ColumnType {
871 ColumnType::TimestampWithTimeZone
872 }
873 }
874}
875
876#[cfg(feature = "with-rust_decimal")]
877#[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
878mod with_rust_decimal {
879 use super::*;
880
881 type_to_box_value!(Decimal, Decimal, Decimal(None));
882}
883
884#[cfg(feature = "with-bigdecimal")]
885#[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
886mod with_bigdecimal {
887 use super::*;
888
889 type_to_box_value!(BigDecimal, BigDecimal, Decimal(None));
890}
891
892#[cfg(feature = "with-uuid")]
893#[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
894mod with_uuid {
895 use super::*;
896
897 type_to_box_value!(Uuid, Uuid, Uuid);
898
899 macro_rules! fmt_uuid_to_box_value {
900 ( $type: ty, $conversion_fn: ident ) => {
901 impl From<$type> for Value {
902 fn from(x: $type) -> Value {
903 Value::Uuid(Some(Box::new(x.into_uuid())))
904 }
905 }
906
907 impl Nullable for $type {
908 fn null() -> Value {
909 Value::Uuid(None)
910 }
911 }
912
913 impl ValueType for $type {
914 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
915 match v {
916 Value::Uuid(Some(x)) => Ok(x.$conversion_fn()),
917 _ => Err(ValueTypeErr),
918 }
919 }
920
921 fn type_name() -> String {
922 stringify!($type).to_owned()
923 }
924
925 fn array_type() -> ArrayType {
926 ArrayType::Uuid
927 }
928
929 fn column_type() -> ColumnType {
930 ColumnType::Uuid
931 }
932 }
933 };
934 }
935
936 fmt_uuid_to_box_value!(uuid::fmt::Braced, braced);
937 fmt_uuid_to_box_value!(uuid::fmt::Hyphenated, hyphenated);
938 fmt_uuid_to_box_value!(uuid::fmt::Simple, simple);
939 fmt_uuid_to_box_value!(uuid::fmt::Urn, urn);
940}
941
942#[cfg(feature = "with-ipnetwork")]
943#[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
944mod with_ipnetwork {
945 use super::*;
946
947 type_to_box_value!(IpNetwork, IpNetwork, Inet);
948}
949
950#[cfg(feature = "with-mac_address")]
951#[cfg_attr(docsrs, doc(cfg(feature = "with-mac_address")))]
952mod with_mac_address {
953 use super::*;
954
955 type_to_box_value!(MacAddress, MacAddress, MacAddr);
956}
957
958#[cfg(feature = "postgres-array")]
959#[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))]
960pub mod with_array {
961 use super::*;
962 use crate::RcOrArc;
963
964 pub trait NotU8 {}
968
969 impl NotU8 for bool {}
970 impl NotU8 for i8 {}
971 impl NotU8 for i16 {}
972 impl NotU8 for i32 {}
973 impl NotU8 for i64 {}
974 impl NotU8 for u16 {}
975 impl NotU8 for u32 {}
976 impl NotU8 for u64 {}
977 impl NotU8 for f32 {}
978 impl NotU8 for f64 {}
979 impl NotU8 for char {}
980 impl NotU8 for String {}
981 impl NotU8 for Vec<u8> {}
982
983 #[cfg(feature = "with-json")]
986 impl NotU8 for Json {}
987
988 #[cfg(feature = "with-chrono")]
989 impl NotU8 for NaiveDate {}
990
991 #[cfg(feature = "with-chrono")]
992 impl NotU8 for NaiveTime {}
993
994 #[cfg(feature = "with-chrono")]
995 impl NotU8 for NaiveDateTime {}
996
997 #[cfg(feature = "with-chrono")]
998 impl<Tz> NotU8 for DateTime<Tz> where Tz: chrono::TimeZone {}
999
1000 #[cfg(feature = "with-time")]
1001 impl NotU8 for time::Date {}
1002
1003 #[cfg(feature = "with-time")]
1004 impl NotU8 for time::Time {}
1005
1006 #[cfg(feature = "with-time")]
1007 impl NotU8 for PrimitiveDateTime {}
1008
1009 #[cfg(feature = "with-time")]
1010 impl NotU8 for OffsetDateTime {}
1011
1012 #[cfg(feature = "with-rust_decimal")]
1013 impl NotU8 for Decimal {}
1014
1015 #[cfg(feature = "with-bigdecimal")]
1016 impl NotU8 for BigDecimal {}
1017
1018 #[cfg(feature = "with-uuid")]
1019 impl NotU8 for Uuid {}
1020
1021 #[cfg(feature = "with-uuid")]
1022 impl NotU8 for uuid::fmt::Braced {}
1023
1024 #[cfg(feature = "with-uuid")]
1025 impl NotU8 for uuid::fmt::Hyphenated {}
1026
1027 #[cfg(feature = "with-uuid")]
1028 impl NotU8 for uuid::fmt::Simple {}
1029
1030 #[cfg(feature = "with-uuid")]
1031 impl NotU8 for uuid::fmt::Urn {}
1032
1033 #[cfg(feature = "with-ipnetwork")]
1034 impl NotU8 for IpNetwork {}
1035
1036 #[cfg(feature = "with-mac_address")]
1037 impl NotU8 for MacAddress {}
1038
1039 impl<T> From<Vec<T>> for Value
1040 where
1041 T: Into<Value> + NotU8 + ValueType,
1042 {
1043 fn from(x: Vec<T>) -> Value {
1044 Value::Array(
1045 T::array_type(),
1046 Some(Box::new(x.into_iter().map(|e| e.into()).collect())),
1047 )
1048 }
1049 }
1050
1051 impl<T> Nullable for Vec<T>
1052 where
1053 T: Into<Value> + NotU8 + ValueType,
1054 {
1055 fn null() -> Value {
1056 Value::Array(T::array_type(), None)
1057 }
1058 }
1059
1060 impl<T> ValueType for Vec<T>
1061 where
1062 T: NotU8 + ValueType,
1063 {
1064 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
1065 match v {
1066 Value::Array(ty, Some(v)) if T::array_type() == ty => {
1067 Ok(v.into_iter().map(|e| e.unwrap()).collect())
1068 }
1069 _ => Err(ValueTypeErr),
1070 }
1071 }
1072
1073 fn type_name() -> String {
1074 stringify!(Vec<T>).to_owned()
1075 }
1076
1077 fn array_type() -> ArrayType {
1078 T::array_type()
1079 }
1080
1081 fn column_type() -> ColumnType {
1082 use ColumnType::*;
1083 Array(RcOrArc::new(T::column_type()))
1084 }
1085 }
1086}
1087
1088#[cfg(feature = "postgres-vector")]
1089#[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))]
1090pub mod with_vector {
1091 use super::*;
1092
1093 impl From<pgvector::Vector> for Value {
1094 fn from(x: pgvector::Vector) -> Value {
1095 Value::Vector(Some(Box::new(x)))
1096 }
1097 }
1098
1099 impl Nullable for pgvector::Vector {
1100 fn null() -> Value {
1101 Value::Vector(None)
1102 }
1103 }
1104
1105 impl ValueType for pgvector::Vector {
1106 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
1107 match v {
1108 Value::Vector(Some(x)) => Ok(*x),
1109 _ => Err(ValueTypeErr),
1110 }
1111 }
1112
1113 fn type_name() -> String {
1114 stringify!(Vector).to_owned()
1115 }
1116
1117 fn array_type() -> ArrayType {
1118 unimplemented!("Vector does not have array type")
1119 }
1120
1121 fn column_type() -> ColumnType {
1122 ColumnType::Vector(None)
1123 }
1124 }
1125}
1126
1127#[allow(unused_macros)]
1128macro_rules! box_to_opt_ref {
1129 ( $v: expr ) => {
1130 match $v {
1131 Some(v) => Some(v.as_ref()),
1132 None => None,
1133 }
1134 };
1135}
1136
1137#[cfg(feature = "with-json")]
1138impl Value {
1139 pub fn is_json(&self) -> bool {
1140 matches!(self, Self::Json(_))
1141 }
1142
1143 pub fn as_ref_json(&self) -> Option<&Json> {
1144 match self {
1145 Self::Json(v) => box_to_opt_ref!(v),
1146 _ => panic!("not Value::Json"),
1147 }
1148 }
1149}
1150
1151#[cfg(feature = "with-chrono")]
1152impl Value {
1153 pub fn is_chrono_date(&self) -> bool {
1154 matches!(self, Self::ChronoDate(_))
1155 }
1156
1157 pub fn as_ref_chrono_date(&self) -> Option<&NaiveDate> {
1158 match self {
1159 Self::ChronoDate(v) => box_to_opt_ref!(v),
1160 _ => panic!("not Value::ChronoDate"),
1161 }
1162 }
1163}
1164
1165#[cfg(feature = "with-time")]
1166impl Value {
1167 pub fn is_time_date(&self) -> bool {
1168 matches!(self, Self::TimeDate(_))
1169 }
1170
1171 pub fn as_ref_time_date(&self) -> Option<&time::Date> {
1172 match self {
1173 Self::TimeDate(v) => box_to_opt_ref!(v),
1174 _ => panic!("not Value::TimeDate"),
1175 }
1176 }
1177}
1178
1179#[cfg(feature = "with-chrono")]
1180impl Value {
1181 pub fn is_chrono_time(&self) -> bool {
1182 matches!(self, Self::ChronoTime(_))
1183 }
1184
1185 pub fn as_ref_chrono_time(&self) -> Option<&NaiveTime> {
1186 match self {
1187 Self::ChronoTime(v) => box_to_opt_ref!(v),
1188 _ => panic!("not Value::ChronoTime"),
1189 }
1190 }
1191}
1192
1193#[cfg(feature = "with-time")]
1194impl Value {
1195 pub fn is_time_time(&self) -> bool {
1196 matches!(self, Self::TimeTime(_))
1197 }
1198
1199 pub fn as_ref_time_time(&self) -> Option<&time::Time> {
1200 match self {
1201 Self::TimeTime(v) => box_to_opt_ref!(v),
1202 _ => panic!("not Value::TimeTime"),
1203 }
1204 }
1205}
1206
1207#[cfg(feature = "with-chrono")]
1208impl Value {
1209 pub fn is_chrono_date_time(&self) -> bool {
1210 matches!(self, Self::ChronoDateTime(_))
1211 }
1212
1213 pub fn as_ref_chrono_date_time(&self) -> Option<&NaiveDateTime> {
1214 match self {
1215 Self::ChronoDateTime(v) => box_to_opt_ref!(v),
1216 _ => panic!("not Value::ChronoDateTime"),
1217 }
1218 }
1219}
1220
1221#[cfg(feature = "with-time")]
1222impl Value {
1223 pub fn is_time_date_time(&self) -> bool {
1224 matches!(self, Self::TimeDateTime(_))
1225 }
1226
1227 pub fn as_ref_time_date_time(&self) -> Option<&PrimitiveDateTime> {
1228 match self {
1229 Self::TimeDateTime(v) => box_to_opt_ref!(v),
1230 _ => panic!("not Value::TimeDateTime"),
1231 }
1232 }
1233}
1234
1235#[cfg(feature = "with-chrono")]
1236impl Value {
1237 pub fn is_chrono_date_time_utc(&self) -> bool {
1238 matches!(self, Self::ChronoDateTimeUtc(_))
1239 }
1240
1241 pub fn as_ref_chrono_date_time_utc(&self) -> Option<&DateTime<Utc>> {
1242 match self {
1243 Self::ChronoDateTimeUtc(v) => box_to_opt_ref!(v),
1244 _ => panic!("not Value::ChronoDateTimeUtc"),
1245 }
1246 }
1247}
1248
1249#[cfg(feature = "with-chrono")]
1250impl Value {
1251 pub fn is_chrono_date_time_local(&self) -> bool {
1252 matches!(self, Self::ChronoDateTimeLocal(_))
1253 }
1254
1255 pub fn as_ref_chrono_date_time_local(&self) -> Option<&DateTime<Local>> {
1256 match self {
1257 Self::ChronoDateTimeLocal(v) => box_to_opt_ref!(v),
1258 _ => panic!("not Value::ChronoDateTimeLocal"),
1259 }
1260 }
1261}
1262
1263#[cfg(feature = "with-chrono")]
1264impl Value {
1265 pub fn is_chrono_date_time_with_time_zone(&self) -> bool {
1266 matches!(self, Self::ChronoDateTimeWithTimeZone(_))
1267 }
1268
1269 pub fn as_ref_chrono_date_time_with_time_zone(&self) -> Option<&DateTime<FixedOffset>> {
1270 match self {
1271 Self::ChronoDateTimeWithTimeZone(v) => box_to_opt_ref!(v),
1272 _ => panic!("not Value::ChronoDateTimeWithTimeZone"),
1273 }
1274 }
1275}
1276
1277#[cfg(feature = "with-time")]
1278impl Value {
1279 pub fn is_time_date_time_with_time_zone(&self) -> bool {
1280 matches!(self, Self::TimeDateTimeWithTimeZone(_))
1281 }
1282
1283 pub fn as_ref_time_date_time_with_time_zone(&self) -> Option<&OffsetDateTime> {
1284 match self {
1285 Self::TimeDateTimeWithTimeZone(v) => box_to_opt_ref!(v),
1286 _ => panic!("not Value::TimeDateTimeWithTimeZone"),
1287 }
1288 }
1289}
1290
1291#[cfg(feature = "with-chrono")]
1292impl Value {
1293 pub fn chrono_as_naive_utc_in_string(&self) -> Option<String> {
1294 match self {
1295 Self::ChronoDate(v) => v.as_ref().map(|v| v.to_string()),
1296 Self::ChronoTime(v) => v.as_ref().map(|v| v.to_string()),
1297 Self::ChronoDateTime(v) => v.as_ref().map(|v| v.to_string()),
1298 Self::ChronoDateTimeUtc(v) => v.as_ref().map(|v| v.naive_utc().to_string()),
1299 Self::ChronoDateTimeLocal(v) => v.as_ref().map(|v| v.naive_utc().to_string()),
1300 Self::ChronoDateTimeWithTimeZone(v) => v.as_ref().map(|v| v.naive_utc().to_string()),
1301 _ => panic!("not chrono Value"),
1302 }
1303 }
1304}
1305
1306#[cfg(feature = "with-time")]
1307impl Value {
1308 pub fn time_as_naive_utc_in_string(&self) -> Option<String> {
1309 match self {
1310 Self::TimeDate(v) => v
1311 .as_ref()
1312 .and_then(|v| v.format(time_format::FORMAT_DATE).ok()),
1313 Self::TimeTime(v) => v
1314 .as_ref()
1315 .and_then(|v| v.format(time_format::FORMAT_TIME).ok()),
1316 Self::TimeDateTime(v) => v
1317 .as_ref()
1318 .and_then(|v| v.format(time_format::FORMAT_DATETIME).ok()),
1319 Self::TimeDateTimeWithTimeZone(v) => v.as_ref().and_then(|v| {
1320 v.to_offset(time::macros::offset!(UTC))
1321 .format(time_format::FORMAT_DATETIME_TZ)
1322 .ok()
1323 }),
1324 _ => panic!("not time Value"),
1325 }
1326 }
1327}
1328
1329#[cfg(feature = "with-rust_decimal")]
1330impl Value {
1331 pub fn is_decimal(&self) -> bool {
1332 matches!(self, Self::Decimal(_))
1333 }
1334
1335 pub fn as_ref_decimal(&self) -> Option<&Decimal> {
1336 match self {
1337 Self::Decimal(v) => box_to_opt_ref!(v),
1338 _ => panic!("not Value::Decimal"),
1339 }
1340 }
1341
1342 pub fn decimal_to_f64(&self) -> Option<f64> {
1343 use rust_decimal::prelude::ToPrimitive;
1344
1345 self.as_ref_decimal().map(|d| d.to_f64().unwrap())
1346 }
1347}
1348
1349#[cfg(feature = "with-bigdecimal")]
1350impl Value {
1351 pub fn is_big_decimal(&self) -> bool {
1352 matches!(self, Self::BigDecimal(_))
1353 }
1354
1355 pub fn as_ref_big_decimal(&self) -> Option<&BigDecimal> {
1356 match self {
1357 Self::BigDecimal(v) => box_to_opt_ref!(v),
1358 _ => panic!("not Value::BigDecimal"),
1359 }
1360 }
1361
1362 pub fn big_decimal_to_f64(&self) -> Option<f64> {
1363 use bigdecimal::ToPrimitive;
1364 self.as_ref_big_decimal().map(|d| d.to_f64().unwrap())
1365 }
1366}
1367
1368#[cfg(feature = "with-uuid")]
1369impl Value {
1370 pub fn is_uuid(&self) -> bool {
1371 matches!(self, Self::Uuid(_))
1372 }
1373 pub fn as_ref_uuid(&self) -> Option<&Uuid> {
1374 match self {
1375 Self::Uuid(v) => box_to_opt_ref!(v),
1376 _ => panic!("not Value::Uuid"),
1377 }
1378 }
1379}
1380
1381#[cfg(feature = "postgres-array")]
1382impl Value {
1383 pub fn is_array(&self) -> bool {
1384 matches!(self, Self::Array(_, _))
1385 }
1386
1387 pub fn as_ref_array(&self) -> Option<&Vec<Value>> {
1388 match self {
1389 Self::Array(_, v) => box_to_opt_ref!(v),
1390 _ => panic!("not Value::Array"),
1391 }
1392 }
1393}
1394
1395#[cfg(feature = "with-ipnetwork")]
1396impl Value {
1397 pub fn is_ipnetwork(&self) -> bool {
1398 matches!(self, Self::IpNetwork(_))
1399 }
1400
1401 pub fn as_ref_ipnetwork(&self) -> Option<&IpNetwork> {
1402 match self {
1403 Self::IpNetwork(v) => box_to_opt_ref!(v),
1404 _ => panic!("not Value::IpNetwork"),
1405 }
1406 }
1407
1408 pub fn as_ipaddr(&self) -> Option<IpAddr> {
1409 match self {
1410 Self::IpNetwork(v) => v.clone().map(|v| v.network()),
1411 _ => panic!("not Value::IpNetwork"),
1412 }
1413 }
1414}
1415
1416#[cfg(feature = "with-mac_address")]
1417impl Value {
1418 pub fn is_mac_address(&self) -> bool {
1419 matches!(self, Self::MacAddress(_))
1420 }
1421
1422 pub fn as_ref_mac_address(&self) -> Option<&MacAddress> {
1423 match self {
1424 Self::MacAddress(v) => box_to_opt_ref!(v),
1425 _ => panic!("not Value::MacAddress"),
1426 }
1427 }
1428}
1429
1430impl IntoIterator for ValueTuple {
1431 type Item = Value;
1432 type IntoIter = std::vec::IntoIter<Self::Item>;
1433
1434 fn into_iter(self) -> Self::IntoIter {
1435 match self {
1436 ValueTuple::One(v) => vec![v].into_iter(),
1437 ValueTuple::Two(v, w) => vec![v, w].into_iter(),
1438 ValueTuple::Three(u, v, w) => vec![u, v, w].into_iter(),
1439 ValueTuple::Many(vec) => vec.into_iter(),
1440 }
1441 }
1442}
1443
1444impl IntoValueTuple for ValueTuple {
1445 fn into_value_tuple(self) -> ValueTuple {
1446 self
1447 }
1448}
1449
1450impl<V> IntoValueTuple for V
1451where
1452 V: Into<Value>,
1453{
1454 fn into_value_tuple(self) -> ValueTuple {
1455 ValueTuple::One(self.into())
1456 }
1457}
1458
1459impl<V, W> IntoValueTuple for (V, W)
1460where
1461 V: Into<Value>,
1462 W: Into<Value>,
1463{
1464 fn into_value_tuple(self) -> ValueTuple {
1465 ValueTuple::Two(self.0.into(), self.1.into())
1466 }
1467}
1468
1469impl<U, V, W> IntoValueTuple for (U, V, W)
1470where
1471 U: Into<Value>,
1472 V: Into<Value>,
1473 W: Into<Value>,
1474{
1475 fn into_value_tuple(self) -> ValueTuple {
1476 ValueTuple::Three(self.0.into(), self.1.into(), self.2.into())
1477 }
1478}
1479
1480macro_rules! impl_into_value_tuple {
1481 ( $($idx:tt : $T:ident),+ $(,)? ) => {
1482 impl< $($T),+ > IntoValueTuple for ( $($T),+ )
1483 where
1484 $($T: Into<Value>),+
1485 {
1486 fn into_value_tuple(self) -> ValueTuple {
1487 ValueTuple::Many(vec![
1488 $(self.$idx.into()),+
1489 ])
1490 }
1491 }
1492 };
1493}
1494
1495#[rustfmt::skip]
1496mod impl_into_value_tuple {
1497 use super::*;
1498
1499 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3);
1500 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3, 4:T4);
1501 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3, 4:T4, 5:T5);
1502 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3, 4:T4, 5:T5, 6:T6);
1503 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3, 4:T4, 5:T5, 6:T6, 7:T7);
1504 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3, 4:T4, 5:T5, 6:T6, 7:T7, 8:T8);
1505 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3, 4:T4, 5:T5, 6:T6, 7:T7, 8:T8, 9:T9);
1506 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3, 4:T4, 5:T5, 6:T6, 7:T7, 8:T8, 9:T9, 10:T10);
1507 impl_into_value_tuple!(0:T0, 1:T1, 2:T2, 3:T3, 4:T4, 5:T5, 6:T6, 7:T7, 8:T8, 9:T9, 10:T10, 11:T11);
1508}
1509
1510impl<V> FromValueTuple for V
1511where
1512 V: Into<Value> + ValueType,
1513{
1514 fn from_value_tuple<I>(i: I) -> Self
1515 where
1516 I: IntoValueTuple,
1517 {
1518 match i.into_value_tuple() {
1519 ValueTuple::One(u) => u.unwrap(),
1520 _ => panic!("not ValueTuple::One"),
1521 }
1522 }
1523}
1524
1525impl<V, W> FromValueTuple for (V, W)
1526where
1527 V: Into<Value> + ValueType,
1528 W: Into<Value> + ValueType,
1529{
1530 fn from_value_tuple<I>(i: I) -> Self
1531 where
1532 I: IntoValueTuple,
1533 {
1534 match i.into_value_tuple() {
1535 ValueTuple::Two(v, w) => (v.unwrap(), w.unwrap()),
1536 _ => panic!("not ValueTuple::Two"),
1537 }
1538 }
1539}
1540
1541impl<U, V, W> FromValueTuple for (U, V, W)
1542where
1543 U: Into<Value> + ValueType,
1544 V: Into<Value> + ValueType,
1545 W: Into<Value> + ValueType,
1546{
1547 fn from_value_tuple<I>(i: I) -> Self
1548 where
1549 I: IntoValueTuple,
1550 {
1551 match i.into_value_tuple() {
1552 ValueTuple::Three(u, v, w) => (u.unwrap(), v.unwrap(), w.unwrap()),
1553 _ => panic!("not ValueTuple::Three"),
1554 }
1555 }
1556}
1557
1558macro_rules! impl_from_value_tuple {
1559 ( $len:expr, $($T:ident),+ $(,)? ) => {
1560 impl< $($T),+ > FromValueTuple for ( $($T),+ )
1561 where
1562 $($T: Into<Value> + ValueType),+
1563 {
1564 fn from_value_tuple<Z>(i: Z) -> Self
1565 where
1566 Z: IntoValueTuple,
1567 {
1568 match i.into_value_tuple() {
1569 ValueTuple::Many(vec) if vec.len() == $len => {
1570 let mut iter = vec.into_iter();
1571 (
1572 $(<$T as ValueType>::unwrap(iter.next().unwrap())),+
1573 )
1574 }
1575 _ => panic!("not ValueTuple::Many with length of {}", $len),
1576 }
1577 }
1578 }
1579 };
1580}
1581
1582#[rustfmt::skip]
1583mod impl_from_value_tuple {
1584 use super::*;
1585
1586 impl_from_value_tuple!( 4, T0, T1, T2, T3);
1587 impl_from_value_tuple!( 5, T0, T1, T2, T3, T4);
1588 impl_from_value_tuple!( 6, T0, T1, T2, T3, T4, T5);
1589 impl_from_value_tuple!( 7, T0, T1, T2, T3, T4, T5, T6);
1590 impl_from_value_tuple!( 8, T0, T1, T2, T3, T4, T5, T6, T7);
1591 impl_from_value_tuple!( 9, T0, T1, T2, T3, T4, T5, T6, T7, T8);
1592 impl_from_value_tuple!(10, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
1593 impl_from_value_tuple!(11, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
1594 impl_from_value_tuple!(12, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
1595}
1596
1597#[allow(clippy::many_single_char_names)]
1599#[cfg(feature = "with-json")]
1600#[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
1601pub fn sea_value_to_json_value(value: &Value) -> Json {
1602 match value {
1603 Value::Bool(None)
1604 | Value::TinyInt(None)
1605 | Value::SmallInt(None)
1606 | Value::Int(None)
1607 | Value::BigInt(None)
1608 | Value::TinyUnsigned(None)
1609 | Value::SmallUnsigned(None)
1610 | Value::Unsigned(None)
1611 | Value::BigUnsigned(None)
1612 | Value::Float(None)
1613 | Value::Double(None)
1614 | Value::String(None)
1615 | Value::Char(None)
1616 | Value::Bytes(None)
1617 | Value::Json(None) => Json::Null,
1618 #[cfg(feature = "with-rust_decimal")]
1619 Value::Decimal(None) => Json::Null,
1620 #[cfg(feature = "with-bigdecimal")]
1621 Value::BigDecimal(None) => Json::Null,
1622 #[cfg(feature = "with-uuid")]
1623 Value::Uuid(None) => Json::Null,
1624 #[cfg(feature = "postgres-array")]
1625 Value::Array(_, None) => Json::Null,
1626 #[cfg(feature = "postgres-vector")]
1627 Value::Vector(None) => Json::Null,
1628 #[cfg(feature = "with-ipnetwork")]
1629 Value::IpNetwork(None) => Json::Null,
1630 #[cfg(feature = "with-mac_address")]
1631 Value::MacAddress(None) => Json::Null,
1632 Value::Bool(Some(b)) => Json::Bool(*b),
1633 Value::TinyInt(Some(v)) => (*v).into(),
1634 Value::SmallInt(Some(v)) => (*v).into(),
1635 Value::Int(Some(v)) => (*v).into(),
1636 Value::BigInt(Some(v)) => (*v).into(),
1637 Value::TinyUnsigned(Some(v)) => (*v).into(),
1638 Value::SmallUnsigned(Some(v)) => (*v).into(),
1639 Value::Unsigned(Some(v)) => (*v).into(),
1640 Value::BigUnsigned(Some(v)) => (*v).into(),
1641 Value::Float(Some(v)) => (*v).into(),
1642 Value::Double(Some(v)) => (*v).into(),
1643 Value::String(Some(s)) => Json::String(s.as_ref().clone()),
1644 Value::Char(Some(v)) => Json::String(v.to_string()),
1645 Value::Bytes(Some(s)) => Json::String(from_utf8(s).unwrap().to_string()),
1646 Value::Json(Some(v)) => v.as_ref().clone(),
1647 #[cfg(feature = "with-chrono")]
1648 Value::ChronoDate(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1649 #[cfg(feature = "with-chrono")]
1650 Value::ChronoTime(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1651 #[cfg(feature = "with-chrono")]
1652 Value::ChronoDateTime(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1653 #[cfg(feature = "with-chrono")]
1654 Value::ChronoDateTimeWithTimeZone(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1655 #[cfg(feature = "with-chrono")]
1656 Value::ChronoDateTimeUtc(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1657 #[cfg(feature = "with-chrono")]
1658 Value::ChronoDateTimeLocal(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1659 #[cfg(feature = "with-time")]
1660 Value::TimeDate(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1661 #[cfg(feature = "with-time")]
1662 Value::TimeTime(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1663 #[cfg(feature = "with-time")]
1664 Value::TimeDateTime(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1665 #[cfg(feature = "with-time")]
1666 Value::TimeDateTimeWithTimeZone(_) => CommonSqlQueryBuilder.value_to_string(value).into(),
1667 #[cfg(feature = "with-rust_decimal")]
1668 Value::Decimal(Some(v)) => {
1669 use rust_decimal::prelude::ToPrimitive;
1670 v.as_ref().to_f64().unwrap().into()
1671 }
1672 #[cfg(feature = "with-bigdecimal")]
1673 Value::BigDecimal(Some(v)) => {
1674 use bigdecimal::ToPrimitive;
1675 v.as_ref().to_f64().unwrap().into()
1676 }
1677 #[cfg(feature = "with-uuid")]
1678 Value::Uuid(Some(v)) => Json::String(v.to_string()),
1679 #[cfg(feature = "postgres-array")]
1680 Value::Array(_, Some(v)) => {
1681 Json::Array(v.as_ref().iter().map(sea_value_to_json_value).collect())
1682 }
1683 #[cfg(feature = "postgres-vector")]
1684 Value::Vector(Some(v)) => Json::Array(v.as_slice().iter().map(|&v| v.into()).collect()),
1685 #[cfg(feature = "with-ipnetwork")]
1686 Value::IpNetwork(Some(_)) => CommonSqlQueryBuilder.value_to_string(value).into(),
1687 #[cfg(feature = "with-mac_address")]
1688 Value::MacAddress(Some(_)) => CommonSqlQueryBuilder.value_to_string(value).into(),
1689 }
1690}
1691
1692impl Values {
1693 pub fn iter(&self) -> impl Iterator<Item = &Value> {
1694 self.0.iter()
1695 }
1696}
1697
1698impl IntoIterator for Values {
1699 type Item = Value;
1700 type IntoIter = std::vec::IntoIter<Self::Item>;
1701
1702 fn into_iter(self) -> Self::IntoIter {
1703 self.0.into_iter()
1704 }
1705}
1706
1707#[cfg(test)]
1708mod tests {
1709 use super::*;
1710 use pretty_assertions::assert_eq;
1711
1712 #[test]
1713 fn test_value() {
1714 macro_rules! test_value {
1715 ( $type: ty, $val: literal ) => {
1716 let val: $type = $val;
1717 let v: Value = val.into();
1718 let out: $type = v.unwrap();
1719 assert_eq!(out, val);
1720 };
1721 }
1722
1723 test_value!(u8, 255);
1724 test_value!(u16, 65535);
1725 test_value!(i8, 127);
1726 test_value!(i16, 32767);
1727 test_value!(i32, 1073741824);
1728 test_value!(i64, 8589934592);
1729 }
1730
1731 #[test]
1732 fn test_option_value() {
1733 macro_rules! test_some_value {
1734 ( $type: ty, $val: literal ) => {
1735 let val: Option<$type> = Some($val);
1736 let v: Value = val.into();
1737 let out: $type = v.unwrap();
1738 assert_eq!(out, val.unwrap());
1739 };
1740 }
1741
1742 macro_rules! test_none {
1743 ( $type: ty, $name: ident ) => {
1744 let val: Option<$type> = None;
1745 let v: Value = val.into();
1746 assert_eq!(v, Value::$name(None));
1747 };
1748 }
1749
1750 test_some_value!(u8, 255);
1751 test_some_value!(u16, 65535);
1752 test_some_value!(i8, 127);
1753 test_some_value!(i16, 32767);
1754 test_some_value!(i32, 1073741824);
1755 test_some_value!(i64, 8589934592);
1756
1757 test_none!(u8, TinyUnsigned);
1758 test_none!(u16, SmallUnsigned);
1759 test_none!(i8, TinyInt);
1760 test_none!(i16, SmallInt);
1761 test_none!(i32, Int);
1762 test_none!(i64, BigInt);
1763 }
1764
1765 #[test]
1766 fn test_cow_value() {
1767 let val: Cow<str> = "hello".into();
1768 let val2 = val.clone();
1769 let v: Value = val.into();
1770 let out: Cow<str> = v.unwrap();
1771 assert_eq!(out, val2);
1772 }
1773
1774 #[test]
1775 fn test_box_value() {
1776 let val: String = "hello".to_owned();
1777 let v: Value = val.clone().into();
1778 let out: String = v.unwrap();
1779 assert_eq!(out, val);
1780 }
1781
1782 #[test]
1783 fn test_value_tuple() {
1784 assert_eq!(
1785 1i32.into_value_tuple(),
1786 ValueTuple::One(Value::Int(Some(1)))
1787 );
1788 assert_eq!(
1789 "b".into_value_tuple(),
1790 ValueTuple::One(Value::String(Some(Box::new("b".to_owned()))))
1791 );
1792 assert_eq!(
1793 (1i32, "b").into_value_tuple(),
1794 ValueTuple::Two(
1795 Value::Int(Some(1)),
1796 Value::String(Some(Box::new("b".to_owned())))
1797 )
1798 );
1799 assert_eq!(
1800 (1i32, 2.4f64, "b").into_value_tuple(),
1801 ValueTuple::Three(
1802 Value::Int(Some(1)),
1803 Value::Double(Some(2.4)),
1804 Value::String(Some(Box::new("b".to_owned())))
1805 )
1806 );
1807 assert_eq!(
1808 (1i32, 2.4f64, "b", 123u8).into_value_tuple(),
1809 ValueTuple::Many(vec![
1810 Value::Int(Some(1)),
1811 Value::Double(Some(2.4)),
1812 Value::String(Some(Box::new("b".to_owned()))),
1813 Value::TinyUnsigned(Some(123))
1814 ])
1815 );
1816 assert_eq!(
1817 (1i32, 2.4f64, "b", 123u8, 456u16).into_value_tuple(),
1818 ValueTuple::Many(vec![
1819 Value::Int(Some(1)),
1820 Value::Double(Some(2.4)),
1821 Value::String(Some(Box::new("b".to_owned()))),
1822 Value::TinyUnsigned(Some(123)),
1823 Value::SmallUnsigned(Some(456))
1824 ])
1825 );
1826 assert_eq!(
1827 (1i32, 2.4f64, "b", 123u8, 456u16, 789u32).into_value_tuple(),
1828 ValueTuple::Many(vec![
1829 Value::Int(Some(1)),
1830 Value::Double(Some(2.4)),
1831 Value::String(Some(Box::new("b".to_owned()))),
1832 Value::TinyUnsigned(Some(123)),
1833 Value::SmallUnsigned(Some(456)),
1834 Value::Unsigned(Some(789))
1835 ])
1836 );
1837 }
1838
1839 #[test]
1840 #[allow(clippy::clone_on_copy)]
1841 fn test_from_value_tuple() {
1842 let mut val = 1i32;
1843 let original = val.clone();
1844 val = FromValueTuple::from_value_tuple(val);
1845 assert_eq!(val, original);
1846
1847 let mut val = "b".to_owned();
1848 let original = val.clone();
1849 val = FromValueTuple::from_value_tuple(val);
1850 assert_eq!(val, original);
1851
1852 let mut val = (1i32, "b".to_owned());
1853 let original = val.clone();
1854 val = FromValueTuple::from_value_tuple(val);
1855 assert_eq!(val, original);
1856
1857 let mut val = (1i32, 2.4f64, "b".to_owned());
1858 let original = val.clone();
1859 val = FromValueTuple::from_value_tuple(val);
1860 assert_eq!(val, original);
1861
1862 let mut val = (1i32, 2.4f64, "b".to_owned(), 123u8);
1863 let original = val.clone();
1864 val = FromValueTuple::from_value_tuple(val);
1865 assert_eq!(val, original);
1866
1867 let mut val = (1i32, 2.4f64, "b".to_owned(), 123u8, 456u16);
1868 let original = val.clone();
1869 val = FromValueTuple::from_value_tuple(val);
1870 assert_eq!(val, original);
1871
1872 let mut val = (1i32, 2.4f64, "b".to_owned(), 123u8, 456u16, 789u32);
1873 let original = val.clone();
1874 val = FromValueTuple::from_value_tuple(val);
1875 assert_eq!(val, original);
1876 }
1877
1878 #[test]
1879 fn test_value_tuple_iter() {
1880 let mut iter = (1i32).into_value_tuple().into_iter();
1881 assert_eq!(iter.next().unwrap(), Value::Int(Some(1)));
1882 assert_eq!(iter.next(), None);
1883
1884 let mut iter = (1i32, 2.4f64).into_value_tuple().into_iter();
1885 assert_eq!(iter.next().unwrap(), Value::Int(Some(1)));
1886 assert_eq!(iter.next().unwrap(), Value::Double(Some(2.4)));
1887 assert_eq!(iter.next(), None);
1888
1889 let mut iter = (1i32, 2.4f64, "b").into_value_tuple().into_iter();
1890 assert_eq!(iter.next().unwrap(), Value::Int(Some(1)));
1891 assert_eq!(iter.next().unwrap(), Value::Double(Some(2.4)));
1892 assert_eq!(
1893 iter.next().unwrap(),
1894 Value::String(Some(Box::new("b".to_owned())))
1895 );
1896 assert_eq!(iter.next(), None);
1897
1898 let mut iter = (1i32, 2.4f64, "b", 123u8).into_value_tuple().into_iter();
1899 assert_eq!(iter.next().unwrap(), Value::Int(Some(1)));
1900 assert_eq!(iter.next().unwrap(), Value::Double(Some(2.4)));
1901 assert_eq!(
1902 iter.next().unwrap(),
1903 Value::String(Some(Box::new("b".to_owned())))
1904 );
1905 assert_eq!(iter.next().unwrap(), Value::TinyUnsigned(Some(123)));
1906 assert_eq!(iter.next(), None);
1907
1908 let mut iter = (1i32, 2.4f64, "b", 123u8, 456u16)
1909 .into_value_tuple()
1910 .into_iter();
1911 assert_eq!(iter.next().unwrap(), Value::Int(Some(1)));
1912 assert_eq!(iter.next().unwrap(), Value::Double(Some(2.4)));
1913 assert_eq!(
1914 iter.next().unwrap(),
1915 Value::String(Some(Box::new("b".to_owned())))
1916 );
1917 assert_eq!(iter.next().unwrap(), Value::TinyUnsigned(Some(123)));
1918 assert_eq!(iter.next().unwrap(), Value::SmallUnsigned(Some(456)));
1919 assert_eq!(iter.next(), None);
1920
1921 let mut iter = (1i32, 2.4f64, "b", 123u8, 456u16, 789u32)
1922 .into_value_tuple()
1923 .into_iter();
1924 assert_eq!(iter.next().unwrap(), Value::Int(Some(1)));
1925 assert_eq!(iter.next().unwrap(), Value::Double(Some(2.4)));
1926 assert_eq!(
1927 iter.next().unwrap(),
1928 Value::String(Some(Box::new("b".to_owned())))
1929 );
1930 assert_eq!(iter.next().unwrap(), Value::TinyUnsigned(Some(123)));
1931 assert_eq!(iter.next().unwrap(), Value::SmallUnsigned(Some(456)));
1932 assert_eq!(iter.next().unwrap(), Value::Unsigned(Some(789)));
1933 assert_eq!(iter.next(), None);
1934 }
1935
1936 #[test]
1937 #[cfg(feature = "with-json")]
1938 fn test_json_value() {
1939 let json = serde_json::json! {{
1940 "a": 25.0,
1941 "b": "hello",
1942 }};
1943 let value: Value = json.clone().into();
1944 let out: Json = value.unwrap();
1945 assert_eq!(out, json);
1946 }
1947
1948 #[test]
1949 #[cfg(feature = "with-chrono")]
1950 fn test_chrono_value() {
1951 let timestamp = NaiveDate::from_ymd_opt(2020, 1, 1)
1952 .unwrap()
1953 .and_hms_opt(2, 2, 2)
1954 .unwrap();
1955 let value: Value = timestamp.into();
1956 let out: NaiveDateTime = value.unwrap();
1957 assert_eq!(out, timestamp);
1958 }
1959
1960 #[test]
1961 #[cfg(feature = "with-chrono")]
1962 fn test_chrono_utc_value() {
1963 let timestamp = DateTime::<Utc>::from_naive_utc_and_offset(
1964 NaiveDate::from_ymd_opt(2022, 1, 2)
1965 .unwrap()
1966 .and_hms_opt(3, 4, 5)
1967 .unwrap(),
1968 Utc,
1969 );
1970 let value: Value = timestamp.into();
1971 let out: DateTime<Utc> = value.unwrap();
1972 assert_eq!(out, timestamp);
1973 }
1974
1975 #[test]
1976 #[cfg(feature = "with-chrono")]
1977 fn test_chrono_local_value() {
1978 let timestamp_utc = DateTime::<Utc>::from_naive_utc_and_offset(
1979 NaiveDate::from_ymd_opt(2022, 1, 2)
1980 .unwrap()
1981 .and_hms_opt(3, 4, 5)
1982 .unwrap(),
1983 Utc,
1984 );
1985 let timestamp_local: DateTime<Local> = timestamp_utc.into();
1986 let value: Value = timestamp_local.into();
1987 let out: DateTime<Local> = value.unwrap();
1988 assert_eq!(out, timestamp_local);
1989 }
1990
1991 #[test]
1992 #[cfg(feature = "with-chrono")]
1993 fn test_chrono_timezone_value() {
1994 let timestamp = DateTime::parse_from_rfc3339("2020-01-01T02:02:02+08:00").unwrap();
1995 let value: Value = timestamp.into();
1996 let out: DateTime<FixedOffset> = value.unwrap();
1997 assert_eq!(out, timestamp);
1998 }
1999
2000 #[test]
2001 #[cfg(feature = "with-chrono")]
2002 fn test_chrono_query() {
2003 use crate::*;
2004
2005 let string = "2020-01-01T02:02:02+08:00";
2006 let timestamp = DateTime::parse_from_rfc3339(string).unwrap();
2007
2008 let query = Query::select().expr(timestamp).to_owned();
2009
2010 let formatted = "2020-01-01 02:02:02.000000 +08:00";
2011
2012 assert_eq!(
2013 query.to_string(MysqlQueryBuilder),
2014 format!("SELECT '{formatted}'")
2015 );
2016 assert_eq!(
2017 query.to_string(PostgresQueryBuilder),
2018 format!("SELECT '{formatted}'")
2019 );
2020 assert_eq!(
2021 query.to_string(SqliteQueryBuilder),
2022 format!("SELECT '{formatted}'")
2023 );
2024 }
2025
2026 #[test]
2027 #[cfg(feature = "with-time")]
2028 fn test_time_value() {
2029 use time::macros::{date, time};
2030 let timestamp = date!(2020 - 01 - 01).with_time(time!(2:2:2));
2031 let value: Value = timestamp.into();
2032 let out: PrimitiveDateTime = value.unwrap();
2033 assert_eq!(out, timestamp);
2034 }
2035
2036 #[test]
2037 #[cfg(feature = "with-time")]
2038 fn test_time_utc_value() {
2039 use time::macros::{date, time};
2040 let timestamp = date!(2022 - 01 - 02).with_time(time!(3:04:05)).assume_utc();
2041 let value: Value = timestamp.into();
2042 let out: OffsetDateTime = value.unwrap();
2043 assert_eq!(out, timestamp);
2044 }
2045
2046 #[test]
2047 #[cfg(feature = "with-time")]
2048 fn test_time_local_value() {
2049 use time::macros::{date, offset, time};
2050 let timestamp_utc = date!(2022 - 01 - 02).with_time(time!(3:04:05)).assume_utc();
2051 let timestamp_local: OffsetDateTime = timestamp_utc.to_offset(offset!(+3));
2052 let value: Value = timestamp_local.into();
2053 let out: OffsetDateTime = value.unwrap();
2054 assert_eq!(out, timestamp_local);
2055 }
2056
2057 #[test]
2058 #[cfg(feature = "with-time")]
2059 fn test_time_timezone_value() {
2060 use time::macros::{date, offset, time};
2061 let timestamp = date!(2022 - 01 - 02)
2062 .with_time(time!(3:04:05))
2063 .assume_offset(offset!(+8));
2064 let value: Value = timestamp.into();
2065 let out: OffsetDateTime = value.unwrap();
2066 assert_eq!(out, timestamp);
2067 }
2068
2069 #[test]
2070 #[cfg(feature = "with-time")]
2071 fn test_time_query() {
2072 use crate::*;
2073 use time::macros::datetime;
2074
2075 let timestamp = datetime!(2020-01-01 02:02:02 +8);
2076 let query = Query::select().expr(timestamp).to_owned();
2077 let formatted = "2020-01-01 02:02:02.000000 +08:00";
2078
2079 assert_eq!(
2080 query.to_string(MysqlQueryBuilder),
2081 format!("SELECT '{formatted}'")
2082 );
2083 assert_eq!(
2084 query.to_string(PostgresQueryBuilder),
2085 format!("SELECT '{formatted}'")
2086 );
2087 assert_eq!(
2088 query.to_string(SqliteQueryBuilder),
2089 format!("SELECT '{formatted}'")
2090 );
2091 }
2092
2093 #[test]
2094 #[cfg(feature = "with-uuid")]
2095 fn test_uuid_value() {
2096 let uuid = Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8").unwrap();
2097 let value: Value = uuid.into();
2098 let out: Uuid = value.unwrap();
2099 assert_eq!(out, uuid);
2100
2101 let uuid_braced = uuid.braced();
2102 let value: Value = uuid_braced.into();
2103 let out: Uuid = value.unwrap();
2104 assert_eq!(out, uuid);
2105
2106 let uuid_hyphenated = uuid.hyphenated();
2107 let value: Value = uuid_hyphenated.into();
2108 let out: Uuid = value.unwrap();
2109 assert_eq!(out, uuid);
2110
2111 let uuid_simple = uuid.simple();
2112 let value: Value = uuid_simple.into();
2113 let out: Uuid = value.unwrap();
2114 assert_eq!(out, uuid);
2115
2116 let uuid_urn = uuid.urn();
2117 let value: Value = uuid_urn.into();
2118 let out: Uuid = value.unwrap();
2119 assert_eq!(out, uuid);
2120 }
2121
2122 #[test]
2123 #[cfg(feature = "with-rust_decimal")]
2124 fn test_decimal_value() {
2125 use std::str::FromStr;
2126
2127 let num = "2.02";
2128 let val = Decimal::from_str(num).unwrap();
2129 let v: Value = val.into();
2130 let out: Decimal = v.unwrap();
2131 assert_eq!(out.to_string(), num);
2132 }
2133
2134 #[test]
2135 #[cfg(feature = "postgres-array")]
2136 fn test_array_value() {
2137 let array = vec![1, 2, 3, 4, 5];
2138 let v: Value = array.into();
2139 let out: Vec<i32> = v.unwrap();
2140 assert_eq!(out, vec![1, 2, 3, 4, 5]);
2141 }
2142
2143 #[test]
2144 #[cfg(feature = "postgres-array")]
2145 fn test_option_array_value() {
2146 let v: Value = Value::Array(ArrayType::Int, None);
2147 let out: Option<Vec<i32>> = v.unwrap();
2148 assert_eq!(out, None);
2149 }
2150}
2151
2152#[cfg(feature = "hashable-value")]
2153mod hashable_value {
2154 use super::*;
2155 use ordered_float::OrderedFloat;
2156 use std::{
2157 hash::{Hash, Hasher},
2158 mem,
2159 };
2160
2161 impl PartialEq for Value {
2162 fn eq(&self, other: &Self) -> bool {
2163 match (self, other) {
2164 (Self::Bool(l), Self::Bool(r)) => l == r,
2165 (Self::TinyInt(l), Self::TinyInt(r)) => l == r,
2166 (Self::SmallInt(l), Self::SmallInt(r)) => l == r,
2167 (Self::Int(l), Self::Int(r)) => l == r,
2168 (Self::BigInt(l), Self::BigInt(r)) => l == r,
2169 (Self::TinyUnsigned(l), Self::TinyUnsigned(r)) => l == r,
2170 (Self::SmallUnsigned(l), Self::SmallUnsigned(r)) => l == r,
2171 (Self::Unsigned(l), Self::Unsigned(r)) => l == r,
2172 (Self::BigUnsigned(l), Self::BigUnsigned(r)) => l == r,
2173 (Self::Float(l), Self::Float(r)) => cmp_f32(l, r),
2174 (Self::Double(l), Self::Double(r)) => cmp_f64(l, r),
2175 (Self::String(l), Self::String(r)) => l == r,
2176 (Self::Char(l), Self::Char(r)) => l == r,
2177 (Self::Bytes(l), Self::Bytes(r)) => l == r,
2178
2179 #[cfg(feature = "with-json")]
2180 (Self::Json(l), Self::Json(r)) => cmp_json(l, r),
2181
2182 #[cfg(feature = "with-chrono")]
2183 (Self::ChronoDate(l), Self::ChronoDate(r)) => l == r,
2184 #[cfg(feature = "with-chrono")]
2185 (Self::ChronoTime(l), Self::ChronoTime(r)) => l == r,
2186 #[cfg(feature = "with-chrono")]
2187 (Self::ChronoDateTime(l), Self::ChronoDateTime(r)) => l == r,
2188 #[cfg(feature = "with-chrono")]
2189 (Self::ChronoDateTimeUtc(l), Self::ChronoDateTimeUtc(r)) => l == r,
2190 #[cfg(feature = "with-chrono")]
2191 (Self::ChronoDateTimeLocal(l), Self::ChronoDateTimeLocal(r)) => l == r,
2192 #[cfg(feature = "with-chrono")]
2193 (Self::ChronoDateTimeWithTimeZone(l), Self::ChronoDateTimeWithTimeZone(r)) => {
2194 l == r
2195 }
2196
2197 #[cfg(feature = "with-time")]
2198 (Self::TimeDate(l), Self::TimeDate(r)) => l == r,
2199 #[cfg(feature = "with-time")]
2200 (Self::TimeTime(l), Self::TimeTime(r)) => l == r,
2201 #[cfg(feature = "with-time")]
2202 (Self::TimeDateTime(l), Self::TimeDateTime(r)) => l == r,
2203 #[cfg(feature = "with-time")]
2204 (Self::TimeDateTimeWithTimeZone(l), Self::TimeDateTimeWithTimeZone(r)) => l == r,
2205
2206 #[cfg(feature = "with-uuid")]
2207 (Self::Uuid(l), Self::Uuid(r)) => l == r,
2208
2209 #[cfg(feature = "with-rust_decimal")]
2210 (Self::Decimal(l), Self::Decimal(r)) => l == r,
2211
2212 #[cfg(feature = "with-bigdecimal")]
2213 (Self::BigDecimal(l), Self::BigDecimal(r)) => l == r,
2214
2215 #[cfg(feature = "postgres-array")]
2216 (Self::Array(ty_l, values_l), Self::Array(ty_r, values_r)) => {
2217 ty_l == ty_r && values_l == values_r
2218 }
2219
2220 #[cfg(feature = "postgres-vector")]
2221 (Self::Vector(l), Self::Vector(r)) => cmp_vector(l, r),
2222
2223 #[cfg(feature = "with-ipnetwork")]
2224 (Self::IpNetwork(l), Self::IpNetwork(r)) => l == r,
2225
2226 #[cfg(feature = "with-mac_address")]
2227 (Self::MacAddress(l), Self::MacAddress(r)) => l == r,
2228
2229 _ => false,
2230 }
2231 }
2232 }
2233
2234 impl Eq for Value {}
2235
2236 impl Hash for Value {
2237 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2238 mem::discriminant(self).hash(state);
2239 match self {
2240 Value::Bool(v) => v.hash(state),
2241 Value::TinyInt(v) => v.hash(state),
2242 Value::SmallInt(v) => v.hash(state),
2243 Value::Int(v) => v.hash(state),
2244 Value::BigInt(v) => v.hash(state),
2245 Value::TinyUnsigned(v) => v.hash(state),
2246 Value::SmallUnsigned(v) => v.hash(state),
2247 Value::Unsigned(v) => v.hash(state),
2248 Value::BigUnsigned(v) => v.hash(state),
2249 Value::Float(v) => hash_f32(v, state),
2250 Value::Double(v) => hash_f64(v, state),
2251 Value::String(v) => v.hash(state),
2252 Value::Char(v) => v.hash(state),
2253 Value::Bytes(v) => v.hash(state),
2254
2255 #[cfg(feature = "with-json")]
2256 Value::Json(value) => hash_json(value, state),
2257
2258 #[cfg(feature = "with-chrono")]
2259 Value::ChronoDate(naive_date) => naive_date.hash(state),
2260 #[cfg(feature = "with-chrono")]
2261 Value::ChronoTime(naive_time) => naive_time.hash(state),
2262 #[cfg(feature = "with-chrono")]
2263 Value::ChronoDateTime(naive_date_time) => naive_date_time.hash(state),
2264 #[cfg(feature = "with-chrono")]
2265 Value::ChronoDateTimeUtc(date_time) => date_time.hash(state),
2266 #[cfg(feature = "with-chrono")]
2267 Value::ChronoDateTimeLocal(date_time) => date_time.hash(state),
2268 #[cfg(feature = "with-chrono")]
2269 Value::ChronoDateTimeWithTimeZone(date_time) => date_time.hash(state),
2270
2271 #[cfg(feature = "with-time")]
2272 Value::TimeDate(date) => date.hash(state),
2273 #[cfg(feature = "with-time")]
2274 Value::TimeTime(time) => time.hash(state),
2275 #[cfg(feature = "with-time")]
2276 Value::TimeDateTime(primitive_date_time) => primitive_date_time.hash(state),
2277 #[cfg(feature = "with-time")]
2278 Value::TimeDateTimeWithTimeZone(offset_date_time) => offset_date_time.hash(state),
2279
2280 #[cfg(feature = "with-uuid")]
2281 Value::Uuid(uuid) => uuid.hash(state),
2282
2283 #[cfg(feature = "with-rust_decimal")]
2284 Value::Decimal(decimal) => decimal.hash(state),
2285
2286 #[cfg(feature = "with-bigdecimal")]
2287 Value::BigDecimal(big_decimal) => big_decimal.hash(state),
2288
2289 #[cfg(feature = "postgres-array")]
2290 Value::Array(array_type, vec) => {
2291 array_type.hash(state);
2292 vec.hash(state);
2293 }
2294
2295 #[cfg(feature = "postgres-vector")]
2296 Value::Vector(vector) => hash_vector(vector, state),
2297
2298 #[cfg(feature = "with-ipnetwork")]
2299 Value::IpNetwork(ip_network) => ip_network.hash(state),
2300
2301 #[cfg(feature = "with-mac_address")]
2302 Value::MacAddress(mac_address) => mac_address.hash(state),
2303 }
2304 }
2305 }
2306
2307 fn hash_f32<H: Hasher>(v: &Option<f32>, state: &mut H) {
2308 match v {
2309 Some(v) => OrderedFloat(*v).hash(state),
2310 None => "null".hash(state),
2311 }
2312 }
2313
2314 fn hash_f64<H: Hasher>(v: &Option<f64>, state: &mut H) {
2315 match v {
2316 Some(v) => OrderedFloat(*v).hash(state),
2317 None => "null".hash(state),
2318 }
2319 }
2320
2321 fn cmp_f32(l: &Option<f32>, r: &Option<f32>) -> bool {
2322 match (l, r) {
2323 (Some(l), Some(r)) => OrderedFloat(*l).eq(&OrderedFloat(*r)),
2324 (None, None) => true,
2325 _ => false,
2326 }
2327 }
2328
2329 fn cmp_f64(l: &Option<f64>, r: &Option<f64>) -> bool {
2330 match (l, r) {
2331 (Some(l), Some(r)) => OrderedFloat(*l).eq(&OrderedFloat(*r)),
2332 (None, None) => true,
2333 _ => false,
2334 }
2335 }
2336
2337 #[cfg(feature = "with-json")]
2338 fn hash_json<H: Hasher>(v: &Option<Box<Json>>, state: &mut H) {
2339 match v {
2340 Some(v) => serde_json::to_string(v).unwrap().hash(state),
2341 None => "null".hash(state),
2342 }
2343 }
2344
2345 #[cfg(feature = "with-json")]
2346 fn cmp_json(l: &Option<Box<Json>>, r: &Option<Box<Json>>) -> bool {
2347 match (l, r) {
2348 (Some(l), Some(r)) => serde_json::to_string(l)
2349 .unwrap()
2350 .eq(&serde_json::to_string(r).unwrap()),
2351 (None, None) => true,
2352 _ => false,
2353 }
2354 }
2355
2356 #[cfg(feature = "postgres-vector")]
2357 fn hash_vector<H: Hasher>(v: &Option<Box<pgvector::Vector>>, state: &mut H) {
2358 match v {
2359 Some(v) => {
2360 for &value in v.as_slice().iter() {
2361 hash_f32(&Some(value), state);
2362 }
2363 }
2364 None => "null".hash(state),
2365 }
2366 }
2367
2368 #[cfg(feature = "postgres-vector")]
2369 fn cmp_vector(l: &Option<Box<pgvector::Vector>>, r: &Option<Box<pgvector::Vector>>) -> bool {
2370 match (l, r) {
2371 (Some(l), Some(r)) => {
2372 let (l, r) = (l.as_slice(), r.as_slice());
2373 if l.len() != r.len() {
2374 return false;
2375 }
2376 for (l, r) in l.iter().zip(r.iter()) {
2377 if !cmp_f32(&Some(*l), &Some(*r)) {
2378 return false;
2379 }
2380 }
2381 true
2382 }
2383 (None, None) => true,
2384 _ => false,
2385 }
2386 }
2387
2388 #[test]
2389 fn test_hash_value_0() {
2390 let hash_set: std::collections::HashSet<Value> = [
2391 Value::Int(None),
2392 Value::Int(None),
2393 Value::BigInt(None),
2394 Value::BigInt(None),
2395 Value::Float(None),
2396 Value::Float(None), Value::Float(Some(std::f32::NAN)), Value::Float(Some(std::f32::NAN)),
2399 Value::Double(None),
2400 Value::Double(None),
2401 Value::Double(Some(std::f64::NAN)),
2402 Value::Double(Some(std::f64::NAN)),
2403 ]
2404 .into_iter()
2405 .collect();
2406
2407 let unique: std::collections::HashSet<Value> = [
2408 Value::Int(None),
2409 Value::BigInt(None),
2410 Value::Float(None),
2411 Value::Double(None),
2412 Value::Float(Some(std::f32::NAN)),
2413 Value::Double(Some(std::f64::NAN)),
2414 ]
2415 .into_iter()
2416 .collect();
2417
2418 assert_eq!(hash_set, unique);
2419 }
2420
2421 #[test]
2422 fn test_hash_value_1() {
2423 let hash_set: std::collections::HashSet<Value> = [
2424 Value::Int(None),
2425 Value::Int(Some(1)),
2426 Value::Int(Some(1)),
2427 Value::BigInt(Some(2)),
2428 Value::BigInt(Some(2)),
2429 Value::Float(Some(3.0)),
2430 Value::Float(Some(3.0)),
2431 Value::Double(Some(3.0)),
2432 Value::Double(Some(3.0)),
2433 Value::BigInt(Some(5)),
2434 ]
2435 .into_iter()
2436 .collect();
2437
2438 let unique: std::collections::HashSet<Value> = [
2439 Value::BigInt(Some(5)),
2440 Value::Double(Some(3.0)),
2441 Value::Float(Some(3.0)),
2442 Value::BigInt(Some(2)),
2443 Value::Int(Some(1)),
2444 Value::Int(None),
2445 ]
2446 .into_iter()
2447 .collect();
2448
2449 assert_eq!(hash_set, unique);
2450 }
2451
2452 #[cfg(feature = "postgres-array")]
2453 #[test]
2454 fn test_hash_value_array() {
2455 assert_eq!(
2456 Into::<Value>::into(vec![0i32, 1, 2]),
2457 Value::Array(
2458 ArrayType::Int,
2459 Some(Box::new(vec![
2460 Value::Int(Some(0)),
2461 Value::Int(Some(1)),
2462 Value::Int(Some(2))
2463 ]))
2464 )
2465 );
2466
2467 assert_eq!(
2468 Into::<Value>::into(vec![0f32, 1.0, 2.0]),
2469 Value::Array(
2470 ArrayType::Float,
2471 Some(Box::new(vec![
2472 Value::Float(Some(0f32)),
2473 Value::Float(Some(1.0)),
2474 Value::Float(Some(2.0))
2475 ]))
2476 )
2477 );
2478
2479 let hash_set: std::collections::HashSet<Value> = [
2480 Into::<Value>::into(vec![0i32, 1, 2]),
2481 Into::<Value>::into(vec![0i32, 1, 2]),
2482 Into::<Value>::into(vec![0f32, 1.0, 2.0]),
2483 Into::<Value>::into(vec![0f32, 1.0, 2.0]),
2484 Into::<Value>::into(vec![3f32, 2.0, 1.0]),
2485 ]
2486 .into_iter()
2487 .collect();
2488
2489 let unique: std::collections::HashSet<Value> = [
2490 Into::<Value>::into(vec![0i32, 1, 2]),
2491 Into::<Value>::into(vec![0f32, 1.0, 2.0]),
2492 Into::<Value>::into(vec![3f32, 2.0, 1.0]),
2493 ]
2494 .into_iter()
2495 .collect();
2496
2497 assert_eq!(hash_set, unique);
2498 }
2499}