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