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