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