1use std::borrow::Cow;
11use std::cmp::Ordering;
12use std::collections::BTreeMap;
13use std::fmt::{self, Debug};
14use std::hash::Hash;
15use std::iter;
16#[cfg(any(test, feature = "proptest"))]
17use std::ops::Add;
18use std::sync::LazyLock;
19
20use anyhow::bail;
21#[cfg(any(test, feature = "proptest"))]
22use chrono::TimeZone;
23use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};
24use dec::OrderedDecimal;
25use enum_kinds::EnumKind;
26use itertools::Itertools;
27use mz_ore::Overflowing;
28#[cfg(any(test, feature = "proptest"))]
29use mz_ore::cast::CastFrom;
30use mz_ore::str::{StrExt, separated};
31use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
32use ordered_float::OrderedFloat;
33#[cfg(any(test, feature = "proptest"))]
34use proptest::prelude::*;
35#[cfg(any(test, feature = "proptest"))]
36use proptest::strategy::Union;
37use serde::{Deserialize, Serialize};
38use uuid::Uuid;
39
40use crate::adt::array::{Array, ArrayDimension};
41use crate::adt::char::{Char, CharLength};
42use crate::adt::date::Date;
43use crate::adt::interval::Interval;
44use crate::adt::jsonb::{Jsonb, JsonbRef};
45use crate::adt::mz_acl_item::{AclItem, AclMode, MzAclItem};
46use crate::adt::numeric::{Numeric, NumericMaxScale};
47use crate::adt::pg_legacy_name::PgLegacyName;
48use crate::adt::range::Range;
49#[cfg(any(test, feature = "proptest"))]
50use crate::adt::range::{RangeLowerBound, RangeUpperBound};
51use crate::adt::system::{Oid, PgLegacyChar, RegClass, RegProc, RegType};
52use crate::adt::timestamp::{CheckedTimestamp, TimestampError, TimestampPrecision};
53#[cfg(any(test, feature = "proptest"))]
54use crate::adt::timestamp::{HIGH_DATE, LOW_DATE};
55use crate::adt::varchar::{VarChar, VarCharMaxLength};
56use crate::relation::ReprColumnType;
57pub use crate::relation_and_scalar::ProtoScalarType;
58pub use crate::relation_and_scalar::proto_scalar_type::ProtoRecordField;
59use crate::role_id::RoleId;
60use crate::row::DatumNested;
61use crate::{CatalogItemId, ColumnName, DatumList, DatumMap, Row, RowArena, SqlColumnType};
62
63#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, EnumKind)]
83#[enum_kind(DatumKind, derive(Hash))]
84pub enum Datum<'a> {
85 False,
87 True,
89 Int16(i16),
91 Int32(i32),
93 Int64(i64),
95 UInt8(u8),
97 UInt16(u16),
99 UInt32(u32),
101 UInt64(u64),
103 Float32(OrderedFloat<f32>),
105 Float64(OrderedFloat<f64>),
107 Date(Date),
109 Time(NaiveTime),
111 Timestamp(CheckedTimestamp<NaiveDateTime>),
114 TimestampTz(CheckedTimestamp<DateTime<Utc>>),
116 Interval(Interval),
118 Bytes(&'a [u8]),
120 String(&'a str),
122 Array(Array<'a>),
125 List(DatumList<'a>),
129 Map(DatumMap<'a>),
131 Numeric(OrderedDecimal<Numeric>),
134 JsonNull,
139 Uuid(Uuid),
141 MzTimestamp(crate::Timestamp),
142 Range(Range<DatumNested<'a>>),
144 MzAclItem(MzAclItem),
147 AclItem(AclItem),
150 Dummy,
167 Null,
175 }
181
182impl Debug for Datum<'_> {
183 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184 use mz_ore::str::*;
185 match self {
186 Datum::False => write!(f, "False"),
187 Datum::True => write!(f, "True"),
188 Datum::Int16(x) => f.debug_tuple("Int16").field(&redact(x)).finish(),
189 Datum::Int32(x) => f.debug_tuple("Int32").field(&redact(x)).finish(),
190 Datum::Int64(x) => f.debug_tuple("Int64").field(&redact(x)).finish(),
191 Datum::UInt8(x) => f.debug_tuple("UInt8").field(&redact(x)).finish(),
192 Datum::UInt16(x) => f.debug_tuple("UInt16").field(&redact(x)).finish(),
193 Datum::UInt32(x) => f.debug_tuple("UInt32").field(&redact(x)).finish(),
194 Datum::UInt64(x) => f.debug_tuple("UInt64").field(&redact(x)).finish(),
195 Datum::Float32(x) => f.debug_tuple("Float32").field(&redact(x)).finish(),
196 Datum::Float64(x) => f.debug_tuple("Float64").field(&redact(x)).finish(),
197 Datum::Date(x) => f.debug_tuple("Date").field(&redact(x)).finish(),
198 Datum::Time(x) => f.debug_tuple("Time").field(&redact(x)).finish(),
199 Datum::Timestamp(x) => f
200 .debug_tuple("Timestamp")
201 .field(&redact(x.to_naive()))
202 .finish(),
203 Datum::TimestampTz(x) => f
204 .debug_tuple("TimestampTz")
205 .field(&redact(<DateTime<Utc>>::from(*x)))
206 .finish(),
207 Datum::Interval(x) => f.debug_tuple("Interval").field(&redact(x)).finish(),
208 Datum::Bytes(x) => f.debug_tuple("Bytes").field(&redact(x)).finish(),
209 Datum::String(x) => f.debug_tuple("String").field(&redact(x)).finish(),
210 Datum::Array(x) => f.debug_tuple("Array").field(x).finish(),
211 Datum::List(x) => f.debug_tuple("List").field(x).finish(),
212 Datum::Map(x) => f.debug_tuple("Map").field(x).finish(),
213 Datum::Numeric(x) => f.debug_tuple("Numeric").field(&redact(&x.0)).finish(),
214 Datum::JsonNull => f.debug_tuple("JsonNull").finish(),
215 Datum::Uuid(x) => f.debug_tuple("Uuid").field(&redact(x)).finish(),
216 Datum::MzTimestamp(x) => f.debug_tuple("MzTimestamp").field(&redact(x)).finish(),
217 Datum::Range(x) => f.debug_tuple("Range").field(&redact(x)).finish(),
218 Datum::MzAclItem(x) => f.debug_tuple("MzAclItem").field(&redact(x)).finish(),
219 Datum::AclItem(x) => f.debug_tuple("AclItem").field(&redact(x)).finish(),
220 Datum::Dummy => f.debug_tuple("Dummy").finish(),
221 Datum::Null => f.debug_tuple("Null").finish(),
222 }
223 }
224}
225
226impl TryFrom<Datum<'_>> for bool {
227 type Error = ();
228
229 #[inline]
230 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
231 match from {
232 Datum::False => Ok(false),
233 Datum::True => Ok(true),
234 _ => Err(()),
235 }
236 }
237}
238
239impl TryFrom<Datum<'_>> for Option<bool> {
240 type Error = ();
241
242 #[inline]
243 fn try_from(datum: Datum<'_>) -> Result<Self, Self::Error> {
244 match datum {
245 Datum::Null => Ok(None),
246 Datum::False => Ok(Some(false)),
247 Datum::True => Ok(Some(true)),
248 _ => Err(()),
249 }
250 }
251}
252
253impl TryFrom<Datum<'_>> for f32 {
254 type Error = ();
255
256 #[inline]
257 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
258 match from {
259 Datum::Float32(f) => Ok(*f),
260 _ => Err(()),
261 }
262 }
263}
264
265impl TryFrom<Datum<'_>> for Option<f32> {
266 type Error = ();
267
268 #[inline]
269 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
270 match from {
271 Datum::Null => Ok(None),
272 Datum::Float32(f) => Ok(Some(*f)),
273 _ => Err(()),
274 }
275 }
276}
277
278impl TryFrom<Datum<'_>> for OrderedFloat<f32> {
279 type Error = ();
280
281 #[inline]
282 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
283 match from {
284 Datum::Float32(f) => Ok(f),
285 _ => Err(()),
286 }
287 }
288}
289
290impl TryFrom<Datum<'_>> for Option<OrderedFloat<f32>> {
291 type Error = ();
292
293 #[inline]
294 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
295 match from {
296 Datum::Null => Ok(None),
297 Datum::Float32(f) => Ok(Some(f)),
298 _ => Err(()),
299 }
300 }
301}
302
303impl TryFrom<Datum<'_>> for f64 {
304 type Error = ();
305
306 #[inline]
307 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
308 match from {
309 Datum::Float64(f) => Ok(*f),
310 _ => Err(()),
311 }
312 }
313}
314
315impl TryFrom<Datum<'_>> for Option<f64> {
316 type Error = ();
317
318 #[inline]
319 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
320 match from {
321 Datum::Null => Ok(None),
322 Datum::Float64(f) => Ok(Some(*f)),
323 _ => Err(()),
324 }
325 }
326}
327
328impl TryFrom<Datum<'_>> for OrderedFloat<f64> {
329 type Error = ();
330
331 #[inline]
332 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
333 match from {
334 Datum::Float64(f) => Ok(f),
335 _ => Err(()),
336 }
337 }
338}
339
340impl TryFrom<Datum<'_>> for Option<OrderedFloat<f64>> {
341 type Error = ();
342
343 #[inline]
344 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
345 match from {
346 Datum::Null => Ok(None),
347 Datum::Float64(f) => Ok(Some(f)),
348 _ => Err(()),
349 }
350 }
351}
352
353impl TryFrom<Datum<'_>> for i16 {
354 type Error = ();
355
356 #[inline]
357 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
358 match from {
359 Datum::Int16(i) => Ok(i),
360 _ => Err(()),
361 }
362 }
363}
364
365impl TryFrom<Datum<'_>> for Option<i16> {
366 type Error = ();
367
368 #[inline]
369 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
370 match from {
371 Datum::Null => Ok(None),
372 Datum::Int16(i) => Ok(Some(i)),
373 _ => Err(()),
374 }
375 }
376}
377
378impl TryFrom<Datum<'_>> for i32 {
379 type Error = ();
380
381 #[inline]
382 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
383 match from {
384 Datum::Int32(i) => Ok(i),
385 _ => Err(()),
386 }
387 }
388}
389
390impl TryFrom<Datum<'_>> for Option<i32> {
391 type Error = ();
392
393 #[inline]
394 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
395 match from {
396 Datum::Null => Ok(None),
397 Datum::Int32(i) => Ok(Some(i)),
398 _ => Err(()),
399 }
400 }
401}
402
403impl TryFrom<Datum<'_>> for i64 {
404 type Error = ();
405
406 #[inline]
407 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
408 match from {
409 Datum::Int64(i) => Ok(i),
410 _ => Err(()),
411 }
412 }
413}
414
415impl TryFrom<Datum<'_>> for Option<i64> {
416 type Error = ();
417
418 #[inline]
419 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
420 match from {
421 Datum::Null => Ok(None),
422 Datum::Int64(i) => Ok(Some(i)),
423 _ => Err(()),
424 }
425 }
426}
427
428impl TryFrom<Datum<'_>> for u16 {
429 type Error = ();
430
431 #[inline]
432 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
433 match from {
434 Datum::UInt16(u) => Ok(u),
435 _ => Err(()),
436 }
437 }
438}
439
440impl TryFrom<Datum<'_>> for Option<u16> {
441 type Error = ();
442
443 #[inline]
444 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
445 match from {
446 Datum::Null => Ok(None),
447 Datum::UInt16(u) => Ok(Some(u)),
448 _ => Err(()),
449 }
450 }
451}
452
453impl TryFrom<Datum<'_>> for u32 {
454 type Error = ();
455
456 #[inline]
457 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
458 match from {
459 Datum::UInt32(u) => Ok(u),
460 _ => Err(()),
461 }
462 }
463}
464
465impl TryFrom<Datum<'_>> for Option<u32> {
466 type Error = ();
467
468 #[inline]
469 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
470 match from {
471 Datum::Null => Ok(None),
472 Datum::UInt32(u) => Ok(Some(u)),
473 _ => Err(()),
474 }
475 }
476}
477
478impl TryFrom<Datum<'_>> for u64 {
479 type Error = ();
480
481 #[inline]
482 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
483 match from {
484 Datum::UInt64(u) => Ok(u),
485 _ => Err(()),
486 }
487 }
488}
489
490impl TryFrom<Datum<'_>> for Option<u64> {
491 type Error = ();
492
493 #[inline]
494 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
495 match from {
496 Datum::Null => Ok(None),
497 Datum::UInt64(u) => Ok(Some(u)),
498 _ => Err(()),
499 }
500 }
501}
502
503impl TryFrom<Datum<'_>> for CheckedTimestamp<NaiveDateTime> {
504 type Error = ();
505
506 #[inline]
507 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
508 match from {
509 Datum::Timestamp(dt) => Ok(dt),
510 _ => Err(()),
511 }
512 }
513}
514
515impl TryFrom<Datum<'_>> for CheckedTimestamp<DateTime<Utc>> {
516 type Error = ();
517
518 #[inline]
519 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
520 match from {
521 Datum::TimestampTz(dt_tz) => Ok(dt_tz),
522 _ => Err(()),
523 }
524 }
525}
526
527impl TryFrom<Datum<'_>> for Date {
528 type Error = ();
529
530 #[inline]
531 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
532 match from {
533 Datum::Date(d) => Ok(d),
534 _ => Err(()),
535 }
536 }
537}
538
539impl TryFrom<Datum<'_>> for OrderedDecimal<Numeric> {
540 type Error = ();
541
542 #[inline]
543 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
544 match from {
545 Datum::Numeric(n) => Ok(n),
546 _ => Err(()),
547 }
548 }
549}
550
551impl TryFrom<Datum<'_>> for Option<OrderedDecimal<Numeric>> {
552 type Error = ();
553
554 #[inline]
555 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
556 match from {
557 Datum::Null => Ok(None),
558 Datum::Numeric(n) => Ok(Some(n)),
559 _ => Err(()),
560 }
561 }
562}
563
564impl TryFrom<Datum<'_>> for crate::Timestamp {
565 type Error = ();
566
567 #[inline]
568 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
569 match from {
570 Datum::MzTimestamp(n) => Ok(n),
571 _ => Err(()),
572 }
573 }
574}
575
576impl TryFrom<Datum<'_>> for Option<crate::Timestamp> {
577 type Error = ();
578
579 #[inline]
580 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
581 match from {
582 Datum::Null => Ok(None),
583 Datum::MzTimestamp(n) => Ok(Some(n)),
584 _ => Err(()),
585 }
586 }
587}
588
589impl TryFrom<Datum<'_>> for Interval {
590 type Error = ();
591
592 #[inline]
593 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
594 match from {
595 Datum::Interval(i) => Ok(i),
596 _ => Err(()),
597 }
598 }
599}
600
601impl TryFrom<Datum<'_>> for Option<Interval> {
602 type Error = ();
603
604 #[inline]
605 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
606 match from {
607 Datum::Null => Ok(None),
608 Datum::Interval(i) => Ok(Some(i)),
609 _ => Err(()),
610 }
611 }
612}
613
614impl TryFrom<Datum<'_>> for NaiveTime {
615 type Error = ();
616
617 #[inline]
618 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
619 match from {
620 Datum::Time(t) => Ok(t),
621 _ => Err(()),
622 }
623 }
624}
625
626impl TryFrom<Datum<'_>> for Option<NaiveTime> {
627 type Error = ();
628
629 #[inline]
630 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
631 match from {
632 Datum::Null => Ok(None),
633 Datum::Time(t) => Ok(Some(t)),
634 _ => Err(()),
635 }
636 }
637}
638
639impl<'a> Datum<'a> {
640 pub fn is_null(&self) -> bool {
642 matches!(self, Datum::Null)
643 }
644
645 #[track_caller]
651 pub fn unwrap_bool(&self) -> bool {
652 match self {
653 Datum::False => false,
654 Datum::True => true,
655 _ => panic!("Datum::unwrap_bool called on {:?}", self),
656 }
657 }
658
659 #[track_caller]
665 pub fn unwrap_int16(&self) -> i16 {
666 match self {
667 Datum::Int16(i) => *i,
668 _ => panic!("Datum::unwrap_int16 called on {:?}", self),
669 }
670 }
671
672 #[track_caller]
678 pub fn unwrap_int32(&self) -> i32 {
679 match self {
680 Datum::Int32(i) => *i,
681 _ => panic!("Datum::unwrap_int32 called on {:?}", self),
682 }
683 }
684
685 #[track_caller]
691 pub fn unwrap_int64(&self) -> i64 {
692 match self {
693 Datum::Int64(i) => *i,
694 _ => panic!("Datum::unwrap_int64 called on {:?}", self),
695 }
696 }
697
698 #[track_caller]
704 pub fn unwrap_uint8(&self) -> u8 {
705 match self {
706 Datum::UInt8(u) => *u,
707 _ => panic!("Datum::unwrap_uint8 called on {:?}", self),
708 }
709 }
710
711 #[track_caller]
717 pub fn unwrap_uint16(&self) -> u16 {
718 match self {
719 Datum::UInt16(u) => *u,
720 _ => panic!("Datum::unwrap_uint16 called on {:?}", self),
721 }
722 }
723
724 #[track_caller]
730 pub fn unwrap_uint32(&self) -> u32 {
731 match self {
732 Datum::UInt32(u) => *u,
733 _ => panic!("Datum::unwrap_uint32 called on {:?}", self),
734 }
735 }
736
737 #[track_caller]
743 pub fn unwrap_uint64(&self) -> u64 {
744 match self {
745 Datum::UInt64(u) => *u,
746 _ => panic!("Datum::unwrap_uint64 called on {:?}", self),
747 }
748 }
749
750 #[track_caller]
751 pub fn unwrap_ordered_float32(&self) -> OrderedFloat<f32> {
752 match self {
753 Datum::Float32(f) => *f,
754 _ => panic!("Datum::unwrap_ordered_float32 called on {:?}", self),
755 }
756 }
757
758 #[track_caller]
759 pub fn unwrap_ordered_float64(&self) -> OrderedFloat<f64> {
760 match self {
761 Datum::Float64(f) => *f,
762 _ => panic!("Datum::unwrap_ordered_float64 called on {:?}", self),
763 }
764 }
765
766 #[track_caller]
772 pub fn unwrap_float32(&self) -> f32 {
773 match self {
774 Datum::Float32(f) => f.into_inner(),
775 _ => panic!("Datum::unwrap_float32 called on {:?}", self),
776 }
777 }
778
779 #[track_caller]
785 pub fn unwrap_float64(&self) -> f64 {
786 match self {
787 Datum::Float64(f) => f.into_inner(),
788 _ => panic!("Datum::unwrap_float64 called on {:?}", self),
789 }
790 }
791
792 #[track_caller]
798 pub fn unwrap_date(&self) -> Date {
799 match self {
800 Datum::Date(d) => *d,
801 _ => panic!("Datum::unwrap_date called on {:?}", self),
802 }
803 }
804
805 #[track_caller]
811 pub fn unwrap_time(&self) -> chrono::NaiveTime {
812 match self {
813 Datum::Time(t) => *t,
814 _ => panic!("Datum::unwrap_time called on {:?}", self),
815 }
816 }
817
818 #[track_caller]
824 pub fn unwrap_timestamp(&self) -> CheckedTimestamp<chrono::NaiveDateTime> {
825 match self {
826 Datum::Timestamp(ts) => *ts,
827 _ => panic!("Datum::unwrap_timestamp called on {:?}", self),
828 }
829 }
830
831 #[track_caller]
837 pub fn unwrap_timestamptz(&self) -> CheckedTimestamp<chrono::DateTime<Utc>> {
838 match self {
839 Datum::TimestampTz(ts) => *ts,
840 _ => panic!("Datum::unwrap_timestamptz called on {:?}", self),
841 }
842 }
843
844 #[track_caller]
850 pub fn unwrap_interval(&self) -> Interval {
851 match self {
852 Datum::Interval(iv) => *iv,
853 _ => panic!("Datum::unwrap_interval called on {:?}", self),
854 }
855 }
856
857 #[track_caller]
863 pub fn unwrap_str(&self) -> &'a str {
864 match self {
865 Datum::String(s) => s,
866 _ => panic!("Datum::unwrap_string called on {:?}", self),
867 }
868 }
869
870 #[track_caller]
876 pub fn unwrap_bytes(&self) -> &'a [u8] {
877 match self {
878 Datum::Bytes(b) => b,
879 _ => panic!("Datum::unwrap_bytes called on {:?}", self),
880 }
881 }
882
883 #[track_caller]
889 pub fn unwrap_uuid(&self) -> Uuid {
890 match self {
891 Datum::Uuid(u) => *u,
892 _ => panic!("Datum::unwrap_uuid called on {:?}", self),
893 }
894 }
895
896 #[track_caller]
902 pub fn unwrap_array(&self) -> Array<'a> {
903 match self {
904 Datum::Array(array) => *array,
905 _ => panic!("Datum::unwrap_array called on {:?}", self),
906 }
907 }
908
909 #[track_caller]
915 pub fn unwrap_list(&self) -> DatumList<'a> {
916 match self {
917 Datum::List(list) => *list,
918 _ => panic!("Datum::unwrap_list called on {:?}", self),
919 }
920 }
921
922 #[track_caller]
928 pub fn unwrap_map(&self) -> DatumMap<'a> {
929 match self {
930 Datum::Map(dict) => *dict,
931 _ => panic!("Datum::unwrap_dict called on {:?}", self),
932 }
933 }
934
935 #[track_caller]
941 pub fn unwrap_numeric(&self) -> OrderedDecimal<Numeric> {
942 match self {
943 Datum::Numeric(n) => *n,
944 _ => panic!("Datum::unwrap_numeric called on {:?}", self),
945 }
946 }
947
948 #[track_caller]
954 pub fn unwrap_mz_timestamp(&self) -> crate::Timestamp {
955 match self {
956 Datum::MzTimestamp(t) => *t,
957 _ => panic!("Datum::unwrap_mz_timestamp called on {:?}", self),
958 }
959 }
960
961 #[track_caller]
972 pub fn unwrap_range(&self) -> Range<Datum<'a>> {
973 match self {
974 Datum::Range(range) => range.into_bounds(|b| b.datum()),
975 _ => panic!("Datum::unwrap_range called on {:?}", self),
976 }
977 }
978
979 #[track_caller]
985 pub fn unwrap_mz_acl_item(&self) -> MzAclItem {
986 match self {
987 Datum::MzAclItem(mz_acl_item) => *mz_acl_item,
988 _ => panic!("Datum::unwrap_mz_acl_item called on {:?}", self),
989 }
990 }
991
992 #[track_caller]
998 pub fn unwrap_acl_item(&self) -> AclItem {
999 match self {
1000 Datum::AclItem(acl_item) => *acl_item,
1001 _ => panic!("Datum::unwrap_acl_item called on {:?}", self),
1002 }
1003 }
1004
1005 pub fn is_instance_of(self, column_type: &ReprColumnType) -> bool {
1009 fn is_instance_of_scalar(datum: Datum, scalar_type: &ReprScalarType) -> bool {
1010 if let ReprScalarType::Jsonb = scalar_type {
1011 match datum {
1013 Datum::Dummy => false,
1014 Datum::JsonNull
1015 | Datum::False
1016 | Datum::True
1017 | Datum::Numeric(_)
1018 | Datum::String(_) => true,
1019 Datum::List(list) => list
1020 .iter()
1021 .all(|elem| is_instance_of_scalar(elem, scalar_type)),
1022 Datum::Map(dict) => dict
1023 .iter()
1024 .all(|(_key, val)| is_instance_of_scalar(val, scalar_type)),
1025 _ => false,
1026 }
1027 } else {
1028 match (datum, scalar_type) {
1030 (Datum::Dummy, _) => false,
1031 (Datum::Null, _) => false,
1032 (Datum::False, ReprScalarType::Bool) => true,
1033 (Datum::False, _) => false,
1034 (Datum::True, ReprScalarType::Bool) => true,
1035 (Datum::True, _) => false,
1036 (Datum::Int16(_), ReprScalarType::Int16) => true,
1037 (Datum::Int16(_), _) => false,
1038 (Datum::Int32(_), ReprScalarType::Int32) => true,
1039 (Datum::Int32(_), _) => false,
1040 (Datum::Int64(_), ReprScalarType::Int64) => true,
1041 (Datum::Int64(_), _) => false,
1042 (Datum::UInt8(_), ReprScalarType::UInt8) => true,
1043 (Datum::UInt8(_), _) => false,
1044 (Datum::UInt16(_), ReprScalarType::UInt16) => true,
1045 (Datum::UInt16(_), _) => false,
1046 (Datum::UInt32(_), ReprScalarType::UInt32) => true,
1047 (Datum::UInt32(_), _) => false,
1048 (Datum::UInt64(_), ReprScalarType::UInt64) => true,
1049 (Datum::UInt64(_), _) => false,
1050 (Datum::Float32(_), ReprScalarType::Float32) => true,
1051 (Datum::Float32(_), _) => false,
1052 (Datum::Float64(_), ReprScalarType::Float64) => true,
1053 (Datum::Float64(_), _) => false,
1054 (Datum::Date(_), ReprScalarType::Date) => true,
1055 (Datum::Date(_), _) => false,
1056 (Datum::Time(_), ReprScalarType::Time) => true,
1057 (Datum::Time(_), _) => false,
1058 (Datum::Timestamp(_), ReprScalarType::Timestamp { .. }) => true,
1059 (Datum::Timestamp(_), _) => false,
1060 (Datum::TimestampTz(_), ReprScalarType::TimestampTz { .. }) => true,
1061 (Datum::TimestampTz(_), _) => false,
1062 (Datum::Interval(_), ReprScalarType::Interval) => true,
1063 (Datum::Interval(_), _) => false,
1064 (Datum::Bytes(_), ReprScalarType::Bytes) => true,
1065 (Datum::Bytes(_), _) => false,
1066 (Datum::String(_), ReprScalarType::String) => true,
1067 (Datum::String(_), _) => false,
1068 (Datum::Uuid(_), ReprScalarType::Uuid) => true,
1069 (Datum::Uuid(_), _) => false,
1070 (Datum::Array(array), ReprScalarType::Array(t)) => {
1071 array.elements.iter().all(|e| match e {
1072 Datum::Null => true,
1073 _ => is_instance_of_scalar(e, t),
1074 })
1075 }
1076 (Datum::Array(array), ReprScalarType::Int2Vector) => {
1077 array.has_int2vector_dims()
1078 && array
1079 .elements
1080 .iter()
1081 .all(|e| is_instance_of_scalar(e, &ReprScalarType::Int16))
1082 }
1083 (Datum::Array(_), _) => false,
1084 (Datum::List(list), ReprScalarType::List { element_type, .. }) => list
1085 .iter()
1086 .all(|e| e.is_null() || is_instance_of_scalar(e, element_type)),
1087 (Datum::List(list), ReprScalarType::Record { fields, .. }) => {
1088 if list.iter().count() != fields.len() {
1089 return false;
1090 }
1091
1092 list.iter().zip_eq(fields).all(|(e, t)| {
1093 (e.is_null() && t.nullable) || is_instance_of_scalar(e, &t.scalar_type)
1094 })
1095 }
1096 (Datum::List(_), _) => false,
1097 (Datum::Map(map), ReprScalarType::Map { value_type, .. }) => map
1098 .iter()
1099 .all(|(_k, v)| v.is_null() || is_instance_of_scalar(v, value_type)),
1100 (Datum::Map(_), _) => false,
1101 (Datum::JsonNull, _) => false,
1102 (Datum::Numeric(_), ReprScalarType::Numeric) => true,
1103 (Datum::Numeric(_), _) => false,
1104 (Datum::MzTimestamp(_), ReprScalarType::MzTimestamp) => true,
1105 (Datum::MzTimestamp(_), _) => false,
1106 (Datum::Range(Range { inner }), ReprScalarType::Range { element_type }) => {
1107 match inner {
1108 None => true,
1109 Some(inner) => {
1110 true && match inner.lower.bound {
1111 None => true,
1112 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1113 } && match inner.upper.bound {
1114 None => true,
1115 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1116 }
1117 }
1118 }
1119 }
1120 (Datum::Range(_), _) => false,
1121 (Datum::MzAclItem(_), ReprScalarType::MzAclItem) => true,
1122 (Datum::MzAclItem(_), _) => false,
1123 (Datum::AclItem(_), ReprScalarType::AclItem) => true,
1124 (Datum::AclItem(_), _) => false,
1125 }
1126 }
1127 }
1128 if column_type.nullable {
1129 if let Datum::Null = self {
1130 return true;
1131 }
1132 }
1133 is_instance_of_scalar(self, &column_type.scalar_type)
1134 }
1135
1136 pub fn is_instance_of_sql(self, column_type: &SqlColumnType) -> bool {
1140 fn is_instance_of_scalar(datum: Datum, scalar_type: &SqlScalarType) -> bool {
1141 if let SqlScalarType::Jsonb = scalar_type {
1142 match datum {
1144 Datum::Dummy => false,
1145 Datum::JsonNull
1146 | Datum::False
1147 | Datum::True
1148 | Datum::Numeric(_)
1149 | Datum::String(_) => true,
1150 Datum::List(list) => list
1151 .iter()
1152 .all(|elem| is_instance_of_scalar(elem, scalar_type)),
1153 Datum::Map(dict) => dict
1154 .iter()
1155 .all(|(_key, val)| is_instance_of_scalar(val, scalar_type)),
1156 _ => false,
1157 }
1158 } else {
1159 match (datum, scalar_type) {
1161 (Datum::Dummy, _) => false,
1162 (Datum::Null, _) => false,
1163 (Datum::False, SqlScalarType::Bool) => true,
1164 (Datum::False, _) => false,
1165 (Datum::True, SqlScalarType::Bool) => true,
1166 (Datum::True, _) => false,
1167 (Datum::Int16(_), SqlScalarType::Int16) => true,
1168 (Datum::Int16(_), _) => false,
1169 (Datum::Int32(_), SqlScalarType::Int32) => true,
1170 (Datum::Int32(_), _) => false,
1171 (Datum::Int64(_), SqlScalarType::Int64) => true,
1172 (Datum::Int64(_), _) => false,
1173 (Datum::UInt8(_), SqlScalarType::PgLegacyChar) => true,
1174 (Datum::UInt8(_), _) => false,
1175 (Datum::UInt16(_), SqlScalarType::UInt16) => true,
1176 (Datum::UInt16(_), _) => false,
1177 (Datum::UInt32(_), SqlScalarType::Oid) => true,
1178 (Datum::UInt32(_), SqlScalarType::RegClass) => true,
1179 (Datum::UInt32(_), SqlScalarType::RegProc) => true,
1180 (Datum::UInt32(_), SqlScalarType::RegType) => true,
1181 (Datum::UInt32(_), SqlScalarType::UInt32) => true,
1182 (Datum::UInt32(_), _) => false,
1183 (Datum::UInt64(_), SqlScalarType::UInt64) => true,
1184 (Datum::UInt64(_), _) => false,
1185 (Datum::Float32(_), SqlScalarType::Float32) => true,
1186 (Datum::Float32(_), _) => false,
1187 (Datum::Float64(_), SqlScalarType::Float64) => true,
1188 (Datum::Float64(_), _) => false,
1189 (Datum::Date(_), SqlScalarType::Date) => true,
1190 (Datum::Date(_), _) => false,
1191 (Datum::Time(_), SqlScalarType::Time) => true,
1192 (Datum::Time(_), _) => false,
1193 (Datum::Timestamp(_), SqlScalarType::Timestamp { .. }) => true,
1194 (Datum::Timestamp(_), _) => false,
1195 (Datum::TimestampTz(_), SqlScalarType::TimestampTz { .. }) => true,
1196 (Datum::TimestampTz(_), _) => false,
1197 (Datum::Interval(_), SqlScalarType::Interval) => true,
1198 (Datum::Interval(_), _) => false,
1199 (Datum::Bytes(_), SqlScalarType::Bytes) => true,
1200 (Datum::Bytes(_), _) => false,
1201 (Datum::String(_), SqlScalarType::String)
1202 | (Datum::String(_), SqlScalarType::VarChar { .. })
1203 | (Datum::String(_), SqlScalarType::Char { .. })
1204 | (Datum::String(_), SqlScalarType::PgLegacyName) => true,
1205 (Datum::String(_), _) => false,
1206 (Datum::Uuid(_), SqlScalarType::Uuid) => true,
1207 (Datum::Uuid(_), _) => false,
1208 (Datum::Array(array), SqlScalarType::Array(t)) => {
1209 array.elements.iter().all(|e| match e {
1210 Datum::Null => true,
1211 _ => is_instance_of_scalar(e, t),
1212 })
1213 }
1214 (Datum::Array(array), SqlScalarType::Int2Vector) => {
1215 array.has_int2vector_dims()
1216 && array
1217 .elements
1218 .iter()
1219 .all(|e| is_instance_of_scalar(e, &SqlScalarType::Int16))
1220 }
1221 (Datum::Array(_), _) => false,
1222 (Datum::List(list), SqlScalarType::List { element_type, .. }) => list
1223 .iter()
1224 .all(|e| e.is_null() || is_instance_of_scalar(e, element_type)),
1225 (Datum::List(list), SqlScalarType::Record { fields, .. }) => {
1226 if list.iter().count() != fields.len() {
1227 return false;
1228 }
1229
1230 list.iter().zip_eq(fields).all(|(e, (_, t))| {
1231 (e.is_null() && t.nullable) || is_instance_of_scalar(e, &t.scalar_type)
1232 })
1233 }
1234 (Datum::List(_), _) => false,
1235 (Datum::Map(map), SqlScalarType::Map { value_type, .. }) => map
1236 .iter()
1237 .all(|(_k, v)| v.is_null() || is_instance_of_scalar(v, value_type)),
1238 (Datum::Map(_), _) => false,
1239 (Datum::JsonNull, _) => false,
1240 (Datum::Numeric(_), SqlScalarType::Numeric { .. }) => true,
1241 (Datum::Numeric(_), _) => false,
1242 (Datum::MzTimestamp(_), SqlScalarType::MzTimestamp) => true,
1243 (Datum::MzTimestamp(_), _) => false,
1244 (Datum::Range(Range { inner }), SqlScalarType::Range { element_type }) => {
1245 match inner {
1246 None => true,
1247 Some(inner) => {
1248 true && match inner.lower.bound {
1249 None => true,
1250 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1251 } && match inner.upper.bound {
1252 None => true,
1253 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1254 }
1255 }
1256 }
1257 }
1258 (Datum::Range(_), _) => false,
1259 (Datum::MzAclItem(_), SqlScalarType::MzAclItem) => true,
1260 (Datum::MzAclItem(_), _) => false,
1261 (Datum::AclItem(_), SqlScalarType::AclItem) => true,
1262 (Datum::AclItem(_), _) => false,
1263 }
1264 }
1265 }
1266 if column_type.nullable {
1267 if let Datum::Null = self {
1268 return true;
1269 }
1270 }
1271 is_instance_of_scalar(self, &column_type.scalar_type)
1272 }
1273}
1274
1275impl<'a> From<bool> for Datum<'a> {
1276 #[inline]
1277 fn from(b: bool) -> Datum<'a> {
1278 if b { Datum::True } else { Datum::False }
1279 }
1280}
1281
1282impl<'a, T> From<Overflowing<T>> for Datum<'a>
1285where
1286 Datum<'a>: From<T>,
1287{
1288 #[inline]
1289 fn from(i: Overflowing<T>) -> Datum<'a> {
1290 Datum::from(i.into_inner())
1291 }
1292}
1293
1294impl<'a> From<i16> for Datum<'a> {
1295 #[inline]
1296 fn from(i: i16) -> Datum<'a> {
1297 Datum::Int16(i)
1298 }
1299}
1300
1301impl<'a> From<i32> for Datum<'a> {
1302 #[inline]
1303 fn from(i: i32) -> Datum<'a> {
1304 Datum::Int32(i)
1305 }
1306}
1307
1308impl<'a> From<i64> for Datum<'a> {
1309 #[inline]
1310 fn from(i: i64) -> Datum<'a> {
1311 Datum::Int64(i)
1312 }
1313}
1314
1315impl<'a> From<u8> for Datum<'a> {
1316 #[inline]
1317 fn from(u: u8) -> Datum<'a> {
1318 Datum::UInt8(u)
1319 }
1320}
1321
1322impl<'a> From<u16> for Datum<'a> {
1323 #[inline]
1324 fn from(u: u16) -> Datum<'a> {
1325 Datum::UInt16(u)
1326 }
1327}
1328
1329impl<'a> From<u32> for Datum<'a> {
1330 #[inline]
1331 fn from(u: u32) -> Datum<'a> {
1332 Datum::UInt32(u)
1333 }
1334}
1335
1336impl<'a> From<u64> for Datum<'a> {
1337 #[inline]
1338 fn from(u: u64) -> Datum<'a> {
1339 Datum::UInt64(u)
1340 }
1341}
1342
1343impl<'a> From<OrderedFloat<f32>> for Datum<'a> {
1344 #[inline]
1345 fn from(f: OrderedFloat<f32>) -> Datum<'a> {
1346 Datum::Float32(f)
1347 }
1348}
1349
1350impl<'a> From<OrderedFloat<f64>> for Datum<'a> {
1351 #[inline]
1352 fn from(f: OrderedFloat<f64>) -> Datum<'a> {
1353 Datum::Float64(f)
1354 }
1355}
1356
1357impl<'a> From<f32> for Datum<'a> {
1358 #[inline]
1359 fn from(f: f32) -> Datum<'a> {
1360 Datum::Float32(OrderedFloat(f))
1361 }
1362}
1363
1364impl<'a> From<f64> for Datum<'a> {
1365 #[inline]
1366 fn from(f: f64) -> Datum<'a> {
1367 Datum::Float64(OrderedFloat(f))
1368 }
1369}
1370
1371impl<'a> From<i128> for Datum<'a> {
1372 #[inline]
1373 fn from(d: i128) -> Datum<'a> {
1374 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1375 }
1376}
1377
1378impl<'a> From<u128> for Datum<'a> {
1379 #[inline]
1380 fn from(d: u128) -> Datum<'a> {
1381 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1382 }
1383}
1384
1385impl<'a> From<Numeric> for Datum<'a> {
1386 #[inline]
1387 fn from(n: Numeric) -> Datum<'a> {
1388 Datum::Numeric(OrderedDecimal(n))
1389 }
1390}
1391
1392impl<'a> From<OrderedDecimal<Numeric>> for Datum<'a> {
1393 #[inline]
1394 fn from(n: OrderedDecimal<Numeric>) -> Datum<'a> {
1395 Datum::Numeric(n)
1396 }
1397}
1398
1399impl<'a> From<chrono::Duration> for Datum<'a> {
1400 #[inline]
1401 fn from(duration: chrono::Duration) -> Datum<'a> {
1402 let micros = duration.num_microseconds().unwrap_or(0);
1403 Datum::Interval(Interval::new(0, 0, micros))
1404 }
1405}
1406
1407impl<'a> From<Interval> for Datum<'a> {
1408 #[inline]
1409 fn from(other: Interval) -> Datum<'a> {
1410 Datum::Interval(other)
1411 }
1412}
1413
1414impl<'a> From<&'a str> for Datum<'a> {
1415 #[inline]
1416 fn from(s: &'a str) -> Datum<'a> {
1417 Datum::String(s)
1418 }
1419}
1420
1421impl<'a> From<&'a [u8]> for Datum<'a> {
1422 #[inline]
1423 fn from(b: &'a [u8]) -> Datum<'a> {
1424 Datum::Bytes(b)
1425 }
1426}
1427
1428impl<'a, const N: usize> From<&'a [u8; N]> for Datum<'a> {
1429 #[inline]
1430 fn from(b: &'a [u8; N]) -> Datum<'a> {
1431 Datum::Bytes(b.as_slice())
1432 }
1433}
1434
1435impl<'a> From<Date> for Datum<'a> {
1436 #[inline]
1437 fn from(d: Date) -> Datum<'a> {
1438 Datum::Date(d)
1439 }
1440}
1441
1442impl<'a> From<NaiveTime> for Datum<'a> {
1443 #[inline]
1444 fn from(t: NaiveTime) -> Datum<'a> {
1445 Datum::Time(t)
1446 }
1447}
1448
1449impl<'a> From<CheckedTimestamp<NaiveDateTime>> for Datum<'a> {
1450 #[inline]
1451 fn from(dt: CheckedTimestamp<NaiveDateTime>) -> Datum<'a> {
1452 Datum::Timestamp(dt)
1453 }
1454}
1455
1456impl<'a> From<CheckedTimestamp<DateTime<Utc>>> for Datum<'a> {
1457 #[inline]
1458 fn from(dt: CheckedTimestamp<DateTime<Utc>>) -> Datum<'a> {
1459 Datum::TimestampTz(dt)
1460 }
1461}
1462
1463impl<'a> TryInto<Datum<'a>> for NaiveDateTime {
1464 type Error = TimestampError;
1465
1466 #[inline]
1467 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1468 let t = CheckedTimestamp::from_timestamplike(self)?;
1469 Ok(t.into())
1470 }
1471}
1472
1473impl<'a> TryInto<Datum<'a>> for DateTime<Utc> {
1474 type Error = TimestampError;
1475
1476 #[inline]
1477 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1478 let t = CheckedTimestamp::from_timestamplike(self)?;
1479 Ok(t.into())
1480 }
1481}
1482
1483impl<'a> From<Uuid> for Datum<'a> {
1484 #[inline]
1485 fn from(uuid: Uuid) -> Datum<'a> {
1486 Datum::Uuid(uuid)
1487 }
1488}
1489impl<'a> From<crate::Timestamp> for Datum<'a> {
1490 #[inline]
1491 fn from(ts: crate::Timestamp) -> Datum<'a> {
1492 Datum::MzTimestamp(ts)
1493 }
1494}
1495
1496impl<'a> From<MzAclItem> for Datum<'a> {
1497 #[inline]
1498 fn from(mz_acl_item: MzAclItem) -> Self {
1499 Datum::MzAclItem(mz_acl_item)
1500 }
1501}
1502
1503impl<'a, T> From<Option<T>> for Datum<'a>
1504where
1505 Datum<'a>: From<T>,
1506{
1507 fn from(o: Option<T>) -> Datum<'a> {
1508 match o {
1509 Some(d) => d.into(),
1510 None => Datum::Null,
1511 }
1512 }
1513}
1514
1515fn write_delimited<T, TS, F>(
1516 f: &mut fmt::Formatter,
1517 delimiter: &str,
1518 things: TS,
1519 write: F,
1520) -> fmt::Result
1521where
1522 TS: IntoIterator<Item = T>,
1523 F: Fn(&mut fmt::Formatter, T) -> fmt::Result,
1524{
1525 let mut iter = things.into_iter().peekable();
1526 while let Some(thing) = iter.next() {
1527 write(f, thing)?;
1528 if iter.peek().is_some() {
1529 f.write_str(delimiter)?;
1530 }
1531 }
1532 Ok(())
1533}
1534
1535impl fmt::Display for Datum<'_> {
1536 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1537 match self {
1538 Datum::Null => f.write_str("null"),
1539 Datum::True => f.write_str("true"),
1540 Datum::False => f.write_str("false"),
1541 Datum::Int16(num) => write!(f, "{}", num),
1542 Datum::Int32(num) => write!(f, "{}", num),
1543 Datum::Int64(num) => write!(f, "{}", num),
1544 Datum::UInt8(num) => write!(f, "{}", num),
1545 Datum::UInt16(num) => write!(f, "{}", num),
1546 Datum::UInt32(num) => write!(f, "{}", num),
1547 Datum::UInt64(num) => write!(f, "{}", num),
1548 Datum::Float32(num) => write!(f, "{}", num),
1549 Datum::Float64(num) => write!(f, "{}", num),
1550 Datum::Date(d) => write!(f, "{}", d),
1551 Datum::Time(t) => write!(f, "{}", t),
1552 Datum::Timestamp(t) => write!(f, "{}", t),
1553 Datum::TimestampTz(t) => write!(f, "{}", t),
1554 Datum::Interval(iv) => write!(f, "{}", iv),
1555 Datum::Bytes(dat) => {
1556 f.write_str("0x")?;
1557 for b in dat.iter() {
1558 write!(f, "{:02x}", b)?;
1559 }
1560 Ok(())
1561 }
1562 Datum::String(s) => {
1563 write!(f, "{}", s.escaped())
1564 }
1565 Datum::Uuid(u) => write!(f, "{}", u),
1566 Datum::Array(array) => {
1567 if array.dims().into_iter().any(|dim| dim.lower_bound != 1) {
1568 write_delimited(f, "", array.dims(), |f, e| {
1569 let (lower, upper) = e.dimension_bounds();
1570 write!(f, "[{}:{}]", lower, upper)
1571 })?;
1572 f.write_str("=")?;
1573 }
1574 f.write_str("{")?;
1575 write_delimited(f, ", ", array.elements, |f, e| write!(f, "{}", e))?;
1576 f.write_str("}")
1577 }
1578 Datum::List(list) => {
1579 f.write_str("[")?;
1580 write_delimited(f, ", ", *list, |f, e| write!(f, "{}", e))?;
1581 f.write_str("]")
1582 }
1583 Datum::Map(dict) => {
1584 f.write_str("{")?;
1585 write_delimited(f, ", ", dict, |f, (k, v)| write!(f, "{}: {}", k, v))?;
1586 f.write_str("}")
1587 }
1588 Datum::Numeric(n) => write!(f, "{}", n.0.to_standard_notation_string()),
1589 Datum::MzTimestamp(t) => write!(f, "{}", t),
1590 Datum::JsonNull => f.write_str("json_null"),
1591 Datum::Dummy => f.write_str("dummy"),
1592 Datum::Range(i) => write!(f, "{}", i),
1593 Datum::MzAclItem(mz_acl_item) => write!(f, "{mz_acl_item}"),
1594 Datum::AclItem(acl_item) => write!(f, "{acl_item}"),
1595 }
1596 }
1597}
1598
1599#[derive(
1609 Clone,
1610 Debug,
1611 PartialEq,
1612 Eq,
1613 Serialize,
1614 Deserialize,
1615 Ord,
1616 PartialOrd,
1617 Hash,
1618 EnumKind
1619)]
1620#[enum_kind(SqlScalarBaseType, derive(PartialOrd, Ord, Hash))]
1621pub enum SqlScalarType {
1622 Bool,
1624 Int16,
1626 Int32,
1628 Int64,
1630 UInt16,
1632 UInt32,
1634 UInt64,
1636 Float32,
1638 Float64,
1640 Numeric {
1650 max_scale: Option<NumericMaxScale>,
1651 },
1652 Date,
1654 Time,
1656 Timestamp {
1658 precision: Option<TimestampPrecision>,
1659 },
1660 TimestampTz {
1662 precision: Option<TimestampPrecision>,
1663 },
1664 Interval,
1666 PgLegacyChar,
1671 PgLegacyName,
1677 Bytes,
1679 String,
1681 Char {
1687 length: Option<CharLength>,
1688 },
1689 VarChar {
1692 max_length: Option<VarCharMaxLength>,
1693 },
1694 Jsonb,
1706 Uuid,
1708 Array(Box<SqlScalarType>),
1714 List {
1719 element_type: Box<SqlScalarType>,
1720 custom_id: Option<CatalogItemId>,
1721 },
1722 Record {
1724 fields: Box<[(ColumnName, SqlColumnType)]>,
1729 custom_id: Option<CatalogItemId>,
1730 },
1731 Oid,
1733 Map {
1739 value_type: Box<SqlScalarType>,
1740 custom_id: Option<CatalogItemId>,
1741 },
1742 RegProc,
1744 RegType,
1746 RegClass,
1748 Int2Vector,
1751 MzTimestamp,
1753 Range {
1754 element_type: Box<SqlScalarType>,
1755 },
1756 MzAclItem,
1758 AclItem,
1760}
1761
1762impl RustType<ProtoRecordField> for (ColumnName, SqlColumnType) {
1763 fn into_proto(&self) -> ProtoRecordField {
1764 ProtoRecordField {
1765 column_name: Some(self.0.into_proto()),
1766 column_type: Some(self.1.into_proto()),
1767 }
1768 }
1769
1770 fn from_proto(proto: ProtoRecordField) -> Result<Self, TryFromProtoError> {
1771 Ok((
1772 proto
1773 .column_name
1774 .into_rust_if_some("ProtoRecordField::column_name")?,
1775 proto
1776 .column_type
1777 .into_rust_if_some("ProtoRecordField::column_type")?,
1778 ))
1779 }
1780}
1781
1782impl RustType<ProtoScalarType> for SqlScalarType {
1783 fn into_proto(&self) -> ProtoScalarType {
1784 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1785 use crate::relation_and_scalar::proto_scalar_type::*;
1786
1787 ProtoScalarType {
1788 kind: Some(match self {
1789 SqlScalarType::Bool => Bool(()),
1790 SqlScalarType::Int16 => Int16(()),
1791 SqlScalarType::Int32 => Int32(()),
1792 SqlScalarType::Int64 => Int64(()),
1793 SqlScalarType::UInt16 => UInt16(()),
1794 SqlScalarType::UInt32 => UInt32(()),
1795 SqlScalarType::UInt64 => UInt64(()),
1796 SqlScalarType::Float32 => Float32(()),
1797 SqlScalarType::Float64 => Float64(()),
1798 SqlScalarType::Date => Date(()),
1799 SqlScalarType::Time => Time(()),
1800 SqlScalarType::Timestamp { precision } => Timestamp(ProtoTimestamp {
1801 precision: precision.into_proto(),
1802 }),
1803 SqlScalarType::TimestampTz { precision } => TimestampTz(ProtoTimestampTz {
1804 precision: precision.into_proto(),
1805 }),
1806 SqlScalarType::Interval => Interval(()),
1807 SqlScalarType::PgLegacyChar => PgLegacyChar(()),
1808 SqlScalarType::PgLegacyName => PgLegacyName(()),
1809 SqlScalarType::Bytes => Bytes(()),
1810 SqlScalarType::String => String(()),
1811 SqlScalarType::Jsonb => Jsonb(()),
1812 SqlScalarType::Uuid => Uuid(()),
1813 SqlScalarType::Oid => Oid(()),
1814 SqlScalarType::RegProc => RegProc(()),
1815 SqlScalarType::RegType => RegType(()),
1816 SqlScalarType::RegClass => RegClass(()),
1817 SqlScalarType::Int2Vector => Int2Vector(()),
1818
1819 SqlScalarType::Numeric { max_scale } => Numeric(max_scale.into_proto()),
1820 SqlScalarType::Char { length } => Char(ProtoChar {
1821 length: length.into_proto(),
1822 }),
1823 SqlScalarType::VarChar { max_length } => VarChar(ProtoVarChar {
1824 max_length: max_length.into_proto(),
1825 }),
1826
1827 SqlScalarType::List {
1828 element_type,
1829 custom_id,
1830 } => List(Box::new(ProtoList {
1831 element_type: Some(element_type.into_proto()),
1832 custom_id: custom_id.map(|id| id.into_proto()),
1833 })),
1834 SqlScalarType::Record { custom_id, fields } => Record(ProtoRecord {
1835 custom_id: custom_id.map(|id| id.into_proto()),
1836 fields: fields.into_proto(),
1837 }),
1838 SqlScalarType::Array(typ) => Array(typ.into_proto()),
1839 SqlScalarType::Map {
1840 value_type,
1841 custom_id,
1842 } => Map(Box::new(ProtoMap {
1843 value_type: Some(value_type.into_proto()),
1844 custom_id: custom_id.map(|id| id.into_proto()),
1845 })),
1846 SqlScalarType::MzTimestamp => MzTimestamp(()),
1847 SqlScalarType::Range { element_type } => Range(Box::new(ProtoRange {
1848 element_type: Some(element_type.into_proto()),
1849 })),
1850 SqlScalarType::MzAclItem => MzAclItem(()),
1851 SqlScalarType::AclItem => AclItem(()),
1852 }),
1853 }
1854 }
1855
1856 fn from_proto(proto: ProtoScalarType) -> Result<Self, TryFromProtoError> {
1857 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1858
1859 let kind = proto
1860 .kind
1861 .ok_or_else(|| TryFromProtoError::missing_field("ProtoScalarType::Kind"))?;
1862
1863 match kind {
1864 Bool(()) => Ok(SqlScalarType::Bool),
1865 Int16(()) => Ok(SqlScalarType::Int16),
1866 Int32(()) => Ok(SqlScalarType::Int32),
1867 Int64(()) => Ok(SqlScalarType::Int64),
1868 UInt16(()) => Ok(SqlScalarType::UInt16),
1869 UInt32(()) => Ok(SqlScalarType::UInt32),
1870 UInt64(()) => Ok(SqlScalarType::UInt64),
1871 Float32(()) => Ok(SqlScalarType::Float32),
1872 Float64(()) => Ok(SqlScalarType::Float64),
1873 Date(()) => Ok(SqlScalarType::Date),
1874 Time(()) => Ok(SqlScalarType::Time),
1875 Timestamp(x) => Ok(SqlScalarType::Timestamp {
1876 precision: x.precision.into_rust()?,
1877 }),
1878 TimestampTz(x) => Ok(SqlScalarType::TimestampTz {
1879 precision: x.precision.into_rust()?,
1880 }),
1881 Interval(()) => Ok(SqlScalarType::Interval),
1882 PgLegacyChar(()) => Ok(SqlScalarType::PgLegacyChar),
1883 PgLegacyName(()) => Ok(SqlScalarType::PgLegacyName),
1884 Bytes(()) => Ok(SqlScalarType::Bytes),
1885 String(()) => Ok(SqlScalarType::String),
1886 Jsonb(()) => Ok(SqlScalarType::Jsonb),
1887 Uuid(()) => Ok(SqlScalarType::Uuid),
1888 Oid(()) => Ok(SqlScalarType::Oid),
1889 RegProc(()) => Ok(SqlScalarType::RegProc),
1890 RegType(()) => Ok(SqlScalarType::RegType),
1891 RegClass(()) => Ok(SqlScalarType::RegClass),
1892 Int2Vector(()) => Ok(SqlScalarType::Int2Vector),
1893
1894 Numeric(x) => Ok(SqlScalarType::Numeric {
1895 max_scale: x.into_rust()?,
1896 }),
1897 Char(x) => Ok(SqlScalarType::Char {
1898 length: x.length.into_rust()?,
1899 }),
1900
1901 VarChar(x) => Ok(SqlScalarType::VarChar {
1902 max_length: x.max_length.into_rust()?,
1903 }),
1904 Array(x) => Ok(SqlScalarType::Array({
1905 let st: SqlScalarType = (*x).into_rust()?;
1906 st.into()
1907 })),
1908 List(x) => Ok(SqlScalarType::List {
1909 element_type: Box::new(
1910 x.element_type
1911 .map(|x| *x)
1912 .into_rust_if_some("ProtoList::element_type")?,
1913 ),
1914 custom_id: x.custom_id.map(|id| id.into_rust()).transpose()?,
1915 }),
1916 Record(x) => Ok(SqlScalarType::Record {
1917 custom_id: x.custom_id.map(|id| id.into_rust()).transpose()?,
1918 fields: x.fields.into_rust()?,
1919 }),
1920 Map(x) => Ok(SqlScalarType::Map {
1921 value_type: Box::new(
1922 x.value_type
1923 .map(|x| *x)
1924 .into_rust_if_some("ProtoMap::value_type")?,
1925 ),
1926 custom_id: x.custom_id.map(|id| id.into_rust()).transpose()?,
1927 }),
1928 MzTimestamp(()) => Ok(SqlScalarType::MzTimestamp),
1929 Range(x) => Ok(SqlScalarType::Range {
1930 element_type: Box::new(
1931 x.element_type
1932 .map(|x| *x)
1933 .into_rust_if_some("ProtoRange::element_type")?,
1934 ),
1935 }),
1936 MzAclItem(()) => Ok(SqlScalarType::MzAclItem),
1937 AclItem(()) => Ok(SqlScalarType::AclItem),
1938 }
1939 }
1940}
1941
1942pub trait SqlContainerType {
1953 fn unwrap_element_type(container: &SqlScalarType) -> &SqlScalarType;
1955 fn wrap_element_type(element: SqlScalarType) -> SqlScalarType;
1957}
1958
1959pub trait AsColumnType {
1961 fn as_column_type() -> SqlColumnType;
1963}
1964
1965pub trait InputDatumType<'a, E>: Sized {
1967 fn nullable() -> bool;
1969
1970 fn all_nullable() -> bool {
1976 Self::nullable()
1977 }
1978
1979 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>>;
1982
1983 fn try_from_iter(
1986 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
1987 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
1988 match iter.next() {
1991 Some(next) => Self::try_from_result(next).map_err(|e| e.map(Some)),
1992 None => Err(Ok(None)),
1993 }
1994 }
1995}
1996
1997pub trait OutputDatumType<'a, E>: Sized {
1999 fn nullable() -> bool;
2001
2002 fn fallible() -> bool;
2004
2005 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E>;
2007}
2008
2009#[derive(Debug)]
2012pub struct ArrayRustType<T>(pub Vec<T>);
2013
2014impl<T> From<Vec<T>> for ArrayRustType<T> {
2015 fn from(v: Vec<T>) -> Self {
2016 Self(v)
2017 }
2018}
2019
2020impl<B: ToOwned<Owned: AsColumnType> + ?Sized> AsColumnType for Cow<'_, B> {
2022 fn as_column_type() -> SqlColumnType {
2023 <B::Owned>::as_column_type()
2024 }
2025}
2026
2027impl<'a, E, B: ToOwned + ?Sized> InputDatumType<'a, E> for Cow<'a, B>
2028where
2029 for<'b> B::Owned: InputDatumType<'b, E>,
2030 for<'b> &'b B: InputDatumType<'b, E>,
2031{
2032 fn nullable() -> bool {
2033 B::Owned::nullable()
2034 }
2035 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2036 <&B>::try_from_result(res).map(|b| Cow::Borrowed(b))
2037 }
2038}
2039
2040impl<'a, E, B: ToOwned + ?Sized> OutputDatumType<'a, E> for Cow<'a, B>
2041where
2042 for<'b> B::Owned: OutputDatumType<'b, E>,
2043 for<'b> &'b B: OutputDatumType<'b, E>,
2044{
2045 fn nullable() -> bool {
2046 B::Owned::nullable()
2047 }
2048 fn fallible() -> bool {
2049 B::Owned::fallible()
2050 }
2051 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2052 match self {
2053 Cow::Owned(b) => b.into_result(temp_storage),
2054 Cow::Borrowed(b) => b.into_result(temp_storage),
2055 }
2056 }
2057}
2058
2059impl<B: AsColumnType> AsColumnType for Option<B> {
2060 fn as_column_type() -> SqlColumnType {
2061 B::as_column_type().nullable(true)
2062 }
2063}
2064
2065impl<'a, E, B: InputDatumType<'a, E>> InputDatumType<'a, E> for Option<B> {
2066 fn nullable() -> bool {
2067 true
2068 }
2069 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2070 match res {
2071 Ok(Datum::Null) => Ok(None),
2072 Ok(datum) => B::try_from_result(Ok(datum)).map(Some),
2073 _ => Err(res),
2074 }
2075 }
2076}
2077
2078impl<'a, E, B: OutputDatumType<'a, E>> OutputDatumType<'a, E> for Option<B> {
2079 fn nullable() -> bool {
2080 true
2081 }
2082 fn fallible() -> bool {
2083 false
2084 }
2085 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2086 match self {
2087 Some(inner) => inner.into_result(temp_storage),
2088 None => Ok(Datum::Null),
2089 }
2090 }
2091}
2092
2093impl<E, B: AsColumnType> AsColumnType for Result<B, E> {
2094 fn as_column_type() -> SqlColumnType {
2095 B::as_column_type()
2096 }
2097}
2098
2099impl<'a, E, B: InputDatumType<'a, E>> InputDatumType<'a, E> for Result<B, E> {
2100 fn nullable() -> bool {
2101 B::nullable()
2102 }
2103 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2104 B::try_from_result(res).map(Ok)
2105 }
2106 fn try_from_iter(
2107 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
2108 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
2109 B::try_from_iter(iter).map(Ok)
2110 }
2111}
2112
2113impl<'a, E, B: OutputDatumType<'a, E>> OutputDatumType<'a, E> for Result<B, E> {
2114 fn nullable() -> bool {
2115 B::nullable()
2116 }
2117 fn fallible() -> bool {
2118 true
2119 }
2120 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2121 self.and_then(|inner| inner.into_result(temp_storage))
2122 }
2123}
2124
2125macro_rules! impl_tuple_input_datum_type {
2126 ($($T:ident),+) => {
2127 #[allow(non_snake_case)]
2128 impl<'a, E, $($T: InputDatumType<'a, E>),+> InputDatumType<'a, E> for ($($T,)+) {
2129 fn try_from_result(_res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2130 unimplemented!("Not possible")
2131 }
2132 fn try_from_iter(
2133 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
2134 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
2135 $(
2142 let $T = <$T>::try_from_iter(iter);
2143 )+
2144 $(
2146 let $T = match $T {
2147 Err(Ok(None)) => return Err(Ok(None)),
2148 Err(Ok(Some(datum))) if !datum.is_null() => return Err(Ok(Some(datum))),
2149 els => els,
2150 };
2151 )+
2152 $(
2154 let $T = match $T {
2155 Err(Err(err)) => return Err(Err(err)),
2156 els => els,
2157 };
2158 )+
2159 $(
2161 let $T = $T?;
2162 )+
2163 Ok(($($T,)+))
2164 }
2165 fn nullable() -> bool {
2166 $( <$T>::nullable() )||+
2171 }
2172 fn all_nullable() -> bool {
2173 $( <$T>::nullable() )&&+
2178 }
2179 }
2180 }
2181}
2182
2183impl_tuple_input_datum_type!(T0);
2184impl_tuple_input_datum_type!(T0, T1);
2185impl_tuple_input_datum_type!(T0, T1, T2);
2186impl_tuple_input_datum_type!(T0, T1, T2, T3);
2187impl_tuple_input_datum_type!(T0, T1, T2, T3, T4);
2188impl_tuple_input_datum_type!(T0, T1, T2, T3, T4, T5);
2189
2190#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2192pub struct Variadic<T>(pub Vec<T>);
2193
2194impl<T> From<Vec<T>> for Variadic<T> {
2195 #[inline(always)]
2196 fn from(v: Vec<T>) -> Self {
2197 Self(v)
2198 }
2199}
2200
2201impl<T> std::ops::Deref for Variadic<T> {
2202 type Target = Vec<T>;
2203
2204 #[inline(always)]
2205 fn deref(&self) -> &Self::Target {
2206 &self.0
2207 }
2208}
2209
2210impl<T> IntoIterator for Variadic<T> {
2211 type Item = T;
2212 type IntoIter = std::vec::IntoIter<T>;
2213
2214 #[inline(always)]
2215 fn into_iter(self) -> Self::IntoIter {
2216 self.0.into_iter()
2217 }
2218}
2219
2220impl<'a, T> IntoIterator for &'a Variadic<T> {
2221 type Item = &'a T;
2222 type IntoIter = std::slice::Iter<'a, T>;
2223
2224 #[inline(always)]
2225 fn into_iter(self) -> Self::IntoIter {
2226 (&self.0).into_iter()
2227 }
2228}
2229
2230impl<'a, E, T: InputDatumType<'a, E>> InputDatumType<'a, E> for Variadic<T> {
2231 fn nullable() -> bool {
2232 T::nullable()
2233 }
2234 #[inline]
2235 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2236 Ok(vec![T::try_from_result(res)?].into())
2237 }
2238 #[inline]
2239 fn try_from_iter(
2240 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
2241 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
2242 let mut res = Vec::with_capacity(iter.size_hint().0);
2243 loop {
2244 match T::try_from_iter(iter) {
2245 Ok(t) => res.push(t),
2246 Err(Ok(None)) => break,
2247 Err(err) => return Err(err),
2248 }
2249 }
2250 Ok(Self(res))
2251 }
2252}
2253
2254#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
2256pub struct OptionalArg<T>(pub Option<T>);
2257
2258impl<T> std::ops::Deref for OptionalArg<T> {
2259 type Target = Option<T>;
2260
2261 #[inline(always)]
2262 fn deref(&self) -> &Self::Target {
2263 &self.0
2264 }
2265}
2266
2267impl<T> From<Option<T>> for OptionalArg<T> {
2268 #[inline(always)]
2269 fn from(opt: Option<T>) -> Self {
2270 Self(opt)
2271 }
2272}
2273
2274impl<'a, E, T: InputDatumType<'a, E>> InputDatumType<'a, E> for OptionalArg<T> {
2275 fn nullable() -> bool {
2276 T::nullable()
2277 }
2278 #[inline]
2279 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2280 Ok(Some(T::try_from_result(res)?).into())
2281 }
2282 #[inline]
2283 fn try_from_iter(
2284 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
2285 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
2286 match iter.next() {
2287 Some(datum) => {
2288 let val = T::try_from_result(datum).map_err(|r| r.map(Some))?;
2289 Ok(Some(val).into())
2290 }
2291 None => Ok(None.into()),
2292 }
2293 }
2294}
2295
2296#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2303pub struct ExcludeNull<B>(B);
2304
2305impl<B: AsColumnType> AsColumnType for ExcludeNull<B> {
2306 fn as_column_type() -> SqlColumnType {
2307 B::as_column_type().nullable(false)
2308 }
2309}
2310
2311impl<'a, E, B: InputDatumType<'a, E>> InputDatumType<'a, E> for ExcludeNull<B> {
2312 fn nullable() -> bool {
2313 false
2314 }
2315 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2316 match res {
2317 Ok(Datum::Null) => Err(Ok(Datum::Null)),
2318 _ => B::try_from_result(res).map(ExcludeNull),
2319 }
2320 }
2321}
2322
2323impl<'a, E, B: OutputDatumType<'a, E>> OutputDatumType<'a, E> for ExcludeNull<B> {
2324 fn nullable() -> bool {
2325 false
2326 }
2327 fn fallible() -> bool {
2328 B::fallible()
2329 }
2330 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2331 self.0.into_result(temp_storage)
2332 }
2333}
2334
2335impl<B> std::ops::Deref for ExcludeNull<B> {
2336 type Target = B;
2337
2338 fn deref(&self) -> &Self::Target {
2339 &self.0
2340 }
2341}
2342
2343macro_rules! impl_datum_type_copy {
2345 ($lt:lifetime, $native:ty, $variant:ident) => {
2346 #[allow(unused_lifetimes)]
2347 impl<$lt> AsColumnType for $native {
2348 fn as_column_type() -> SqlColumnType {
2349 SqlScalarType::$variant.nullable(false)
2350 }
2351 }
2352
2353 impl<$lt, E> InputDatumType<$lt, E> for $native {
2354 fn nullable() -> bool {
2355 false
2356 }
2357
2358 fn try_from_result(res: Result<Datum<$lt>, E>) -> Result<Self, Result<Datum<$lt>, E>> {
2359 match res {
2360 Ok(Datum::$variant(f)) => Ok(f.into()),
2361 _ => Err(res),
2362 }
2363 }
2364 }
2365
2366 impl<$lt, E> OutputDatumType<$lt, E> for $native {
2367 fn nullable() -> bool {
2368 false
2369 }
2370
2371 fn fallible() -> bool {
2372 false
2373 }
2374
2375 fn into_result(self, _temp_storage: &$lt RowArena) -> Result<Datum<$lt>, E> {
2376 Ok(Datum::$variant(self.into()))
2377 }
2378 }
2379 };
2380 ($native:ty, $variant:ident) => {
2381 impl_datum_type_copy!('a, $native, $variant);
2382 };
2383}
2384
2385impl_datum_type_copy!(f32, Float32);
2386impl_datum_type_copy!(f64, Float64);
2387impl_datum_type_copy!(i16, Int16);
2388impl_datum_type_copy!(i32, Int32);
2389impl_datum_type_copy!(i64, Int64);
2390impl_datum_type_copy!(u16, UInt16);
2391impl_datum_type_copy!(u32, UInt32);
2392impl_datum_type_copy!(u64, UInt64);
2393impl_datum_type_copy!(Interval, Interval);
2394impl_datum_type_copy!(Date, Date);
2395impl_datum_type_copy!(NaiveTime, Time);
2396impl_datum_type_copy!(Uuid, Uuid);
2397impl_datum_type_copy!('a, &'a str, String);
2398impl_datum_type_copy!('a, &'a [u8], Bytes);
2399impl_datum_type_copy!(crate::Timestamp, MzTimestamp);
2400
2401impl<'a, E> InputDatumType<'a, E> for Datum<'a> {
2402 fn nullable() -> bool {
2403 true
2404 }
2405
2406 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2407 match res {
2408 Ok(datum) => Ok(datum),
2409 _ => Err(res),
2410 }
2411 }
2412}
2413
2414impl<'a, E> OutputDatumType<'a, E> for Datum<'a> {
2415 fn nullable() -> bool {
2416 true
2417 }
2418
2419 fn fallible() -> bool {
2420 false
2421 }
2422
2423 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2424 Ok(self)
2425 }
2426}
2427
2428impl<'a, E> InputDatumType<'a, E> for DatumList<'a> {
2429 fn nullable() -> bool {
2430 false
2431 }
2432
2433 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2434 match res {
2435 Ok(Datum::List(list)) => Ok(list),
2436 _ => Err(res),
2437 }
2438 }
2439}
2440
2441impl<'a, E> OutputDatumType<'a, E> for DatumList<'a> {
2442 fn nullable() -> bool {
2443 false
2444 }
2445
2446 fn fallible() -> bool {
2447 false
2448 }
2449
2450 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2451 Ok(Datum::List(self))
2452 }
2453}
2454
2455impl<'a, E> InputDatumType<'a, E> for Array<'a> {
2456 fn nullable() -> bool {
2457 false
2458 }
2459
2460 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2461 match res {
2462 Ok(Datum::Array(array)) => Ok(array),
2463 _ => Err(res),
2464 }
2465 }
2466}
2467
2468impl<'a, E> OutputDatumType<'a, E> for Array<'a> {
2469 fn nullable() -> bool {
2470 false
2471 }
2472
2473 fn fallible() -> bool {
2474 false
2475 }
2476
2477 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2478 Ok(Datum::Array(self))
2479 }
2480}
2481
2482#[derive(Debug)]
2499pub struct Int2Vector<'a>(pub Array<'a>);
2500
2501impl AsColumnType for Int2Vector<'_> {
2502 fn as_column_type() -> SqlColumnType {
2503 SqlScalarType::Int2Vector.nullable(false)
2504 }
2505}
2506
2507impl<'a, E> InputDatumType<'a, E> for Int2Vector<'a> {
2508 fn nullable() -> bool {
2509 false
2510 }
2511
2512 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2513 match res {
2514 Ok(Datum::Array(array)) => Ok(Int2Vector(array)),
2515 _ => Err(res),
2516 }
2517 }
2518}
2519
2520impl<'a, E> OutputDatumType<'a, E> for Int2Vector<'a> {
2521 fn nullable() -> bool {
2522 false
2523 }
2524
2525 fn fallible() -> bool {
2526 false
2527 }
2528
2529 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2530 Ok(Datum::Array(self.0))
2531 }
2532}
2533
2534impl<'a, E> InputDatumType<'a, E> for DatumMap<'a> {
2535 fn nullable() -> bool {
2536 false
2537 }
2538
2539 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2540 match res {
2541 Ok(Datum::Map(map)) => Ok(map),
2542 _ => Err(res),
2543 }
2544 }
2545}
2546
2547impl<'a, E> OutputDatumType<'a, E> for DatumMap<'a> {
2548 fn nullable() -> bool {
2549 false
2550 }
2551
2552 fn fallible() -> bool {
2553 false
2554 }
2555
2556 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2557 Ok(Datum::Map(self))
2558 }
2559}
2560
2561impl<'a, E> InputDatumType<'a, E> for Range<DatumNested<'a>> {
2562 fn nullable() -> bool {
2563 false
2564 }
2565
2566 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2567 match res {
2568 Ok(Datum::Range(range)) => Ok(range),
2569 _ => Err(res),
2570 }
2571 }
2572}
2573
2574impl<'a, E> OutputDatumType<'a, E> for Range<DatumNested<'a>> {
2575 fn nullable() -> bool {
2576 false
2577 }
2578
2579 fn fallible() -> bool {
2580 false
2581 }
2582
2583 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2584 Ok(Datum::Range(self))
2585 }
2586}
2587
2588impl<'a, E> InputDatumType<'a, E> for Range<Datum<'a>> {
2589 fn nullable() -> bool {
2590 false
2591 }
2592
2593 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2594 match res {
2595 Ok(r @ Datum::Range(..)) => Ok(r.unwrap_range()),
2596 _ => Err(res),
2597 }
2598 }
2599}
2600
2601impl<'a, E> OutputDatumType<'a, E> for Range<Datum<'a>> {
2602 fn nullable() -> bool {
2603 false
2604 }
2605
2606 fn fallible() -> bool {
2607 false
2608 }
2609
2610 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2611 let d =
2612 self.into_bounds(|bound| temp_storage.make_datum_nested(|packer| packer.push(bound)));
2613 Ok(Datum::Range(d))
2614 }
2615}
2616
2617impl AsColumnType for bool {
2618 fn as_column_type() -> SqlColumnType {
2619 SqlScalarType::Bool.nullable(false)
2620 }
2621}
2622
2623impl<'a, E> InputDatumType<'a, E> for bool {
2624 fn nullable() -> bool {
2625 false
2626 }
2627
2628 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2629 match res {
2630 Ok(Datum::True) => Ok(true),
2631 Ok(Datum::False) => Ok(false),
2632 _ => Err(res),
2633 }
2634 }
2635}
2636
2637impl<'a, E> OutputDatumType<'a, E> for bool {
2638 fn nullable() -> bool {
2639 false
2640 }
2641
2642 fn fallible() -> bool {
2643 false
2644 }
2645
2646 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2647 if self {
2648 Ok(Datum::True)
2649 } else {
2650 Ok(Datum::False)
2651 }
2652 }
2653}
2654
2655impl AsColumnType for String {
2656 fn as_column_type() -> SqlColumnType {
2657 SqlScalarType::String.nullable(false)
2658 }
2659}
2660
2661impl<'a, E> InputDatumType<'a, E> for String {
2662 fn nullable() -> bool {
2663 false
2664 }
2665
2666 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2667 match res {
2668 Ok(Datum::String(s)) => Ok(s.to_owned()),
2669 _ => Err(res),
2670 }
2671 }
2672}
2673
2674impl<'a, E> OutputDatumType<'a, E> for String {
2675 fn nullable() -> bool {
2676 false
2677 }
2678
2679 fn fallible() -> bool {
2680 false
2681 }
2682
2683 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2684 Ok(Datum::String(temp_storage.push_string(self)))
2685 }
2686}
2687
2688impl<T: AsColumnType> AsColumnType for ArrayRustType<T> {
2689 fn as_column_type() -> SqlColumnType {
2690 let inner = T::as_column_type();
2691 SqlScalarType::Array(Box::new(inner.scalar_type)).nullable(false)
2692 }
2693}
2694
2695impl<'a, T, E> InputDatumType<'a, E> for ArrayRustType<T>
2696where
2697 T: InputDatumType<'a, E>,
2698{
2699 fn nullable() -> bool {
2700 false
2701 }
2702
2703 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2704 if let Ok(Datum::Array(arr)) = &res {
2705 let result = arr
2706 .elements()
2707 .into_iter()
2708 .map(|d| T::try_from_result(Ok(d)))
2709 .collect::<Result<_, _>>();
2710 if let Ok(elements) = result {
2711 return Ok(ArrayRustType(elements));
2712 }
2713 }
2714
2715 Err(res)
2717 }
2718}
2719
2720impl<'a, T, E> OutputDatumType<'a, E> for ArrayRustType<T>
2721where
2722 T: OutputDatumType<'a, E>,
2723{
2724 fn nullable() -> bool {
2725 false
2726 }
2727
2728 fn fallible() -> bool {
2729 T::fallible()
2730 }
2731
2732 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2733 let dimensions = ArrayDimension {
2734 lower_bound: 1,
2735 length: self.0.len(),
2736 };
2737 let iter = self
2738 .0
2739 .into_iter()
2740 .map(|elem| elem.into_result(temp_storage));
2741 temp_storage.try_make_datum(|packer| {
2742 packer
2743 .try_push_array_fallible(&[dimensions], iter)
2744 .expect("self is 1 dimensional, and its length is used for the array length")
2745 })
2746 }
2747}
2748
2749impl AsColumnType for Vec<u8> {
2750 fn as_column_type() -> SqlColumnType {
2751 SqlScalarType::Bytes.nullable(false)
2752 }
2753}
2754
2755impl<'a, E> InputDatumType<'a, E> for Vec<u8> {
2756 fn nullable() -> bool {
2757 false
2758 }
2759
2760 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2761 match res {
2762 Ok(Datum::Bytes(b)) => Ok(b.to_owned()),
2763 _ => Err(res),
2764 }
2765 }
2766}
2767
2768impl<'a, E> OutputDatumType<'a, E> for Vec<u8> {
2769 fn nullable() -> bool {
2770 false
2771 }
2772
2773 fn fallible() -> bool {
2774 false
2775 }
2776
2777 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2778 Ok(Datum::Bytes(temp_storage.push_bytes(self)))
2779 }
2780}
2781
2782impl AsColumnType for Numeric {
2783 fn as_column_type() -> SqlColumnType {
2784 SqlScalarType::Numeric { max_scale: None }.nullable(false)
2785 }
2786}
2787
2788impl<'a, E> InputDatumType<'a, E> for Numeric {
2789 fn nullable() -> bool {
2790 false
2791 }
2792
2793 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2794 match res {
2795 Ok(Datum::Numeric(n)) => Ok(n.into_inner()),
2796 _ => Err(res),
2797 }
2798 }
2799}
2800
2801impl<'a, E> OutputDatumType<'a, E> for Numeric {
2802 fn nullable() -> bool {
2803 false
2804 }
2805
2806 fn fallible() -> bool {
2807 false
2808 }
2809
2810 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2811 Ok(Datum::from(self))
2812 }
2813}
2814
2815impl<'a, E> InputDatumType<'a, E> for OrderedDecimal<Numeric> {
2816 fn nullable() -> bool {
2817 false
2818 }
2819
2820 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2821 match res {
2822 Ok(Datum::Numeric(n)) => Ok(n),
2823 _ => Err(res),
2824 }
2825 }
2826}
2827
2828impl<'a, E> OutputDatumType<'a, E> for OrderedDecimal<Numeric> {
2829 fn nullable() -> bool {
2830 false
2831 }
2832
2833 fn fallible() -> bool {
2834 false
2835 }
2836
2837 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2838 Ok(Datum::from(self))
2839 }
2840}
2841
2842impl AsColumnType for PgLegacyChar {
2843 fn as_column_type() -> SqlColumnType {
2844 SqlScalarType::PgLegacyChar.nullable(false)
2845 }
2846}
2847
2848impl<'a, E> InputDatumType<'a, E> for PgLegacyChar {
2849 fn nullable() -> bool {
2850 false
2851 }
2852
2853 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2854 match res {
2855 Ok(Datum::UInt8(a)) => Ok(PgLegacyChar(a)),
2856 _ => Err(res),
2857 }
2858 }
2859}
2860
2861impl<'a, E> OutputDatumType<'a, E> for PgLegacyChar {
2862 fn nullable() -> bool {
2863 false
2864 }
2865
2866 fn fallible() -> bool {
2867 false
2868 }
2869
2870 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2871 Ok(Datum::UInt8(self.0))
2872 }
2873}
2874
2875impl<S> AsColumnType for PgLegacyName<S>
2876where
2877 S: AsRef<str>,
2878{
2879 fn as_column_type() -> SqlColumnType {
2880 SqlScalarType::PgLegacyName.nullable(false)
2881 }
2882}
2883
2884impl<'a, E> InputDatumType<'a, E> for PgLegacyName<&'a str> {
2885 fn nullable() -> bool {
2886 false
2887 }
2888
2889 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2890 match res {
2891 Ok(Datum::String(a)) => Ok(PgLegacyName(a)),
2892 _ => Err(res),
2893 }
2894 }
2895}
2896
2897impl<'a, E> OutputDatumType<'a, E> for PgLegacyName<&'a str> {
2898 fn nullable() -> bool {
2899 false
2900 }
2901
2902 fn fallible() -> bool {
2903 false
2904 }
2905
2906 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2907 Ok(Datum::String(self.0))
2908 }
2909}
2910
2911impl<'a, E> InputDatumType<'a, E> for PgLegacyName<String> {
2912 fn nullable() -> bool {
2913 false
2914 }
2915
2916 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2917 match res {
2918 Ok(Datum::String(a)) => Ok(PgLegacyName(a.to_owned())),
2919 _ => Err(res),
2920 }
2921 }
2922}
2923
2924impl<'a, E> OutputDatumType<'a, E> for PgLegacyName<String> {
2925 fn nullable() -> bool {
2926 false
2927 }
2928
2929 fn fallible() -> bool {
2930 false
2931 }
2932
2933 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2934 Ok(Datum::String(temp_storage.push_string(self.0)))
2935 }
2936}
2937
2938impl AsColumnType for Oid {
2939 fn as_column_type() -> SqlColumnType {
2940 SqlScalarType::Oid.nullable(false)
2941 }
2942}
2943
2944impl<'a, E> InputDatumType<'a, E> for Oid {
2945 fn nullable() -> bool {
2946 false
2947 }
2948
2949 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2950 match res {
2951 Ok(Datum::UInt32(a)) => Ok(Oid(a)),
2952 _ => Err(res),
2953 }
2954 }
2955}
2956
2957impl<'a, E> OutputDatumType<'a, E> for Oid {
2958 fn nullable() -> bool {
2959 false
2960 }
2961
2962 fn fallible() -> bool {
2963 false
2964 }
2965
2966 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2967 Ok(Datum::UInt32(self.0))
2968 }
2969}
2970
2971impl AsColumnType for RegClass {
2972 fn as_column_type() -> SqlColumnType {
2973 SqlScalarType::RegClass.nullable(false)
2974 }
2975}
2976
2977impl<'a, E> InputDatumType<'a, E> for RegClass {
2978 fn nullable() -> bool {
2979 false
2980 }
2981
2982 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2983 match res {
2984 Ok(Datum::UInt32(a)) => Ok(RegClass(a)),
2985 _ => Err(res),
2986 }
2987 }
2988}
2989
2990impl<'a, E> OutputDatumType<'a, E> for RegClass {
2991 fn nullable() -> bool {
2992 false
2993 }
2994
2995 fn fallible() -> bool {
2996 false
2997 }
2998
2999 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3000 Ok(Datum::UInt32(self.0))
3001 }
3002}
3003
3004impl AsColumnType for RegProc {
3005 fn as_column_type() -> SqlColumnType {
3006 SqlScalarType::RegProc.nullable(false)
3007 }
3008}
3009
3010impl<'a, E> InputDatumType<'a, E> for RegProc {
3011 fn nullable() -> bool {
3012 false
3013 }
3014
3015 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3016 match res {
3017 Ok(Datum::UInt32(a)) => Ok(RegProc(a)),
3018 _ => Err(res),
3019 }
3020 }
3021}
3022
3023impl<'a, E> OutputDatumType<'a, E> for RegProc {
3024 fn nullable() -> bool {
3025 false
3026 }
3027
3028 fn fallible() -> bool {
3029 false
3030 }
3031
3032 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3033 Ok(Datum::UInt32(self.0))
3034 }
3035}
3036
3037impl AsColumnType for RegType {
3038 fn as_column_type() -> SqlColumnType {
3039 SqlScalarType::RegType.nullable(false)
3040 }
3041}
3042
3043impl<'a, E> InputDatumType<'a, E> for RegType {
3044 fn nullable() -> bool {
3045 false
3046 }
3047
3048 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3049 match res {
3050 Ok(Datum::UInt32(a)) => Ok(RegType(a)),
3051 _ => Err(res),
3052 }
3053 }
3054}
3055
3056impl<'a, E> OutputDatumType<'a, E> for RegType {
3057 fn nullable() -> bool {
3058 false
3059 }
3060
3061 fn fallible() -> bool {
3062 false
3063 }
3064
3065 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3066 Ok(Datum::UInt32(self.0))
3067 }
3068}
3069
3070impl<S> AsColumnType for Char<S>
3071where
3072 S: AsRef<str>,
3073{
3074 fn as_column_type() -> SqlColumnType {
3075 SqlScalarType::Char { length: None }.nullable(false)
3076 }
3077}
3078
3079impl<'a, E> InputDatumType<'a, E> for Char<&'a str> {
3080 fn nullable() -> bool {
3081 false
3082 }
3083
3084 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3085 match res {
3086 Ok(Datum::String(a)) => Ok(Char(a)),
3087 _ => Err(res),
3088 }
3089 }
3090}
3091
3092impl<'a, E> OutputDatumType<'a, E> for Char<&'a str> {
3093 fn nullable() -> bool {
3094 false
3095 }
3096
3097 fn fallible() -> bool {
3098 false
3099 }
3100
3101 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3102 Ok(Datum::String(self.0))
3103 }
3104}
3105
3106impl<'a, E> InputDatumType<'a, E> for Char<String> {
3107 fn nullable() -> bool {
3108 false
3109 }
3110
3111 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3112 match res {
3113 Ok(Datum::String(a)) => Ok(Char(a.to_owned())),
3114 _ => Err(res),
3115 }
3116 }
3117}
3118
3119impl<'a, E> OutputDatumType<'a, E> for Char<String> {
3120 fn nullable() -> bool {
3121 false
3122 }
3123
3124 fn fallible() -> bool {
3125 false
3126 }
3127
3128 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3129 Ok(Datum::String(temp_storage.push_string(self.0)))
3130 }
3131}
3132
3133impl<S> AsColumnType for VarChar<S>
3134where
3135 S: AsRef<str>,
3136{
3137 fn as_column_type() -> SqlColumnType {
3138 SqlScalarType::VarChar { max_length: None }.nullable(false)
3139 }
3140}
3141
3142impl<'a, E> InputDatumType<'a, E> for VarChar<&'a str> {
3143 fn nullable() -> bool {
3144 false
3145 }
3146
3147 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3148 match res {
3149 Ok(Datum::String(a)) => Ok(VarChar(a)),
3150 _ => Err(res),
3151 }
3152 }
3153}
3154
3155impl<'a, E> OutputDatumType<'a, E> for VarChar<&'a str> {
3156 fn nullable() -> bool {
3157 false
3158 }
3159
3160 fn fallible() -> bool {
3161 false
3162 }
3163
3164 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3165 Ok(Datum::String(self.0))
3166 }
3167}
3168
3169impl<'a, E> InputDatumType<'a, E> for VarChar<String> {
3170 fn nullable() -> bool {
3171 false
3172 }
3173
3174 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3175 match res {
3176 Ok(Datum::String(a)) => Ok(VarChar(a.to_owned())),
3177 _ => Err(res),
3178 }
3179 }
3180}
3181
3182impl<'a, E> OutputDatumType<'a, E> for VarChar<String> {
3183 fn nullable() -> bool {
3184 false
3185 }
3186
3187 fn fallible() -> bool {
3188 false
3189 }
3190
3191 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3192 Ok(Datum::String(temp_storage.push_string(self.0)))
3193 }
3194}
3195
3196impl<'a, E> InputDatumType<'a, E> for Jsonb {
3197 fn nullable() -> bool {
3198 false
3199 }
3200
3201 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3202 Ok(JsonbRef::try_from_result(res)?.to_owned())
3203 }
3204}
3205
3206impl<'a, E> OutputDatumType<'a, E> for Jsonb {
3207 fn nullable() -> bool {
3208 false
3209 }
3210
3211 fn fallible() -> bool {
3212 false
3213 }
3214
3215 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3216 Ok(temp_storage.push_unary_row(self.into_row()))
3217 }
3218}
3219
3220impl AsColumnType for Jsonb {
3221 fn as_column_type() -> SqlColumnType {
3222 SqlScalarType::Jsonb.nullable(false)
3223 }
3224}
3225
3226impl<'a, E> InputDatumType<'a, E> for JsonbRef<'a> {
3227 fn nullable() -> bool {
3228 false
3229 }
3230
3231 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3232 match res {
3233 Ok(
3234 d @ (Datum::JsonNull
3235 | Datum::True
3236 | Datum::False
3237 | Datum::Numeric(_)
3238 | Datum::String(_)
3239 | Datum::List(_)
3240 | Datum::Map(_)),
3241 ) => Ok(JsonbRef::from_datum(d)),
3242 _ => Err(res),
3243 }
3244 }
3245}
3246
3247impl<'a, E> OutputDatumType<'a, E> for JsonbRef<'a> {
3248 fn nullable() -> bool {
3249 false
3250 }
3251
3252 fn fallible() -> bool {
3253 false
3254 }
3255
3256 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3257 Ok(self.into_datum())
3258 }
3259}
3260
3261impl<'a> AsColumnType for JsonbRef<'a> {
3262 fn as_column_type() -> SqlColumnType {
3263 SqlScalarType::Jsonb.nullable(false)
3264 }
3265}
3266
3267impl AsColumnType for MzAclItem {
3268 fn as_column_type() -> SqlColumnType {
3269 SqlScalarType::MzAclItem.nullable(false)
3270 }
3271}
3272
3273impl<'a, E> InputDatumType<'a, E> for MzAclItem {
3274 fn nullable() -> bool {
3275 false
3276 }
3277
3278 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3279 match res {
3280 Ok(Datum::MzAclItem(mz_acl_item)) => Ok(mz_acl_item),
3281 _ => Err(res),
3282 }
3283 }
3284}
3285
3286impl<'a, E> OutputDatumType<'a, E> for MzAclItem {
3287 fn nullable() -> bool {
3288 false
3289 }
3290
3291 fn fallible() -> bool {
3292 false
3293 }
3294
3295 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3296 Ok(Datum::MzAclItem(self))
3297 }
3298}
3299
3300impl AsColumnType for AclItem {
3301 fn as_column_type() -> SqlColumnType {
3302 SqlScalarType::AclItem.nullable(false)
3303 }
3304}
3305
3306impl<'a, E> InputDatumType<'a, E> for AclItem {
3307 fn nullable() -> bool {
3308 false
3309 }
3310
3311 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3312 match res {
3313 Ok(Datum::AclItem(acl_item)) => Ok(acl_item),
3314 _ => Err(res),
3315 }
3316 }
3317}
3318
3319impl<'a, E> OutputDatumType<'a, E> for AclItem {
3320 fn nullable() -> bool {
3321 false
3322 }
3323
3324 fn fallible() -> bool {
3325 false
3326 }
3327
3328 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3329 Ok(Datum::AclItem(self))
3330 }
3331}
3332
3333impl AsColumnType for CheckedTimestamp<NaiveDateTime> {
3334 fn as_column_type() -> SqlColumnType {
3335 SqlScalarType::Timestamp { precision: None }.nullable(false)
3336 }
3337}
3338
3339impl<'a, E> InputDatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
3340 fn nullable() -> bool {
3341 false
3342 }
3343
3344 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3345 match res {
3346 Ok(Datum::Timestamp(a)) => Ok(a),
3347 _ => Err(res),
3348 }
3349 }
3350}
3351
3352impl<'a, E> OutputDatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
3353 fn nullable() -> bool {
3354 false
3355 }
3356
3357 fn fallible() -> bool {
3358 false
3359 }
3360
3361 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3362 Ok(Datum::Timestamp(self))
3363 }
3364}
3365
3366impl AsColumnType for CheckedTimestamp<DateTime<Utc>> {
3367 fn as_column_type() -> SqlColumnType {
3368 SqlScalarType::TimestampTz { precision: None }.nullable(false)
3369 }
3370}
3371
3372impl<'a, E> InputDatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
3373 fn nullable() -> bool {
3374 false
3375 }
3376
3377 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3378 match res {
3379 Ok(Datum::TimestampTz(a)) => Ok(a),
3380 _ => Err(res),
3381 }
3382 }
3383}
3384
3385impl<'a, E> OutputDatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
3386 fn nullable() -> bool {
3387 false
3388 }
3389
3390 fn fallible() -> bool {
3391 false
3392 }
3393
3394 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3395 Ok(Datum::TimestampTz(self))
3396 }
3397}
3398
3399impl SqlScalarType {
3400 pub fn unwrap_numeric_max_scale(&self) -> Option<NumericMaxScale> {
3406 match self {
3407 SqlScalarType::Numeric { max_scale } => *max_scale,
3408 _ => panic!("SqlScalarType::unwrap_numeric_scale called on {:?}", self),
3409 }
3410 }
3411
3412 pub fn unwrap_timestamp_precision(&self) -> Option<TimestampPrecision> {
3419 match self {
3420 SqlScalarType::Timestamp { precision } | SqlScalarType::TimestampTz { precision } => {
3421 *precision
3422 }
3423 _ => panic!(
3424 "SqlScalarType::unwrap_timestamp_precision called on {:?}",
3425 self
3426 ),
3427 }
3428 }
3429
3430 pub fn unwrap_list_element_type(&self) -> &SqlScalarType {
3436 match self {
3437 SqlScalarType::List { element_type, .. } => element_type,
3438 _ => panic!(
3439 "SqlScalarType::unwrap_list_element_type called on {:?}",
3440 self
3441 ),
3442 }
3443 }
3444
3445 pub fn unwrap_list_nth_layer_type(&self, layer: usize) -> &SqlScalarType {
3458 if layer == 0 {
3459 return self;
3460 }
3461 match self {
3462 SqlScalarType::List { element_type, .. } => {
3463 element_type.unwrap_list_nth_layer_type(layer - 1)
3464 }
3465 _ => panic!(
3466 "SqlScalarType::unwrap_list_nth_layer_type called on {:?}",
3467 self
3468 ),
3469 }
3470 }
3471
3472 pub fn unwrap_record_element_type(&self) -> Vec<&SqlScalarType> {
3478 match self {
3479 SqlScalarType::Record { fields, .. } => {
3480 fields.iter().map(|(_, t)| &t.scalar_type).collect_vec()
3481 }
3482 _ => panic!(
3483 "SqlScalarType::unwrap_record_element_type called on {:?}",
3484 self
3485 ),
3486 }
3487 }
3488
3489 pub fn unwrap_record_element_column_type(&self) -> Vec<&SqlColumnType> {
3495 match self {
3496 SqlScalarType::Record { fields, .. } => fields.iter().map(|(_, t)| t).collect_vec(),
3497 _ => panic!(
3498 "SqlScalarType::unwrap_record_element_column_type called on {:?}",
3499 self
3500 ),
3501 }
3502 }
3503
3504 pub fn unwrap_list_n_layers(&self) -> usize {
3511 let mut descender = self.unwrap_list_element_type();
3512 let mut layers = 1;
3513
3514 while let SqlScalarType::List { element_type, .. } = descender {
3515 layers += 1;
3516 descender = element_type;
3517 }
3518
3519 layers
3520 }
3521
3522 pub fn without_modifiers(&self) -> SqlScalarType {
3526 use SqlScalarType::*;
3527 match self {
3528 List {
3529 element_type,
3530 custom_id: None,
3531 } => List {
3532 element_type: Box::new(element_type.without_modifiers()),
3533 custom_id: None,
3534 },
3535 Map {
3536 value_type,
3537 custom_id: None,
3538 } => Map {
3539 value_type: Box::new(value_type.without_modifiers()),
3540 custom_id: None,
3541 },
3542 Record {
3543 fields,
3544 custom_id: None,
3545 } => {
3546 let fields = fields
3547 .iter()
3548 .map(|(column_name, column_type)| {
3549 (
3550 column_name.clone(),
3551 SqlColumnType {
3552 scalar_type: column_type.scalar_type.without_modifiers(),
3553 nullable: column_type.nullable,
3554 },
3555 )
3556 })
3557 .collect();
3558 Record {
3559 fields,
3560 custom_id: None,
3561 }
3562 }
3563 Array(a) => Array(Box::new(a.without_modifiers())),
3564 Numeric { .. } => Numeric { max_scale: None },
3565 Char { .. } => Char { length: None },
3568 VarChar { .. } => VarChar { max_length: None },
3569 Range { element_type } => Range {
3570 element_type: Box::new(element_type.without_modifiers()),
3571 },
3572 v => v.clone(),
3573 }
3574 }
3575
3576 pub fn unwrap_array_element_type(&self) -> &SqlScalarType {
3585 match self {
3586 SqlScalarType::Array(s) => &**s,
3587 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3588 _ => panic!(
3589 "SqlScalarType::unwrap_array_element_type called on {:?}",
3590 self
3591 ),
3592 }
3593 }
3594
3595 pub fn unwrap_collection_element_type(&self) -> &SqlScalarType {
3603 match self {
3604 SqlScalarType::Array(element_type) => element_type,
3605 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3606 SqlScalarType::List { element_type, .. } => element_type,
3607 _ => panic!(
3608 "SqlScalarType::unwrap_collection_element_type called on {:?}",
3609 self
3610 ),
3611 }
3612 }
3613
3614 pub fn unwrap_map_value_type(&self) -> &SqlScalarType {
3620 match self {
3621 SqlScalarType::Map { value_type, .. } => &**value_type,
3622 _ => panic!("SqlScalarType::unwrap_map_value_type called on {:?}", self),
3623 }
3624 }
3625
3626 pub fn unwrap_char_length(&self) -> Option<CharLength> {
3632 match self {
3633 SqlScalarType::Char { length, .. } => *length,
3634 _ => panic!("SqlScalarType::unwrap_char_length called on {:?}", self),
3635 }
3636 }
3637
3638 pub fn unwrap_varchar_max_length(&self) -> Option<VarCharMaxLength> {
3644 match self {
3645 SqlScalarType::VarChar { max_length, .. } => *max_length,
3646 _ => panic!(
3647 "SqlScalarType::unwrap_varchar_max_length called on {:?}",
3648 self
3649 ),
3650 }
3651 }
3652
3653 pub fn unwrap_range_element_type(&self) -> &SqlScalarType {
3659 match self {
3660 SqlScalarType::Range { element_type } => &**element_type,
3661 _ => panic!(
3662 "SqlScalarType::unwrap_range_element_type called on {:?}",
3663 self
3664 ),
3665 }
3666 }
3667
3668 pub fn near_match(&self) -> Option<&'static SqlScalarType> {
3692 match self {
3693 SqlScalarType::UInt16 => Some(&SqlScalarType::Int32),
3694 SqlScalarType::UInt32 => Some(&SqlScalarType::Int64),
3695 SqlScalarType::UInt64 => Some(&SqlScalarType::Numeric { max_scale: None }),
3696 _ => None,
3697 }
3698 }
3699
3700 pub const fn nullable(self, nullable: bool) -> SqlColumnType {
3703 SqlColumnType {
3704 nullable,
3705 scalar_type: self,
3706 }
3707 }
3708
3709 pub fn is_vec(&self) -> bool {
3713 matches!(
3714 self,
3715 SqlScalarType::Array(_) | SqlScalarType::Int2Vector | SqlScalarType::List { .. }
3716 )
3717 }
3718
3719 pub fn is_custom_type(&self) -> bool {
3720 use SqlScalarType::*;
3721 match self {
3722 List {
3723 element_type: t,
3724 custom_id,
3725 }
3726 | Map {
3727 value_type: t,
3728 custom_id,
3729 } => custom_id.is_some() || t.is_custom_type(),
3730 Record {
3731 fields, custom_id, ..
3732 } => {
3733 custom_id.is_some()
3734 || fields
3735 .iter()
3736 .map(|(_, t)| t)
3737 .any(|t| t.scalar_type.is_custom_type())
3738 }
3739 _ => false,
3740 }
3741 }
3742
3743 pub fn sql_union(&self, other: &SqlScalarType) -> Result<SqlScalarType, anyhow::Error> {
3753 use SqlScalarType::*;
3754 match (self, other) {
3755 (scalar_type, other_scalar_type) if scalar_type == other_scalar_type => {
3756 Ok(scalar_type.clone())
3757 }
3758 (
3759 Record { fields, custom_id },
3760 Record {
3761 fields: other_fields,
3762 custom_id: other_custom_id,
3763 },
3764 ) if custom_id == other_custom_id && fields.len() == other_fields.len() => {
3765 let mut union_fields = Vec::with_capacity(fields.len());
3766 for ((name, typ), (other_name, other_typ)) in
3767 fields.iter().zip_eq(other_fields.iter())
3768 {
3769 if name != other_name {
3770 bail!("Can't union types: {:?} and {:?}", self, other);
3771 }
3772 union_fields.push((name.clone(), typ.sql_union(other_typ)?));
3773 }
3774 Ok(Record {
3775 fields: union_fields.into(),
3776 custom_id: *custom_id,
3777 })
3778 }
3779 (
3780 List {
3781 element_type,
3782 custom_id,
3783 },
3784 List {
3785 element_type: other_element_type,
3786 custom_id: other_custom_id,
3787 },
3788 ) if custom_id == other_custom_id => Ok(List {
3789 element_type: Box::new(element_type.sql_union(other_element_type)?),
3790 custom_id: *custom_id,
3791 }),
3792 (
3793 Map {
3794 value_type,
3795 custom_id,
3796 },
3797 Map {
3798 value_type: other_value_type,
3799 custom_id: other_custom_id,
3800 },
3801 ) if custom_id == other_custom_id => Ok(Map {
3802 value_type: Box::new(value_type.sql_union(other_value_type)?),
3803 custom_id: *custom_id,
3804 }),
3805 (Array(element_type), Array(other_element_type)) => {
3806 Ok(Array(Box::new(element_type.sql_union(other_element_type)?)))
3807 }
3808 (
3809 Range { element_type },
3810 Range {
3811 element_type: other_element_type,
3812 },
3813 ) => Ok(Range {
3814 element_type: Box::new(element_type.sql_union(other_element_type)?),
3815 }),
3816 (scalar_type, other_scalar_type) if scalar_type.base_eq(other_scalar_type) => {
3817 Ok(scalar_type.without_modifiers())
3818 }
3819 _ => bail!("Can't union types: {:?} and {:?}", self, other),
3820 }
3821 }
3822
3823 pub fn base_eq(&self, other: &SqlScalarType) -> bool {
3836 self.eq_inner(other, false)
3837 }
3838
3839 pub fn structural_eq(&self, other: &SqlScalarType) -> bool {
3842 self.eq_inner(other, true)
3843 }
3844
3845 pub fn eq_inner(&self, other: &SqlScalarType, structure_only: bool) -> bool {
3846 use SqlScalarType::*;
3847 match (self, other) {
3848 (
3849 List {
3850 element_type: l,
3851 custom_id: oid_l,
3852 },
3853 List {
3854 element_type: r,
3855 custom_id: oid_r,
3856 },
3857 )
3858 | (
3859 Map {
3860 value_type: l,
3861 custom_id: oid_l,
3862 },
3863 Map {
3864 value_type: r,
3865 custom_id: oid_r,
3866 },
3867 ) => l.eq_inner(r, structure_only) && (oid_l == oid_r || structure_only),
3868 (Array(a), Array(b)) | (Range { element_type: a }, Range { element_type: b }) => {
3869 a.eq_inner(b, structure_only)
3870 }
3871 (
3872 Record {
3873 fields: fields_a,
3874 custom_id: oid_a,
3875 },
3876 Record {
3877 fields: fields_b,
3878 custom_id: oid_b,
3879 },
3880 ) => {
3881 (oid_a == oid_b || structure_only)
3882 && fields_a.len() == fields_b.len()
3883 && fields_a
3884 .iter()
3885 .zip_eq(fields_b)
3886 .all(|(a, b)| {
3888 (a.0 == b.0 || structure_only)
3889 && a.1.scalar_type.eq_inner(&b.1.scalar_type, structure_only)
3890 })
3891 }
3892 (s, o) => SqlScalarBaseType::from(s) == SqlScalarBaseType::from(o),
3893 }
3894 }
3895
3896 pub fn backport_nullability(&mut self, backport_typ: &ReprScalarType) {
3899 match (self, backport_typ) {
3900 (
3901 SqlScalarType::List { element_type, .. },
3902 ReprScalarType::List {
3903 element_type: backport_element_type,
3904 ..
3905 },
3906 ) => {
3907 element_type.backport_nullability(backport_element_type);
3908 }
3909 (
3910 SqlScalarType::Map { value_type, .. },
3911 ReprScalarType::Map {
3912 value_type: backport_value_type,
3913 ..
3914 },
3915 ) => {
3916 value_type.backport_nullability(backport_value_type);
3917 }
3918 (
3919 SqlScalarType::Record { fields, .. },
3920 ReprScalarType::Record {
3921 fields: backport_fields,
3922 ..
3923 },
3924 ) => {
3925 assert_eq!(
3926 fields.len(),
3927 backport_fields.len(),
3928 "HIR and MIR types should have the same number of fields"
3929 );
3930 fields
3931 .iter_mut()
3932 .zip_eq(backport_fields)
3933 .for_each(|(field, backport_field)| {
3934 field.1.backport_nullability(backport_field);
3935 });
3936 }
3937 (SqlScalarType::Array(a), ReprScalarType::Array(b)) => {
3938 a.backport_nullability(b);
3939 }
3940 (
3941 SqlScalarType::Range { element_type },
3942 ReprScalarType::Range {
3943 element_type: backport_element_type,
3944 },
3945 ) => {
3946 element_type.backport_nullability(backport_element_type);
3947 }
3948 _ => (),
3949 }
3950 }
3951
3952 pub fn interesting_datums(&self) -> impl Iterator<Item = Datum<'static>> {
3954 static BOOL: LazyLock<Row> =
3960 LazyLock::new(|| Row::pack_slice(&[Datum::True, Datum::False]));
3961 static INT16: LazyLock<Row> = LazyLock::new(|| {
3962 Row::pack_slice(&[
3963 Datum::Int16(0),
3964 Datum::Int16(1),
3965 Datum::Int16(-1),
3966 Datum::Int16(i16::MIN),
3967 Datum::Int16(i16::MIN + 1),
3968 Datum::Int16(i16::MAX),
3969 Datum::Int16(127),
3977 Datum::Int16(128),
3978 ])
3979 });
3980 static INT32: LazyLock<Row> = LazyLock::new(|| {
3981 Row::pack_slice(&[
3982 Datum::Int32(0),
3983 Datum::Int32(1),
3984 Datum::Int32(-1),
3985 Datum::Int32(i32::MIN),
3986 Datum::Int32(i32::MIN + 1),
3987 Datum::Int32(i32::MAX),
3988 Datum::Int32(32767),
3992 Datum::Int32(32768),
3993 ])
3994 });
3995 static INT64: LazyLock<Row> = LazyLock::new(|| {
3996 Row::pack_slice(&[
3997 Datum::Int64(0),
3998 Datum::Int64(1),
3999 Datum::Int64(-1),
4000 Datum::Int64(i64::MIN),
4001 Datum::Int64(i64::MIN + 1),
4002 Datum::Int64(i64::MAX),
4003 Datum::Int64(2147483647),
4007 Datum::Int64(2147483648),
4008 ])
4009 });
4010 static UINT16: LazyLock<Row> = LazyLock::new(|| {
4011 Row::pack_slice(&[
4012 Datum::UInt16(0),
4013 Datum::UInt16(1),
4014 Datum::UInt16(u16::MAX),
4015 Datum::UInt16(255),
4019 Datum::UInt16(256),
4020 ])
4021 });
4022 static UINT32: LazyLock<Row> = LazyLock::new(|| {
4023 Row::pack_slice(&[
4024 Datum::UInt32(0),
4025 Datum::UInt32(1),
4026 Datum::UInt32(u32::MAX),
4027 Datum::UInt32(32767),
4031 Datum::UInt32(32768),
4032 ])
4033 });
4034 static UINT64: LazyLock<Row> = LazyLock::new(|| {
4035 Row::pack_slice(&[
4036 Datum::UInt64(0),
4037 Datum::UInt64(1),
4038 Datum::UInt64(u64::MAX),
4039 Datum::UInt64(2147483647),
4043 Datum::UInt64(2147483648),
4044 ])
4045 });
4046 static FLOAT32: LazyLock<Row> = LazyLock::new(|| {
4047 Row::pack_slice(&[
4048 Datum::Float32(OrderedFloat(0.0)),
4049 Datum::Float32(OrderedFloat(1.0)),
4050 Datum::Float32(OrderedFloat(-1.0)),
4051 Datum::Float32(OrderedFloat(f32::MIN)),
4052 Datum::Float32(OrderedFloat(f32::MIN_POSITIVE)),
4053 Datum::Float32(OrderedFloat(f32::MAX)),
4054 Datum::Float32(OrderedFloat(f32::EPSILON)),
4055 Datum::Float32(OrderedFloat(f32::NAN)),
4056 Datum::Float32(OrderedFloat(f32::INFINITY)),
4057 Datum::Float32(OrderedFloat(f32::NEG_INFINITY)),
4058 ])
4059 });
4060 static FLOAT64: LazyLock<Row> = LazyLock::new(|| {
4061 Row::pack_slice(&[
4062 Datum::Float64(OrderedFloat(0.0)),
4063 Datum::Float64(OrderedFloat(1.0)),
4064 Datum::Float64(OrderedFloat(-1.0)),
4065 Datum::Float64(OrderedFloat(f64::MIN)),
4066 Datum::Float64(OrderedFloat(f64::MIN_POSITIVE)),
4067 Datum::Float64(OrderedFloat(f64::MAX)),
4068 Datum::Float64(OrderedFloat(f64::EPSILON)),
4069 Datum::Float64(OrderedFloat(f64::NAN)),
4070 Datum::Float64(OrderedFloat(f64::INFINITY)),
4071 Datum::Float64(OrderedFloat(f64::NEG_INFINITY)),
4072 ])
4073 });
4074 static NUMERIC: LazyLock<Row> = LazyLock::new(|| {
4075 cfg_if::cfg_if! {
4076 if #[cfg(miri)] {
4078 Row::pack_slice(&[])
4079 } else {
4080 Row::pack_slice(&[
4081 Datum::Numeric(OrderedDecimal(Numeric::from(0.0))),
4082 Datum::Numeric(OrderedDecimal(Numeric::from(1.0))),
4083 Datum::Numeric(OrderedDecimal(Numeric::from(-1.0))),
4084 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN))),
4085 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN_POSITIVE))),
4086 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MAX))),
4087 Datum::Numeric(OrderedDecimal(Numeric::from(f64::EPSILON))),
4088 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NAN))),
4089 Datum::Numeric(OrderedDecimal(Numeric::from(f64::INFINITY))),
4090 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NEG_INFINITY))),
4091 ])
4092 }
4093 }
4094 });
4095 static DATE: LazyLock<Row> = LazyLock::new(|| {
4096 Row::pack_slice(&[
4097 Datum::Date(Date::from_pg_epoch(0).unwrap()),
4098 Datum::Date(Date::from_pg_epoch(Date::LOW_DAYS).unwrap()),
4099 Datum::Date(Date::from_pg_epoch(Date::HIGH_DAYS).unwrap()),
4100 ])
4101 });
4102 static TIME: LazyLock<Row> = LazyLock::new(|| {
4103 Row::pack_slice(&[
4104 Datum::Time(NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap()),
4105 Datum::Time(NaiveTime::from_hms_micro_opt(23, 59, 59, 999_999).unwrap()),
4106 ])
4107 });
4108 static TIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
4109 Row::pack_slice(&[
4110 Datum::Timestamp(
4111 DateTime::from_timestamp(0, 0)
4112 .unwrap()
4113 .naive_utc()
4114 .try_into()
4115 .unwrap(),
4116 ),
4117 Datum::Timestamp(
4118 crate::adt::timestamp::LOW_DATE
4119 .and_hms_opt(0, 0, 0)
4120 .unwrap()
4121 .try_into()
4122 .unwrap(),
4123 ),
4124 Datum::Timestamp(
4125 crate::adt::timestamp::HIGH_DATE
4126 .and_hms_opt(23, 59, 59)
4127 .unwrap()
4128 .try_into()
4129 .unwrap(),
4130 ),
4131 Datum::Timestamp(
4133 DateTime::from_timestamp(0, 123456789)
4134 .unwrap()
4135 .naive_utc()
4136 .try_into()
4137 .unwrap(),
4138 ),
4139 Datum::Timestamp(
4141 CheckedTimestamp::from_timestamplike(
4142 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
4143 .unwrap()
4144 .and_hms_milli_opt(23, 59, 59, 1234)
4145 .unwrap(),
4146 )
4147 .unwrap(),
4148 ),
4149 ])
4150 });
4151 static TIMESTAMPTZ: LazyLock<Row> = LazyLock::new(|| {
4152 Row::pack_slice(&[
4153 Datum::TimestampTz(DateTime::from_timestamp(0, 0).unwrap().try_into().unwrap()),
4154 Datum::TimestampTz(
4155 DateTime::from_naive_utc_and_offset(
4156 crate::adt::timestamp::LOW_DATE
4157 .and_hms_opt(0, 0, 0)
4158 .unwrap(),
4159 Utc,
4160 )
4161 .try_into()
4162 .unwrap(),
4163 ),
4164 Datum::TimestampTz(
4165 DateTime::from_naive_utc_and_offset(
4166 crate::adt::timestamp::HIGH_DATE
4167 .and_hms_opt(23, 59, 59)
4168 .unwrap(),
4169 Utc,
4170 )
4171 .try_into()
4172 .unwrap(),
4173 ),
4174 Datum::TimestampTz(
4176 DateTime::from_timestamp(0, 123456789)
4177 .unwrap()
4178 .try_into()
4179 .unwrap(),
4180 ),
4181 ])
4182 });
4183 static INTERVAL: LazyLock<Row> = LazyLock::new(|| {
4184 Row::pack_slice(&[
4185 Datum::Interval(Interval::new(0, 0, 0)),
4186 Datum::Interval(Interval::new(1, 1, 1)),
4187 Datum::Interval(Interval::new(-1, -1, -1)),
4188 Datum::Interval(Interval::new(1, 0, 0)),
4189 Datum::Interval(Interval::new(0, 1, 0)),
4190 Datum::Interval(Interval::new(0, 0, 1)),
4191 Datum::Interval(Interval::new(-1, 0, 0)),
4192 Datum::Interval(Interval::new(0, -1, 0)),
4193 Datum::Interval(Interval::new(0, 0, -1)),
4194 Datum::Interval(Interval::new(i32::MIN, i32::MIN, i64::MIN)),
4195 Datum::Interval(Interval::new(i32::MAX, i32::MAX, i64::MAX)),
4196 Datum::Interval(Interval::new(i32::MIN, 0, 0)),
4197 Datum::Interval(Interval::new(i32::MAX, 0, 0)),
4198 Datum::Interval(Interval::new(0, i32::MIN, 0)),
4199 Datum::Interval(Interval::new(0, i32::MAX, 0)),
4200 Datum::Interval(Interval::new(0, 0, i64::MIN)),
4201 Datum::Interval(Interval::new(0, 0, i64::MAX)),
4202 ])
4203 });
4204 static PGLEGACYCHAR: LazyLock<Row> =
4205 LazyLock::new(|| Row::pack_slice(&[Datum::UInt8(u8::MIN), Datum::UInt8(u8::MAX)]));
4206 static PGLEGACYNAME: LazyLock<Row> = LazyLock::new(|| {
4207 Row::pack_slice(&[
4208 Datum::String(""),
4209 Datum::String(" "),
4210 Datum::String("'"),
4211 Datum::String("\""),
4212 Datum::String("."),
4213 Datum::String(&"x".repeat(64)),
4214 ])
4215 });
4216 static BYTES: LazyLock<Row> = LazyLock::new(|| {
4217 Row::pack_slice(&[Datum::Bytes(&[]), Datum::Bytes(&[0]), Datum::Bytes(&[255])])
4218 });
4219 static STRING: LazyLock<Row> = LazyLock::new(|| {
4220 Row::pack_slice(&[
4221 Datum::String(""),
4222 Datum::String(" "),
4223 Datum::String("'"),
4224 Datum::String("\""),
4225 Datum::String("."),
4226 Datum::String("2015-09-18T23:56:04.123Z"),
4227 Datum::String(&"x".repeat(100)),
4228 Datum::String("JAPAN"),
4230 Datum::String("1,2,3"),
4231 Datum::String("\r\n"),
4232 Datum::String("\"\""),
4233 ])
4234 });
4235 static CHAR: LazyLock<Row> = LazyLock::new(|| {
4236 Row::pack_slice(&[
4237 Datum::String(" "),
4238 Datum::String("'"),
4239 Datum::String("\""),
4240 Datum::String("."),
4241 Datum::String(","),
4242 Datum::String("\t"),
4243 Datum::String("\n"),
4244 Datum::String("\r"),
4245 Datum::String("\\"),
4246 Datum::String(std::str::from_utf8(b"\x00").unwrap()),
4248 Datum::String(std::str::from_utf8(b"\x02").unwrap()),
4250 Datum::String(std::str::from_utf8(b"\x03").unwrap()),
4252 Datum::String(std::str::from_utf8(b"\x08").unwrap()),
4254 Datum::String(std::str::from_utf8(b"\x1B").unwrap()),
4256 Datum::String(std::str::from_utf8(b"\x7F").unwrap()),
4258 ])
4259 });
4260 static JSONB: LazyLock<Row> = LazyLock::new(|| {
4261 let mut datums = vec![Datum::True, Datum::False, Datum::JsonNull];
4262 datums.extend(STRING.iter());
4263 datums.extend(NUMERIC.iter().filter(|n| {
4264 let Datum::Numeric(n) = n else {
4265 panic!("expected Numeric, found {n:?}");
4266 };
4267 !(n.0.is_nan() || n.0.is_infinite())
4269 }));
4270 Row::pack_slice(&datums)
4272 });
4273 static UUID: LazyLock<Row> = LazyLock::new(|| {
4274 Row::pack_slice(&[
4275 Datum::Uuid(Uuid::from_u128(u128::MIN)),
4276 Datum::Uuid(Uuid::from_u128(u128::MAX)),
4277 ])
4278 });
4279 static ARRAY: LazyLock<BTreeMap<&'static SqlScalarType, Row>> = LazyLock::new(|| {
4280 let generate_row = |inner_type: &SqlScalarType| {
4281 let datums: Vec<_> = inner_type.interesting_datums().collect();
4282
4283 let mut row = Row::default();
4284 row.packer()
4285 .try_push_array::<_, Datum<'static>>(
4286 &[ArrayDimension {
4287 lower_bound: 1,
4288 length: 0,
4289 }],
4290 [],
4291 )
4292 .expect("failed to push empty array");
4293 row.packer()
4294 .try_push_array(
4295 &[ArrayDimension {
4296 lower_bound: 1,
4297 length: datums.len(),
4298 }],
4299 datums,
4300 )
4301 .expect("failed to push array");
4302
4303 row
4304 };
4305
4306 SqlScalarType::enumerate()
4307 .into_iter()
4308 .filter(|ty| !matches!(ty, SqlScalarType::Array(_)))
4309 .map(|ty| (ty, generate_row(ty)))
4310 .collect()
4311 });
4312 static EMPTY_ARRAY: LazyLock<Row> = LazyLock::new(|| {
4313 let mut row = Row::default();
4314 row.packer()
4315 .try_push_array::<_, Datum<'static>>(
4316 &[ArrayDimension {
4317 lower_bound: 1,
4318 length: 0,
4319 }],
4320 [],
4321 )
4322 .expect("failed to push empty array");
4323 row
4324 });
4325 static LIST: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4326 static RECORD: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4327 static OID: LazyLock<Row> =
4328 LazyLock::new(|| Row::pack_slice(&[Datum::UInt32(u32::MIN), Datum::UInt32(u32::MAX)]));
4329 static MAP: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4330 static INT2VECTOR: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4331 static MZTIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
4332 Row::pack_slice(&[
4333 Datum::MzTimestamp(crate::Timestamp::MIN),
4334 Datum::MzTimestamp(crate::Timestamp::MAX),
4335 ])
4336 });
4337 static RANGE: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4338 static MZACLITEM: LazyLock<Row> = LazyLock::new(|| {
4339 Row::pack_slice(&[
4340 Datum::MzAclItem(MzAclItem {
4341 grantee: RoleId::Public,
4342 grantor: RoleId::Public,
4343 acl_mode: AclMode::empty(),
4344 }),
4345 Datum::MzAclItem(MzAclItem {
4346 grantee: RoleId::Public,
4347 grantor: RoleId::Public,
4348 acl_mode: AclMode::all(),
4349 }),
4350 Datum::MzAclItem(MzAclItem {
4351 grantee: RoleId::User(42),
4352 grantor: RoleId::Public,
4353 acl_mode: AclMode::empty(),
4354 }),
4355 Datum::MzAclItem(MzAclItem {
4356 grantee: RoleId::User(42),
4357 grantor: RoleId::Public,
4358 acl_mode: AclMode::all(),
4359 }),
4360 Datum::MzAclItem(MzAclItem {
4361 grantee: RoleId::Public,
4362 grantor: RoleId::User(42),
4363 acl_mode: AclMode::empty(),
4364 }),
4365 Datum::MzAclItem(MzAclItem {
4366 grantee: RoleId::Public,
4367 grantor: RoleId::User(42),
4368 acl_mode: AclMode::all(),
4369 }),
4370 ])
4371 });
4372 static ACLITEM: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4374
4375 let iter: Box<dyn Iterator<Item = Datum<'static>>> = match self {
4376 SqlScalarType::Bool => Box::new((*BOOL).iter()),
4377 SqlScalarType::Int16 => Box::new((*INT16).iter()),
4378 SqlScalarType::Int32 => Box::new((*INT32).iter()),
4379 SqlScalarType::Int64 => Box::new((*INT64).iter()),
4380 SqlScalarType::UInt16 => Box::new((*UINT16).iter()),
4381 SqlScalarType::UInt32 => Box::new((*UINT32).iter()),
4382 SqlScalarType::UInt64 => Box::new((*UINT64).iter()),
4383 SqlScalarType::Float32 => Box::new((*FLOAT32).iter()),
4384 SqlScalarType::Float64 => Box::new((*FLOAT64).iter()),
4385 SqlScalarType::Numeric { .. } => Box::new((*NUMERIC).iter()),
4386 SqlScalarType::Date => Box::new((*DATE).iter()),
4387 SqlScalarType::Time => Box::new((*TIME).iter()),
4388 SqlScalarType::Timestamp { .. } => Box::new((*TIMESTAMP).iter()),
4389 SqlScalarType::TimestampTz { .. } => Box::new((*TIMESTAMPTZ).iter()),
4390 SqlScalarType::Interval => Box::new((*INTERVAL).iter()),
4391 SqlScalarType::PgLegacyChar => Box::new((*PGLEGACYCHAR).iter()),
4392 SqlScalarType::PgLegacyName => Box::new((*PGLEGACYNAME).iter()),
4393 SqlScalarType::Bytes => Box::new((*BYTES).iter()),
4394 SqlScalarType::String => Box::new((*STRING).iter().chain((*CHAR).iter())),
4395 SqlScalarType::Char { .. } => Box::new((*CHAR).iter()),
4396 SqlScalarType::VarChar { .. } => Box::new((*STRING).iter().chain((*CHAR).iter())),
4397 SqlScalarType::Jsonb => Box::new((*JSONB).iter()),
4398 SqlScalarType::Uuid => Box::new((*UUID).iter()),
4399 SqlScalarType::Array(inner_type) => {
4400 if matches!(inner_type.as_ref(), SqlScalarType::Array(_)) {
4401 panic!("SqlScalarType::Array cannot have a nested Array");
4402 }
4403
4404 Box::new(
4405 (*ARRAY)
4406 .get(inner_type.as_ref())
4407 .unwrap_or(&*EMPTY_ARRAY)
4408 .iter(),
4409 )
4410 }
4411 SqlScalarType::List { .. } => Box::new((*LIST).iter()),
4412 SqlScalarType::Record { .. } => Box::new((*RECORD).iter()),
4413 SqlScalarType::Oid => Box::new((*OID).iter()),
4414 SqlScalarType::Map { .. } => Box::new((*MAP).iter()),
4415 SqlScalarType::RegProc => Box::new((*OID).iter()),
4416 SqlScalarType::RegType => Box::new((*OID).iter()),
4417 SqlScalarType::RegClass => Box::new((*OID).iter()),
4418 SqlScalarType::Int2Vector => Box::new((*INT2VECTOR).iter()),
4419 SqlScalarType::MzTimestamp => Box::new((*MZTIMESTAMP).iter()),
4420 SqlScalarType::Range { .. } => Box::new((*RANGE).iter()),
4421 SqlScalarType::MzAclItem { .. } => Box::new((*MZACLITEM).iter()),
4422 SqlScalarType::AclItem { .. } => Box::new((*ACLITEM).iter()),
4423 };
4424
4425 iter
4426 }
4427
4428 pub fn enumerate() -> &'static [Self] {
4431 &[
4434 SqlScalarType::Bool,
4435 SqlScalarType::Int16,
4436 SqlScalarType::Int32,
4437 SqlScalarType::Int64,
4438 SqlScalarType::UInt16,
4439 SqlScalarType::UInt32,
4440 SqlScalarType::UInt64,
4441 SqlScalarType::Float32,
4442 SqlScalarType::Float64,
4443 SqlScalarType::Numeric {
4444 max_scale: Some(NumericMaxScale(
4445 crate::adt::numeric::NUMERIC_DATUM_MAX_PRECISION,
4446 )),
4447 },
4448 SqlScalarType::Date,
4449 SqlScalarType::Time,
4450 SqlScalarType::Timestamp {
4451 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
4452 },
4453 SqlScalarType::Timestamp {
4454 precision: Some(TimestampPrecision(0)),
4455 },
4456 SqlScalarType::Timestamp { precision: None },
4457 SqlScalarType::TimestampTz {
4458 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
4459 },
4460 SqlScalarType::TimestampTz {
4461 precision: Some(TimestampPrecision(0)),
4462 },
4463 SqlScalarType::TimestampTz { precision: None },
4464 SqlScalarType::Interval,
4465 SqlScalarType::PgLegacyChar,
4466 SqlScalarType::Bytes,
4467 SqlScalarType::String,
4468 SqlScalarType::Char {
4469 length: Some(CharLength(1)),
4470 },
4471 SqlScalarType::VarChar { max_length: None },
4472 SqlScalarType::Jsonb,
4473 SqlScalarType::Uuid,
4474 SqlScalarType::Oid,
4475 SqlScalarType::RegProc,
4476 SqlScalarType::RegType,
4477 SqlScalarType::RegClass,
4478 SqlScalarType::Int2Vector,
4479 SqlScalarType::MzTimestamp,
4480 SqlScalarType::MzAclItem,
4481 ]
4502 }
4503
4504 pub fn array_of_self_elem_type(self) -> Result<SqlScalarType, SqlScalarType> {
4509 match self {
4510 t @ (SqlScalarType::AclItem
4511 | SqlScalarType::Bool
4512 | SqlScalarType::Int16
4513 | SqlScalarType::Int32
4514 | SqlScalarType::Int64
4515 | SqlScalarType::UInt16
4516 | SqlScalarType::UInt32
4517 | SqlScalarType::UInt64
4518 | SqlScalarType::Float32
4519 | SqlScalarType::Float64
4520 | SqlScalarType::Numeric { .. }
4521 | SqlScalarType::Date
4522 | SqlScalarType::Time
4523 | SqlScalarType::Timestamp { .. }
4524 | SqlScalarType::TimestampTz { .. }
4525 | SqlScalarType::Interval
4526 | SqlScalarType::PgLegacyChar
4527 | SqlScalarType::PgLegacyName
4528 | SqlScalarType::Bytes
4529 | SqlScalarType::String
4530 | SqlScalarType::VarChar { .. }
4531 | SqlScalarType::Jsonb
4532 | SqlScalarType::Uuid
4533 | SqlScalarType::Record { .. }
4534 | SqlScalarType::Oid
4535 | SqlScalarType::RegProc
4536 | SqlScalarType::RegType
4537 | SqlScalarType::RegClass
4538 | SqlScalarType::Int2Vector
4539 | SqlScalarType::MzTimestamp
4540 | SqlScalarType::Range { .. }
4541 | SqlScalarType::MzAclItem { .. }) => Ok(t),
4542
4543 SqlScalarType::Array(elem) => Ok(elem.array_of_self_elem_type()?),
4544
4545 t @ (SqlScalarType::Char { .. }
4547 | SqlScalarType::Map { .. }
4549 | SqlScalarType::List { .. }) => Err(t),
4550 }
4551 }
4552}
4553
4554#[cfg(any(test, feature = "proptest"))]
4557impl Arbitrary for SqlScalarType {
4558 type Parameters = ();
4559 type Strategy = BoxedStrategy<SqlScalarType>;
4560
4561 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
4562 let leaf = Union::new(vec![
4564 Just(SqlScalarType::Bool).boxed(),
4565 Just(SqlScalarType::UInt16).boxed(),
4566 Just(SqlScalarType::UInt32).boxed(),
4567 Just(SqlScalarType::UInt64).boxed(),
4568 Just(SqlScalarType::Int16).boxed(),
4569 Just(SqlScalarType::Int32).boxed(),
4570 Just(SqlScalarType::Int64).boxed(),
4571 Just(SqlScalarType::Float32).boxed(),
4572 Just(SqlScalarType::Float64).boxed(),
4573 any::<Option<NumericMaxScale>>()
4574 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
4575 .boxed(),
4576 Just(SqlScalarType::Date).boxed(),
4577 Just(SqlScalarType::Time).boxed(),
4578 any::<Option<TimestampPrecision>>()
4579 .prop_map(|precision| SqlScalarType::Timestamp { precision })
4580 .boxed(),
4581 any::<Option<TimestampPrecision>>()
4582 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
4583 .boxed(),
4584 Just(SqlScalarType::MzTimestamp).boxed(),
4585 Just(SqlScalarType::Interval).boxed(),
4586 Just(SqlScalarType::PgLegacyChar).boxed(),
4587 Just(SqlScalarType::Bytes).boxed(),
4588 Just(SqlScalarType::String).boxed(),
4589 any::<Option<CharLength>>()
4590 .prop_map(|length| SqlScalarType::Char { length })
4591 .boxed(),
4592 any::<Option<VarCharMaxLength>>()
4593 .prop_map(|max_length| SqlScalarType::VarChar { max_length })
4594 .boxed(),
4595 Just(SqlScalarType::PgLegacyName).boxed(),
4596 Just(SqlScalarType::Jsonb).boxed(),
4597 Just(SqlScalarType::Uuid).boxed(),
4598 Just(SqlScalarType::AclItem).boxed(),
4599 Just(SqlScalarType::MzAclItem).boxed(),
4600 Just(SqlScalarType::Oid).boxed(),
4601 Just(SqlScalarType::RegProc).boxed(),
4602 Just(SqlScalarType::RegType).boxed(),
4603 Just(SqlScalarType::RegClass).boxed(),
4604 Just(SqlScalarType::Int2Vector).boxed(),
4605 ])
4606 .no_shrink()
4609 .boxed();
4610
4611 let range_leaf = Union::new(vec![
4613 Just(SqlScalarType::Int32).boxed(),
4614 Just(SqlScalarType::Int64).boxed(),
4615 Just(SqlScalarType::Date).boxed(),
4616 any::<Option<NumericMaxScale>>()
4617 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
4618 .boxed(),
4619 any::<Option<TimestampPrecision>>()
4620 .prop_map(|precision| SqlScalarType::Timestamp { precision })
4621 .boxed(),
4622 any::<Option<TimestampPrecision>>()
4623 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
4624 .boxed(),
4625 ]);
4626 let range = range_leaf
4627 .prop_map(|inner_type| SqlScalarType::Range {
4628 element_type: Box::new(inner_type),
4629 })
4630 .boxed();
4631
4632 let array = leaf
4634 .clone()
4635 .prop_map(|inner_type| SqlScalarType::Array(Box::new(inner_type)))
4636 .boxed();
4637
4638 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
4639
4640 leaf.prop_recursive(2, 3, 5, |inner| {
4641 Union::new(vec![
4642 (inner.clone(), any::<Option<CatalogItemId>>())
4644 .prop_map(|(x, id)| SqlScalarType::List {
4645 element_type: Box::new(x),
4646 custom_id: id,
4647 })
4648 .boxed(),
4649 (inner.clone(), any::<Option<CatalogItemId>>())
4651 .prop_map(|(x, id)| SqlScalarType::Map {
4652 value_type: Box::new(x),
4653 custom_id: id,
4654 })
4655 .boxed(),
4656 {
4658 let column_type_strat =
4661 (inner, any::<bool>()).prop_map(|(scalar_type, nullable)| SqlColumnType {
4662 scalar_type,
4663 nullable,
4664 });
4665
4666 let fields_strat =
4669 prop::collection::vec((any::<ColumnName>(), column_type_strat), 0..10);
4670
4671 (fields_strat, any::<Option<CatalogItemId>>())
4673 .prop_map(|(fields, custom_id)| SqlScalarType::Record {
4674 fields: fields.into(),
4675 custom_id,
4676 })
4677 .boxed()
4678 },
4679 ])
4680 })
4681 .boxed()
4682 }
4683}
4684
4685#[cfg(any(test, feature = "proptest"))]
4686impl Arbitrary for ReprScalarType {
4687 type Parameters = ();
4688 type Strategy = BoxedStrategy<ReprScalarType>;
4689
4690 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
4691 let leaf = Union::new(vec![
4693 Just(ReprScalarType::Bool).boxed(),
4694 Just(ReprScalarType::UInt8).boxed(),
4695 Just(ReprScalarType::UInt16).boxed(),
4696 Just(ReprScalarType::UInt32).boxed(),
4697 Just(ReprScalarType::UInt64).boxed(),
4698 Just(ReprScalarType::Int16).boxed(),
4699 Just(ReprScalarType::Int32).boxed(),
4700 Just(ReprScalarType::Int64).boxed(),
4701 Just(ReprScalarType::Float32).boxed(),
4702 Just(ReprScalarType::Float64).boxed(),
4703 Just(ReprScalarType::Numeric).boxed(),
4704 Just(ReprScalarType::Date).boxed(),
4705 Just(ReprScalarType::Time).boxed(),
4706 Just(ReprScalarType::Timestamp).boxed(),
4707 Just(ReprScalarType::TimestampTz).boxed(),
4708 Just(ReprScalarType::MzTimestamp).boxed(),
4709 Just(ReprScalarType::Interval).boxed(),
4710 Just(ReprScalarType::Bytes).boxed(),
4711 Just(ReprScalarType::String).boxed(),
4712 Just(ReprScalarType::Jsonb).boxed(),
4713 Just(ReprScalarType::Uuid).boxed(),
4714 Just(ReprScalarType::AclItem).boxed(),
4715 Just(ReprScalarType::MzAclItem).boxed(),
4716 Just(ReprScalarType::Int2Vector).boxed(),
4717 ])
4718 .no_shrink()
4721 .boxed();
4722
4723 let range_leaf = Union::new(vec![
4725 Just(ReprScalarType::Int32).boxed(),
4726 Just(ReprScalarType::Int64).boxed(),
4727 Just(ReprScalarType::Date).boxed(),
4728 Just(ReprScalarType::Numeric).boxed(),
4729 Just(ReprScalarType::Timestamp).boxed(),
4730 Just(ReprScalarType::TimestampTz).boxed(),
4731 ]);
4732 let range = range_leaf
4733 .prop_map(|inner_type| ReprScalarType::Range {
4734 element_type: Box::new(inner_type),
4735 })
4736 .boxed();
4737
4738 let array = leaf
4740 .clone()
4741 .prop_map(|inner_type| ReprScalarType::Array(Box::new(inner_type)))
4742 .boxed();
4743
4744 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
4745
4746 leaf.prop_recursive(2, 3, 5, |inner| {
4747 Union::new(vec![
4748 inner
4750 .clone()
4751 .prop_map(|x| ReprScalarType::List {
4752 element_type: Box::new(x),
4753 })
4754 .boxed(),
4755 inner
4757 .clone()
4758 .prop_map(|x| ReprScalarType::Map {
4759 value_type: Box::new(x),
4760 })
4761 .boxed(),
4762 {
4764 let column_type_strat =
4767 (inner.clone(), any::<bool>()).prop_map(|(scalar_type, nullable)| {
4768 ReprColumnType {
4769 scalar_type,
4770 nullable,
4771 }
4772 });
4773
4774 let fields_strat = prop::collection::vec(column_type_strat, 0..10);
4777
4778 fields_strat
4780 .prop_map(|fields| ReprScalarType::Record {
4781 fields: fields.into_boxed_slice(),
4782 })
4783 .boxed()
4784 },
4785 ])
4786 })
4787 .boxed()
4788 }
4789}
4790
4791#[derive(Clone, Debug, EnumKind, Serialize, Deserialize)]
4802#[enum_kind(ReprScalarBaseType, derive(PartialOrd, Ord, Hash))]
4803pub enum ReprScalarType {
4804 Bool,
4805 Int16,
4806 Int32,
4807 Int64,
4808 UInt8, UInt16,
4810 UInt32, UInt64,
4812 Float32,
4813 Float64,
4814 Numeric,
4815 Date,
4816 Time,
4817 Timestamp,
4818 TimestampTz,
4819 MzTimestamp,
4820 Interval,
4821 Bytes,
4822 Jsonb,
4823 String, Uuid,
4825 Array(Box<ReprScalarType>),
4826 Int2Vector, List { element_type: Box<ReprScalarType> },
4828 Record { fields: Box<[ReprColumnType]> },
4829 Map { value_type: Box<ReprScalarType> },
4830 Range { element_type: Box<ReprScalarType> },
4831 MzAclItem,
4832 AclItem,
4833}
4834
4835impl PartialEq for ReprScalarType {
4836 fn eq(&self, other: &Self) -> bool {
4837 match (self, other) {
4838 (ReprScalarType::Array(a), ReprScalarType::Array(b)) => a.eq(b),
4839 (
4840 ReprScalarType::List { element_type: a },
4841 ReprScalarType::List { element_type: b },
4842 ) => a.eq(b),
4843 (ReprScalarType::Record { fields: a }, ReprScalarType::Record { fields: b }) => {
4844 a.len() == b.len()
4845 && a.iter()
4846 .zip_eq(b.iter())
4847 .all(|(af, bf)| af.scalar_type.eq(&bf.scalar_type))
4848 }
4849 (ReprScalarType::Map { value_type: a }, ReprScalarType::Map { value_type: b }) => {
4850 a.eq(b)
4851 }
4852 (
4853 ReprScalarType::Range { element_type: a },
4854 ReprScalarType::Range { element_type: b },
4855 ) => a.eq(b),
4856 _ => ReprScalarBaseType::from(self) == ReprScalarBaseType::from(other),
4857 }
4858 }
4859}
4860impl Eq for ReprScalarType {}
4861
4862impl Hash for ReprScalarType {
4863 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
4864 match self {
4865 ReprScalarType::Array(a) => a.hash(state),
4866 ReprScalarType::List { element_type: a } => a.hash(state),
4867 ReprScalarType::Record { fields: a } => {
4868 for field in a {
4869 field.scalar_type.hash(state);
4870 }
4871 }
4872 ReprScalarType::Map { value_type: a } => a.hash(state),
4873 ReprScalarType::Range { element_type: a } => a.hash(state),
4874 _ => ReprScalarBaseType::from(self).hash(state),
4875 }
4876 }
4877}
4878
4879impl PartialOrd for ReprScalarType {
4880 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
4881 Some(self.cmp(other))
4882 }
4883}
4884
4885impl Ord for ReprScalarType {
4886 fn cmp(&self, other: &Self) -> Ordering {
4887 match (self, other) {
4888 (ReprScalarType::Array(a), ReprScalarType::Array(b)) => a.cmp(b),
4889 (
4890 ReprScalarType::List { element_type: a },
4891 ReprScalarType::List { element_type: b },
4892 ) => a.cmp(b),
4893 (ReprScalarType::Record { fields: a }, ReprScalarType::Record { fields: b }) => {
4894 let len_ordering = a.len().cmp(&b.len());
4895 if len_ordering != Ordering::Equal {
4896 return len_ordering;
4897 }
4898
4899 for (af, bf) in a.iter().zip_eq(b.iter()) {
4901 let scalar_type_ordering = af.scalar_type.cmp(&bf.scalar_type);
4902 if scalar_type_ordering != Ordering::Equal {
4903 return scalar_type_ordering;
4904 }
4905 }
4906
4907 Ordering::Equal
4908 }
4909 (ReprScalarType::Map { value_type: a }, ReprScalarType::Map { value_type: b }) => {
4910 a.cmp(b)
4911 }
4912 (
4913 ReprScalarType::Range { element_type: a },
4914 ReprScalarType::Range { element_type: b },
4915 ) => a.cmp(b),
4916 _ => ReprScalarBaseType::from(self).cmp(&ReprScalarBaseType::from(other)),
4917 }
4918 }
4919}
4920
4921impl std::fmt::Display for ReprScalarType {
4922 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4923 match self {
4924 ReprScalarType::Bool => write!(f, "r_bool"),
4925 ReprScalarType::Int16 => write!(f, "r_int16"),
4926 ReprScalarType::Int32 => write!(f, "r_int32"),
4927 ReprScalarType::Int64 => write!(f, "r_int64"),
4928 ReprScalarType::UInt8 => write!(f, "r_uint8"),
4929 ReprScalarType::UInt16 => write!(f, "r_uint16"),
4930 ReprScalarType::UInt32 => write!(f, "r_uint32"),
4931 ReprScalarType::UInt64 => write!(f, "r_uint64"),
4932 ReprScalarType::Float32 => write!(f, "r_float32"),
4933 ReprScalarType::Float64 => write!(f, "r_float64"),
4934 ReprScalarType::Numeric => write!(f, "r_numeric"),
4935 ReprScalarType::Date => write!(f, "r_date"),
4936 ReprScalarType::Time => write!(f, "r_time"),
4937 ReprScalarType::Timestamp => write!(f, "r_timestamp"),
4938 ReprScalarType::TimestampTz => write!(f, "r_timestamptz"),
4939 ReprScalarType::MzTimestamp => write!(f, "r_mz_timestamp"),
4940 ReprScalarType::Interval => write!(f, "r_interval"),
4941 ReprScalarType::Bytes => write!(f, "r_bytes"),
4942 ReprScalarType::Jsonb => write!(f, "r_jsonb"),
4943 ReprScalarType::String => write!(f, "r_string"),
4944 ReprScalarType::Uuid => write!(f, "r_uuid"),
4945 ReprScalarType::Array(element_type) => write!(f, "r_array({element_type})"),
4946 ReprScalarType::Int2Vector => write!(f, "r_int2vector"),
4947 ReprScalarType::List { element_type } => write!(f, "r_list({element_type})"),
4948 ReprScalarType::Record { fields } => {
4949 let fields = separated(", ", fields.iter());
4950 write!(f, "r_record({fields})")
4951 }
4952 ReprScalarType::Map { value_type } => write!(f, "r_map({value_type})"),
4953 ReprScalarType::Range { element_type } => write!(f, "r_range({element_type})"),
4954 ReprScalarType::MzAclItem => write!(f, "r_mz_acl_item"),
4955 ReprScalarType::AclItem => write!(f, "r_acl_item"),
4956 }
4957 }
4958}
4959
4960impl ReprScalarType {
4961 pub fn nullable(self, nullable: bool) -> ReprColumnType {
4963 ReprColumnType {
4964 scalar_type: self,
4965 nullable,
4966 }
4967 }
4968
4969 pub fn union(&self, scalar_type: &ReprScalarType) -> Result<Self, anyhow::Error> {
4975 match (self, scalar_type) {
4976 (ReprScalarType::Bool, ReprScalarType::Bool) => Ok(ReprScalarType::Bool),
4977 (ReprScalarType::Int16, ReprScalarType::Int16) => Ok(ReprScalarType::Int16),
4978 (ReprScalarType::Int32, ReprScalarType::Int32) => Ok(ReprScalarType::Int32),
4979 (ReprScalarType::Int64, ReprScalarType::Int64) => Ok(ReprScalarType::Int64),
4980 (ReprScalarType::UInt8, ReprScalarType::UInt8) => Ok(ReprScalarType::UInt8),
4981 (ReprScalarType::UInt16, ReprScalarType::UInt16) => Ok(ReprScalarType::UInt16),
4982 (ReprScalarType::UInt32, ReprScalarType::UInt32) => Ok(ReprScalarType::UInt32),
4983 (ReprScalarType::UInt64, ReprScalarType::UInt64) => Ok(ReprScalarType::UInt64),
4984 (ReprScalarType::Float32, ReprScalarType::Float32) => Ok(ReprScalarType::Float32),
4985 (ReprScalarType::Float64, ReprScalarType::Float64) => Ok(ReprScalarType::Float64),
4986 (ReprScalarType::Numeric, ReprScalarType::Numeric) => Ok(ReprScalarType::Numeric),
4987 (ReprScalarType::Date, ReprScalarType::Date) => Ok(ReprScalarType::Date),
4988 (ReprScalarType::Time, ReprScalarType::Time) => Ok(ReprScalarType::Time),
4989 (ReprScalarType::Timestamp, ReprScalarType::Timestamp) => Ok(ReprScalarType::Timestamp),
4990 (ReprScalarType::TimestampTz, ReprScalarType::TimestampTz) => {
4991 Ok(ReprScalarType::TimestampTz)
4992 }
4993 (ReprScalarType::MzTimestamp, ReprScalarType::MzTimestamp) => {
4994 Ok(ReprScalarType::MzTimestamp)
4995 }
4996 (ReprScalarType::AclItem, ReprScalarType::AclItem) => Ok(ReprScalarType::AclItem),
4997 (ReprScalarType::MzAclItem, ReprScalarType::MzAclItem) => Ok(ReprScalarType::MzAclItem),
4998 (ReprScalarType::Interval, ReprScalarType::Interval) => Ok(ReprScalarType::Interval),
4999 (ReprScalarType::Bytes, ReprScalarType::Bytes) => Ok(ReprScalarType::Bytes),
5000 (ReprScalarType::Jsonb, ReprScalarType::Jsonb) => Ok(ReprScalarType::Jsonb),
5001 (ReprScalarType::String, ReprScalarType::String) => Ok(ReprScalarType::String),
5002 (ReprScalarType::Uuid, ReprScalarType::Uuid) => Ok(ReprScalarType::Uuid),
5003 (ReprScalarType::Array(element_type), ReprScalarType::Array(other_element_type)) => Ok(
5004 ReprScalarType::Array(Box::new(element_type.union(other_element_type)?)),
5005 ),
5006 (ReprScalarType::Int2Vector, ReprScalarType::Int2Vector) => {
5007 Ok(ReprScalarType::Int2Vector)
5008 }
5009 (
5010 ReprScalarType::List { element_type },
5011 ReprScalarType::List {
5012 element_type: other_element_type,
5013 },
5014 ) => Ok(ReprScalarType::List {
5015 element_type: Box::new(element_type.union(other_element_type)?),
5016 }),
5017 (
5018 ReprScalarType::Record { fields },
5019 ReprScalarType::Record {
5020 fields: other_fields,
5021 },
5022 ) => {
5023 if fields.len() != other_fields.len() {
5024 bail!("Can't union record types: {:?} and {:?}", self, scalar_type);
5025 }
5026
5027 let mut union_fields = Vec::with_capacity(fields.len());
5028 for (field, other_field) in fields.iter().zip_eq(other_fields.iter()) {
5029 union_fields.push(field.union(other_field)?);
5030 }
5031 Ok(ReprScalarType::Record {
5032 fields: union_fields.into_boxed_slice(),
5033 })
5034 }
5035 (
5036 ReprScalarType::Map { value_type },
5037 ReprScalarType::Map {
5038 value_type: other_value_type,
5039 },
5040 ) => Ok(ReprScalarType::Map {
5041 value_type: Box::new(value_type.union(other_value_type)?),
5042 }),
5043 (
5044 ReprScalarType::Range { element_type },
5045 ReprScalarType::Range {
5046 element_type: other_element_type,
5047 },
5048 ) => Ok(ReprScalarType::Range {
5049 element_type: Box::new(element_type.union(other_element_type)?),
5050 }),
5051 (_, _) => bail!("Can't union scalar types: {:?} and {:?}", self, scalar_type),
5052 }
5053 }
5054
5055 pub fn unwrap_list_element_type(&self) -> &ReprScalarType {
5061 match self {
5062 ReprScalarType::List { element_type, .. } => element_type,
5063 _ => panic!(
5064 "ReprScalarType::unwrap_list_element_type called on {:?}",
5065 self
5066 ),
5067 }
5068 }
5069
5070 pub fn unwrap_record_element_type(&self) -> Vec<&ReprScalarType> {
5076 match self {
5077 ReprScalarType::Record { fields, .. } => {
5078 fields.iter().map(|t| &t.scalar_type).collect_vec()
5079 }
5080 _ => panic!(
5081 "SqlScalarType::unwrap_record_element_type called on {:?}",
5082 self
5083 ),
5084 }
5085 }
5086}
5087
5088impl From<&SqlScalarType> for ReprScalarType {
5089 fn from(typ: &SqlScalarType) -> Self {
5090 match typ {
5091 SqlScalarType::Bool => ReprScalarType::Bool,
5092 SqlScalarType::Int16 => ReprScalarType::Int16,
5093 SqlScalarType::Int32 => ReprScalarType::Int32,
5094 SqlScalarType::Int64 => ReprScalarType::Int64,
5095 SqlScalarType::UInt16 => ReprScalarType::UInt16,
5096 SqlScalarType::UInt32 => ReprScalarType::UInt32,
5097 SqlScalarType::UInt64 => ReprScalarType::UInt64,
5098 SqlScalarType::Float32 => ReprScalarType::Float32,
5099 SqlScalarType::Float64 => ReprScalarType::Float64,
5100 SqlScalarType::Numeric { max_scale: _ } => ReprScalarType::Numeric,
5101 SqlScalarType::Date => ReprScalarType::Date,
5102 SqlScalarType::Time => ReprScalarType::Time,
5103 SqlScalarType::Timestamp { precision: _ } => ReprScalarType::Timestamp,
5104 SqlScalarType::TimestampTz { precision: _ } => ReprScalarType::TimestampTz,
5105 SqlScalarType::Interval => ReprScalarType::Interval,
5106 SqlScalarType::PgLegacyChar => ReprScalarType::UInt8,
5107 SqlScalarType::PgLegacyName => ReprScalarType::String,
5108 SqlScalarType::Bytes => ReprScalarType::Bytes,
5109 SqlScalarType::String => ReprScalarType::String,
5110 SqlScalarType::Char { length: _ } => ReprScalarType::String,
5111 SqlScalarType::VarChar { max_length: _ } => ReprScalarType::String,
5112 SqlScalarType::Jsonb => ReprScalarType::Jsonb,
5113 SqlScalarType::Uuid => ReprScalarType::Uuid,
5114 SqlScalarType::Array(element_type) => {
5115 ReprScalarType::Array(Box::new(element_type.as_ref().into()))
5116 }
5117 SqlScalarType::List {
5118 element_type,
5119 custom_id: _,
5120 } => ReprScalarType::List {
5121 element_type: Box::new(element_type.as_ref().into()),
5122 },
5123 SqlScalarType::Record {
5124 fields,
5125 custom_id: _,
5126 } => ReprScalarType::Record {
5127 fields: fields.into_iter().map(|(_, typ)| typ.into()).collect(),
5128 },
5129 SqlScalarType::Oid => ReprScalarType::UInt32,
5130 SqlScalarType::Map {
5131 value_type,
5132 custom_id: _,
5133 } => ReprScalarType::Map {
5134 value_type: Box::new(value_type.as_ref().into()),
5135 },
5136 SqlScalarType::RegProc => ReprScalarType::UInt32,
5137 SqlScalarType::RegType => ReprScalarType::UInt32,
5138 SqlScalarType::RegClass => ReprScalarType::UInt32,
5139 SqlScalarType::Int2Vector => ReprScalarType::Int2Vector,
5140 SqlScalarType::MzTimestamp => ReprScalarType::MzTimestamp,
5141 SqlScalarType::Range { element_type } => ReprScalarType::Range {
5142 element_type: Box::new(element_type.as_ref().into()),
5143 },
5144 SqlScalarType::MzAclItem => ReprScalarType::MzAclItem,
5145 SqlScalarType::AclItem => ReprScalarType::AclItem,
5146 }
5147 }
5148}
5149
5150impl SqlScalarType {
5151 pub fn from_repr(repr: &ReprScalarType) -> Self {
5171 match repr {
5172 ReprScalarType::Bool => SqlScalarType::Bool,
5173 ReprScalarType::Int16 => SqlScalarType::Int16,
5174 ReprScalarType::Int32 => SqlScalarType::Int32,
5175 ReprScalarType::Int64 => SqlScalarType::Int64,
5176 ReprScalarType::UInt8 => SqlScalarType::PgLegacyChar,
5177 ReprScalarType::UInt16 => SqlScalarType::UInt16,
5178 ReprScalarType::UInt32 => SqlScalarType::UInt32,
5179 ReprScalarType::UInt64 => SqlScalarType::UInt64,
5180 ReprScalarType::Float32 => SqlScalarType::Float32,
5181 ReprScalarType::Float64 => SqlScalarType::Float64,
5182 ReprScalarType::Numeric => SqlScalarType::Numeric { max_scale: None },
5183 ReprScalarType::Date => SqlScalarType::Date,
5184 ReprScalarType::Time => SqlScalarType::Time,
5185 ReprScalarType::Timestamp => SqlScalarType::Timestamp { precision: None },
5186 ReprScalarType::TimestampTz => SqlScalarType::TimestampTz { precision: None },
5187 ReprScalarType::MzTimestamp => SqlScalarType::MzTimestamp,
5188 ReprScalarType::Interval => SqlScalarType::Interval,
5189 ReprScalarType::Bytes => SqlScalarType::Bytes,
5190 ReprScalarType::Jsonb => SqlScalarType::Jsonb,
5191 ReprScalarType::String => SqlScalarType::String,
5192 ReprScalarType::Uuid => SqlScalarType::Uuid,
5193 ReprScalarType::Array(element_type) => {
5194 SqlScalarType::Array(Box::new(SqlScalarType::from_repr(element_type)))
5195 }
5196 ReprScalarType::Int2Vector => SqlScalarType::Int2Vector,
5197 ReprScalarType::List { element_type } => SqlScalarType::List {
5198 element_type: Box::new(SqlScalarType::from_repr(element_type)),
5199 custom_id: None,
5200 },
5201 ReprScalarType::Record { fields } => SqlScalarType::Record {
5202 fields: fields
5203 .iter()
5204 .enumerate()
5205 .map(|typ| {
5206 (
5207 ColumnName::from(format!("field_{}", typ.0)),
5208 SqlColumnType::from_repr(typ.1),
5209 )
5210 })
5211 .collect::<Vec<_>>()
5212 .into_boxed_slice(),
5213 custom_id: None,
5214 },
5215 ReprScalarType::Map { value_type } => SqlScalarType::Map {
5216 value_type: Box::new(SqlScalarType::from_repr(value_type)),
5217 custom_id: None,
5218 },
5219 ReprScalarType::Range { element_type } => SqlScalarType::Range {
5220 element_type: Box::new(SqlScalarType::from_repr(element_type)),
5221 },
5222 ReprScalarType::MzAclItem => SqlScalarType::MzAclItem,
5223 ReprScalarType::AclItem => SqlScalarType::AclItem,
5224 }
5225 }
5226}
5227
5228static EMPTY_ARRAY_ROW: LazyLock<Row> = LazyLock::new(|| {
5229 let mut row = Row::default();
5230 row.packer()
5231 .try_push_array(&[], iter::empty::<Datum>())
5232 .expect("array known to be valid");
5233 row
5234});
5235
5236static EMPTY_LIST_ROW: LazyLock<Row> = LazyLock::new(|| {
5237 let mut row = Row::default();
5238 row.packer().push_list(iter::empty::<Datum>());
5239 row
5240});
5241
5242static EMPTY_MAP_ROW: LazyLock<Row> = LazyLock::new(|| {
5243 let mut row = Row::default();
5244 row.packer().push_dict(iter::empty::<(_, Datum)>());
5245 row
5246});
5247
5248impl Datum<'_> {
5249 pub fn empty_array() -> Datum<'static> {
5250 EMPTY_ARRAY_ROW.unpack_first()
5251 }
5252
5253 pub fn empty_list() -> Datum<'static> {
5254 EMPTY_LIST_ROW.unpack_first()
5255 }
5256
5257 pub fn empty_map() -> Datum<'static> {
5258 EMPTY_MAP_ROW.unpack_first()
5259 }
5260
5261 pub fn contains_dummy(&self) -> bool {
5262 match self {
5263 Datum::Dummy => true,
5264 Datum::List(list) => list.iter().any(|d| d.contains_dummy()),
5265 Datum::Map(map) => map.iter().any(|(_, d)| d.contains_dummy()),
5266 Datum::Array(array) => array.elements().iter().any(|d| d.contains_dummy()),
5267 Datum::Range(range) => range.inner.map_or(false, |range| {
5268 range
5269 .lower
5270 .bound
5271 .map_or(false, |d| d.datum().contains_dummy())
5272 || range
5273 .upper
5274 .bound
5275 .map_or(false, |d| d.datum().contains_dummy())
5276 }),
5277 _ => false,
5278 }
5279 }
5280}
5281
5282#[derive(Debug, PartialEq, Clone)]
5284#[cfg(any(test, feature = "proptest"))]
5285pub enum PropDatum {
5286 Null,
5287 Bool(bool),
5288 Int16(i16),
5289 Int32(i32),
5290 Int64(i64),
5291 UInt8(u8),
5292 UInt16(u16),
5293 UInt32(u32),
5294 UInt64(u64),
5295 Float32(f32),
5296 Float64(f64),
5297
5298 Date(Date),
5299 Time(chrono::NaiveTime),
5300 Timestamp(CheckedTimestamp<chrono::NaiveDateTime>),
5301 TimestampTz(CheckedTimestamp<chrono::DateTime<chrono::Utc>>),
5302 MzTimestamp(u64),
5303
5304 Interval(Interval),
5305 Numeric(Numeric),
5306
5307 Bytes(Vec<u8>),
5308 String(String),
5309
5310 Array(PropArray),
5311 List(PropList),
5312 Map(PropDict),
5313 Record(PropDict),
5314 Range(PropRange),
5315
5316 AclItem(AclItem),
5317 MzAclItem(MzAclItem),
5318
5319 JsonNull,
5320 Uuid(Uuid),
5321 Dummy,
5322}
5323
5324#[cfg(any(test, feature = "proptest"))]
5325impl std::cmp::Eq for PropDatum {}
5326
5327#[cfg(any(test, feature = "proptest"))]
5328impl PartialOrd for PropDatum {
5329 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
5330 Some(self.cmp(other))
5331 }
5332}
5333
5334#[cfg(any(test, feature = "proptest"))]
5335impl Ord for PropDatum {
5336 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
5337 Datum::from(self).cmp(&Datum::from(other))
5338 }
5339}
5340
5341#[cfg(any(test, feature = "proptest"))]
5343pub fn arb_datum(allow_dummy: bool) -> BoxedStrategy<PropDatum> {
5344 let mut leaf_options = vec![
5345 any::<bool>().prop_map(PropDatum::Bool).boxed(),
5346 any::<i16>().prop_map(PropDatum::Int16).boxed(),
5347 any::<i32>().prop_map(PropDatum::Int32).boxed(),
5348 any::<i64>().prop_map(PropDatum::Int64).boxed(),
5349 any::<u16>().prop_map(PropDatum::UInt16).boxed(),
5350 any::<u32>().prop_map(PropDatum::UInt32).boxed(),
5351 any::<u64>().prop_map(PropDatum::UInt64).boxed(),
5352 any::<f32>().prop_map(PropDatum::Float32).boxed(),
5353 any::<f64>().prop_map(PropDatum::Float64).boxed(),
5354 arb_date().prop_map(PropDatum::Date).boxed(),
5355 add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
5356 .prop_map(PropDatum::Time)
5357 .boxed(),
5358 arb_naive_date_time()
5359 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
5360 .boxed(),
5361 arb_utc_date_time()
5362 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
5363 .boxed(),
5364 any::<Interval>().prop_map(PropDatum::Interval).boxed(),
5365 arb_numeric().prop_map(PropDatum::Numeric).boxed(),
5366 prop::collection::vec(any::<u8>(), 1024)
5367 .prop_map(PropDatum::Bytes)
5368 .boxed(),
5369 ".*".prop_map(PropDatum::String).boxed(),
5370 Just(PropDatum::JsonNull).boxed(),
5371 any::<[u8; 16]>()
5372 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
5373 .boxed(),
5374 arb_range(arb_range_data())
5375 .prop_map(PropDatum::Range)
5376 .boxed(),
5377 ];
5378
5379 if allow_dummy {
5380 leaf_options.push(Just(PropDatum::Dummy).boxed());
5381 }
5382 let leaf = Union::new(leaf_options);
5383
5384 leaf.prop_recursive(3, 8, 16, |inner| {
5385 Union::new(vec![
5386 arb_array(inner.clone()).prop_map(PropDatum::Array).boxed(),
5387 arb_list(inner.clone()).prop_map(PropDatum::List).boxed(),
5388 arb_dict(inner).prop_map(PropDatum::Map).boxed(),
5389 ])
5390 })
5391 .boxed()
5392}
5393
5394#[cfg(any(test, feature = "proptest"))]
5396pub fn arb_datum_for_column(column_type: SqlColumnType) -> impl Strategy<Value = PropDatum> {
5397 let strat = arb_datum_for_scalar(column_type.scalar_type);
5398
5399 if column_type.nullable {
5400 Union::new_weighted(vec![(1, Just(PropDatum::Null).boxed()), (5, strat.boxed())]).boxed()
5401 } else {
5402 strat.boxed()
5403 }
5404}
5405
5406#[cfg(any(test, feature = "proptest"))]
5408pub fn arb_datum_for_scalar(scalar_type: SqlScalarType) -> impl Strategy<Value = PropDatum> {
5409 match scalar_type {
5410 SqlScalarType::Bool => any::<bool>().prop_map(PropDatum::Bool).boxed(),
5411 SqlScalarType::Int16 => any::<i16>().prop_map(PropDatum::Int16).boxed(),
5412 SqlScalarType::Int32 => any::<i32>().prop_map(PropDatum::Int32).boxed(),
5413 SqlScalarType::Int64 => any::<i64>().prop_map(PropDatum::Int64).boxed(),
5414 SqlScalarType::PgLegacyChar => any::<u8>().prop_map(PropDatum::UInt8).boxed(),
5415 SqlScalarType::UInt16 => any::<u16>().prop_map(PropDatum::UInt16).boxed(),
5416 SqlScalarType::UInt32
5417 | SqlScalarType::Oid
5418 | SqlScalarType::RegClass
5419 | SqlScalarType::RegProc
5420 | SqlScalarType::RegType => any::<u32>().prop_map(PropDatum::UInt32).boxed(),
5421 SqlScalarType::UInt64 => any::<u64>().prop_map(PropDatum::UInt64).boxed(),
5422 SqlScalarType::Float32 => any::<f32>().prop_map(PropDatum::Float32).boxed(),
5423 SqlScalarType::Float64 => any::<f64>().prop_map(PropDatum::Float64).boxed(),
5424 SqlScalarType::Numeric { .. } => arb_numeric().prop_map(PropDatum::Numeric).boxed(),
5425 SqlScalarType::String
5426 | SqlScalarType::PgLegacyName
5427 | SqlScalarType::Char { length: None }
5428 | SqlScalarType::VarChar { max_length: None } => ".*".prop_map(PropDatum::String).boxed(),
5429 SqlScalarType::Char {
5430 length: Some(length),
5431 } => {
5432 let max_len = usize::cast_from(length.into_u32()).max(1);
5433 prop::collection::vec(any::<char>(), 0..max_len)
5434 .prop_map(move |chars| {
5435 let num_blanks = max_len - chars.len();
5437 let s = chars
5438 .into_iter()
5439 .chain(std::iter::repeat(' ').take(num_blanks))
5440 .collect();
5441 PropDatum::String(s)
5442 })
5443 .boxed()
5444 }
5445 SqlScalarType::VarChar {
5446 max_length: Some(length),
5447 } => {
5448 let max_len = usize::cast_from(length.into_u32()).max(1);
5449 prop::collection::vec(any::<char>(), 0..max_len)
5450 .prop_map(|chars| PropDatum::String(chars.into_iter().collect()))
5451 .boxed()
5452 }
5453 SqlScalarType::Bytes => prop::collection::vec(any::<u8>(), 300)
5454 .prop_map(PropDatum::Bytes)
5455 .boxed(),
5456 SqlScalarType::Date => arb_date().prop_map(PropDatum::Date).boxed(),
5457 SqlScalarType::Time => add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
5458 .prop_map(PropDatum::Time)
5459 .boxed(),
5460 SqlScalarType::Timestamp { .. } => arb_naive_date_time()
5461 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
5462 .boxed(),
5463 SqlScalarType::TimestampTz { .. } => arb_utc_date_time()
5464 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
5465 .boxed(),
5466 SqlScalarType::MzTimestamp => any::<u64>().prop_map(PropDatum::MzTimestamp).boxed(),
5467 SqlScalarType::Interval => any::<Interval>().prop_map(PropDatum::Interval).boxed(),
5468 SqlScalarType::Uuid => any::<[u8; 16]>()
5469 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
5470 .boxed(),
5471 SqlScalarType::AclItem => any::<AclItem>().prop_map(PropDatum::AclItem).boxed(),
5472 SqlScalarType::MzAclItem => any::<MzAclItem>().prop_map(PropDatum::MzAclItem).boxed(),
5473 SqlScalarType::Range { element_type } => {
5474 let data_strat = (
5475 arb_datum_for_scalar(*element_type.clone()),
5476 arb_datum_for_scalar(*element_type),
5477 );
5478 arb_range(data_strat).prop_map(PropDatum::Range).boxed()
5479 }
5480 SqlScalarType::List { element_type, .. } => arb_list(arb_datum_for_scalar(*element_type))
5481 .prop_map(PropDatum::List)
5482 .boxed(),
5483 SqlScalarType::Array(element_type) => arb_array(arb_datum_for_scalar(*element_type))
5484 .prop_map(PropDatum::Array)
5485 .boxed(),
5486 SqlScalarType::Int2Vector => {
5487 let element_strategy = any::<i16>().prop_map(PropDatum::Int16).boxed();
5493 prop::collection::vec(element_strategy, 0..16)
5494 .prop_map(|elements| {
5495 let dims = [ArrayDimension {
5496 lower_bound: 1,
5497 length: elements.len(),
5498 }];
5499 let element_datums: Vec<Datum<'_>> =
5500 elements.iter().map(|pd| pd.into()).collect();
5501 let mut row = Row::default();
5502 row.packer().try_push_array(&dims, element_datums).unwrap();
5503 PropDatum::Array(PropArray(row, elements))
5504 })
5505 .boxed()
5506 }
5507 SqlScalarType::Map { value_type, .. } => arb_dict(arb_datum_for_scalar(*value_type))
5508 .prop_map(PropDatum::Map)
5509 .boxed(),
5510 SqlScalarType::Record { fields, .. } => {
5511 let field_strats = fields.iter().map(|(name, ty)| {
5512 (
5513 name.to_string(),
5514 arb_datum_for_scalar(ty.scalar_type.clone()),
5515 )
5516 });
5517 arb_record(field_strats).prop_map(PropDatum::Record).boxed()
5518 }
5519 SqlScalarType::Jsonb => {
5520 let int_value = any::<i128>()
5521 .prop_map(|v| Numeric::try_from(v).unwrap())
5522 .boxed();
5523 let float_value = (1e-39f64..1e39)
5525 .prop_map(|v| Numeric::try_from(v).unwrap())
5526 .boxed();
5527 let json_number = Union::new(vec![int_value, float_value]);
5530
5531 let json_leaf = Union::new(vec![
5532 any::<()>().prop_map(|_| PropDatum::JsonNull).boxed(),
5533 any::<bool>().prop_map(PropDatum::Bool).boxed(),
5534 json_number.prop_map(PropDatum::Numeric).boxed(),
5535 ".*".prop_map(PropDatum::String).boxed(),
5536 ]);
5537 json_leaf
5538 .prop_recursive(4, 32, 8, |element| {
5539 Union::new(vec![
5540 prop::collection::vec(element.clone(), 0..16)
5541 .prop_map(|elements| {
5542 let datums: Vec<_> = elements.iter().map(|pd| pd.into()).collect();
5543 let mut row = Row::default();
5544 row.packer().push_list(datums.iter());
5545 PropDatum::List(PropList(row, elements))
5546 })
5547 .boxed(),
5548 prop::collection::hash_map(".*", element, 0..16)
5549 .prop_map(|elements| {
5550 let mut elements: Vec<_> = elements.into_iter().collect();
5551 elements.sort_by_key(|(k, _)| k.clone());
5552 elements.dedup_by_key(|(k, _)| k.clone());
5553 let mut row = Row::default();
5554 let entry_iter =
5555 elements.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
5556 row.packer().push_dict(entry_iter);
5557 PropDatum::Map(PropDict(row, elements))
5558 })
5559 .boxed(),
5560 ])
5561 })
5562 .boxed()
5563 }
5564 }
5565}
5566
5567#[cfg(any(test, feature = "proptest"))]
5569pub fn arb_naive_date_time() -> impl Strategy<Value = NaiveDateTime> {
5570 add_arb_duration(chrono::DateTime::from_timestamp(0, 0).unwrap().naive_utc())
5571}
5572
5573#[cfg(any(test, feature = "proptest"))]
5575pub fn arb_utc_date_time() -> impl Strategy<Value = DateTime<Utc>> {
5576 add_arb_duration(chrono::Utc.timestamp_opt(0, 0).unwrap())
5577}
5578
5579#[cfg(any(test, feature = "proptest"))]
5580fn arb_array_dimension() -> BoxedStrategy<ArrayDimension> {
5581 (1..4_usize)
5582 .prop_map(|length| ArrayDimension {
5583 lower_bound: 1,
5584 length,
5585 })
5586 .boxed()
5587}
5588
5589#[derive(Debug, PartialEq, Clone)]
5590#[cfg(any(test, feature = "proptest"))]
5591pub struct PropArray(Row, Vec<PropDatum>);
5592
5593#[cfg(any(test, feature = "proptest"))]
5594fn arb_array(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropArray> {
5595 let element_strategy = Union::new_weighted(vec![
5597 (20, element_strategy),
5598 (1, Just(PropDatum::Null).boxed()),
5599 ]);
5600
5601 prop::collection::vec(
5602 arb_array_dimension(),
5603 1..usize::from(crate::adt::array::MAX_ARRAY_DIMENSIONS),
5604 )
5605 .prop_flat_map(move |dimensions| {
5606 let n_elts: usize = dimensions.iter().map(|d| d.length).product();
5607 (
5608 Just(dimensions),
5609 prop::collection::vec(element_strategy.clone(), n_elts),
5610 )
5611 })
5612 .prop_map(|(dimensions, elements)| {
5613 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
5614 let mut row = Row::default();
5615 row.packer()
5616 .try_push_array(&dimensions, element_datums)
5617 .unwrap();
5618 PropArray(row, elements)
5619 })
5620 .boxed()
5621}
5622
5623#[derive(Debug, PartialEq, Clone)]
5624#[cfg(any(test, feature = "proptest"))]
5625pub struct PropList(Row, Vec<PropDatum>);
5626
5627#[cfg(any(test, feature = "proptest"))]
5628fn arb_list(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropList> {
5629 let element_strategy = Union::new_weighted(vec![
5631 (20, element_strategy),
5632 (1, Just(PropDatum::Null).boxed()),
5633 ]);
5634
5635 prop::collection::vec(element_strategy, 1..50)
5636 .prop_map(|elements| {
5637 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
5638 let mut row = Row::default();
5639 row.packer().push_list(element_datums.iter());
5640 PropList(row, elements)
5641 })
5642 .boxed()
5643}
5644
5645#[derive(Debug, PartialEq, Clone)]
5646#[cfg(any(test, feature = "proptest"))]
5647pub struct PropRange(
5648 Row,
5649 Option<(
5650 (Option<Box<PropDatum>>, bool),
5651 (Option<Box<PropDatum>>, bool),
5652 )>,
5653);
5654
5655#[cfg(any(test, feature = "proptest"))]
5656pub fn arb_range_type() -> Union<BoxedStrategy<SqlScalarType>> {
5657 Union::new(vec![
5658 Just(SqlScalarType::Int32).boxed(),
5659 Just(SqlScalarType::Int64).boxed(),
5660 Just(SqlScalarType::Date).boxed(),
5661 ])
5662}
5663
5664#[cfg(any(test, feature = "proptest"))]
5665fn arb_range_data() -> Union<BoxedStrategy<(PropDatum, PropDatum)>> {
5666 Union::new(vec![
5667 (
5668 any::<i32>().prop_map(PropDatum::Int32),
5669 any::<i32>().prop_map(PropDatum::Int32),
5670 )
5671 .boxed(),
5672 (
5673 any::<i64>().prop_map(PropDatum::Int64),
5674 any::<i64>().prop_map(PropDatum::Int64),
5675 )
5676 .boxed(),
5677 (
5678 arb_date().prop_map(PropDatum::Date),
5679 arb_date().prop_map(PropDatum::Date),
5680 )
5681 .boxed(),
5682 ])
5683}
5684
5685#[cfg(any(test, feature = "proptest"))]
5686fn arb_range(
5687 data: impl Strategy<Value = (PropDatum, PropDatum)> + 'static,
5688) -> BoxedStrategy<PropRange> {
5689 (
5690 any::<u16>(),
5691 any::<bool>(),
5692 any::<bool>(),
5693 any::<bool>(),
5694 any::<bool>(),
5695 data,
5696 )
5697 .prop_map(
5698 |(split, lower_inf, lower_inc, upper_inf, upper_inc, (a, b))| {
5699 let mut row = Row::default();
5700 let mut packer = row.packer();
5701 let r = if split % 32 == 0 {
5702 packer
5703 .push_range(Range::new(None))
5704 .expect("pushing empty ranges never fails");
5705 None
5706 } else {
5707 let b_is_lower = Datum::from(&b) < Datum::from(&a);
5708
5709 let (lower, upper) = if b_is_lower { (b, a) } else { (a, b) };
5710 let mut range = Range::new(Some((
5711 RangeLowerBound {
5712 inclusive: lower_inc,
5713 bound: if lower_inf {
5714 None
5715 } else {
5716 Some(Datum::from(&lower))
5717 },
5718 },
5719 RangeUpperBound {
5720 inclusive: upper_inc,
5721 bound: if upper_inf {
5722 None
5723 } else {
5724 Some(Datum::from(&upper))
5725 },
5726 },
5727 )));
5728
5729 range.canonicalize().unwrap();
5730
5731 let (empty, lower_inf, lower_inc, upper_inf, upper_inc) = match range.inner {
5734 None => (true, false, false, false, false),
5735 Some(inner) => (
5736 false
5737 || match inner.lower.bound {
5738 Some(b) => b != Datum::from(&lower),
5739 None => !lower_inf,
5740 }
5741 || match inner.upper.bound {
5742 Some(b) => b != Datum::from(&upper),
5743 None => !upper_inf,
5744 },
5745 inner.lower.bound.is_none(),
5746 inner.lower.inclusive,
5747 inner.upper.bound.is_none(),
5748 inner.upper.inclusive,
5749 ),
5750 };
5751
5752 if empty {
5753 packer.push_range(Range { inner: None }).unwrap();
5754 None
5755 } else {
5756 packer.push_range(range).unwrap();
5757 Some((
5758 (
5759 if lower_inf {
5760 None
5761 } else {
5762 Some(Box::new(lower))
5763 },
5764 lower_inc,
5765 ),
5766 (
5767 if upper_inf {
5768 None
5769 } else {
5770 Some(Box::new(upper))
5771 },
5772 upper_inc,
5773 ),
5774 ))
5775 }
5776 };
5777
5778 PropRange(row, r)
5779 },
5780 )
5781 .boxed()
5782}
5783
5784#[derive(Debug, PartialEq, Clone)]
5785#[cfg(any(test, feature = "proptest"))]
5786pub struct PropDict(Row, Vec<(String, PropDatum)>);
5787
5788#[cfg(any(test, feature = "proptest"))]
5789fn arb_dict(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropDict> {
5790 let element_strategy = Union::new_weighted(vec![
5792 (20, element_strategy),
5793 (1, Just(PropDatum::Null).boxed()),
5794 ]);
5795
5796 prop::collection::vec((".*", element_strategy), 1..50)
5797 .prop_map(|mut entries| {
5798 entries.sort_by_key(|(k, _)| k.clone());
5799 entries.dedup_by_key(|(k, _)| k.clone());
5800 let mut row = Row::default();
5801 let entry_iter = entries.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
5802 row.packer().push_dict(entry_iter);
5803 PropDict(row, entries)
5804 })
5805 .boxed()
5806}
5807
5808#[cfg(any(test, feature = "proptest"))]
5809fn arb_record(
5810 fields: impl Iterator<Item = (String, BoxedStrategy<PropDatum>)>,
5811) -> BoxedStrategy<PropDict> {
5812 let (names, strategies): (Vec<_>, Vec<_>) = fields.unzip();
5813
5814 strategies
5815 .prop_map(move |x| {
5816 let mut row = Row::default();
5817 row.packer().push_list(x.iter().map(Datum::from));
5818 let entries: Vec<_> = names.clone().into_iter().zip_eq(x).collect();
5819 PropDict(row, entries)
5820 })
5821 .boxed()
5822}
5823
5824#[cfg(any(test, feature = "proptest"))]
5825fn arb_date() -> BoxedStrategy<Date> {
5826 (Date::LOW_DAYS..Date::HIGH_DAYS)
5827 .prop_map(move |days| Date::from_pg_epoch(days).unwrap())
5828 .boxed()
5829}
5830
5831#[cfg(any(test, feature = "proptest"))]
5832pub fn add_arb_duration<T: 'static + Copy + Add<chrono::Duration> + std::fmt::Debug>(
5833 to: T,
5834) -> BoxedStrategy<T::Output>
5835where
5836 T::Output: std::fmt::Debug,
5837{
5838 let lower = LOW_DATE
5839 .and_hms_opt(0, 0, 0)
5840 .unwrap()
5841 .and_utc()
5842 .timestamp_micros();
5843 let upper = HIGH_DATE
5844 .and_hms_opt(0, 0, 0)
5845 .unwrap()
5846 .and_utc()
5847 .timestamp_micros();
5848 (lower..upper)
5849 .prop_map(move |v| to + chrono::Duration::microseconds(v))
5850 .boxed()
5851}
5852
5853#[cfg(any(test, feature = "proptest"))]
5854pub(crate) fn arb_numeric() -> BoxedStrategy<Numeric> {
5855 let int_value = any::<i128>()
5856 .prop_map(|v| Numeric::try_from(v).unwrap())
5857 .boxed();
5858 let float_value = (-1e39f64..1e39)
5859 .prop_map(|v| Numeric::try_from(v).unwrap())
5860 .boxed();
5861
5862 let tiny_floats = ((-10.0..10.0), (1u32..10))
5865 .prop_map(|(v, num_digits)| {
5866 let num_digits: f64 = 10u32.pow(num_digits).try_into().unwrap();
5868 let trunc = f64::trunc(v * num_digits) / num_digits;
5869 Numeric::try_from(trunc).unwrap()
5870 })
5871 .boxed();
5872 let small_ints = (-1_000_000..1_000_000)
5873 .prop_map(|v| Numeric::try_from(v).unwrap())
5874 .boxed();
5875 let small_floats = (-1_000_000.0..1_000_000.0)
5876 .prop_map(|v| Numeric::try_from(v).unwrap())
5877 .boxed();
5878
5879 Union::new_weighted(vec![
5880 (20, tiny_floats),
5881 (20, small_ints),
5882 (20, small_floats),
5883 (10, int_value),
5884 (10, float_value),
5885 (1, Just(Numeric::infinity()).boxed()),
5886 (1, Just(-Numeric::infinity()).boxed()),
5887 (1, Just(Numeric::nan()).boxed()),
5888 (1, Just(Numeric::zero()).boxed()),
5889 ])
5890 .boxed()
5891}
5892
5893#[cfg(any(test, feature = "proptest"))]
5894impl<'a> From<&'a PropDatum> for Datum<'a> {
5895 #[inline]
5896 fn from(pd: &'a PropDatum) -> Self {
5897 use PropDatum::*;
5898 match pd {
5899 Null => Datum::Null,
5900 Bool(b) => Datum::from(*b),
5901 Int16(i) => Datum::from(*i),
5902 Int32(i) => Datum::from(*i),
5903 Int64(i) => Datum::from(*i),
5904 UInt8(u) => Datum::from(*u),
5905 UInt16(u) => Datum::from(*u),
5906 UInt32(u) => Datum::from(*u),
5907 UInt64(u) => Datum::from(*u),
5908 Float32(f) => Datum::from(*f),
5909 Float64(f) => Datum::from(*f),
5910 Date(d) => Datum::from(*d),
5911 Time(t) => Datum::from(*t),
5912 Timestamp(t) => Datum::from(*t),
5913 TimestampTz(t) => Datum::from(*t),
5914 MzTimestamp(t) => Datum::MzTimestamp((*t).into()),
5915 Interval(i) => Datum::from(*i),
5916 Numeric(s) => Datum::from(*s),
5917 Bytes(b) => Datum::from(&b[..]),
5918 String(s) => Datum::from(s.as_str()),
5919 Array(PropArray(row, _)) => {
5920 let array = row.unpack_first().unwrap_array();
5921 Datum::Array(array)
5922 }
5923 List(PropList(row, _)) => {
5924 let list = row.unpack_first().unwrap_list();
5925 Datum::List(list)
5926 }
5927 Map(PropDict(row, _)) => {
5928 let map = row.unpack_first().unwrap_map();
5929 Datum::Map(map)
5930 }
5931 Record(PropDict(row, _)) => {
5932 let list = row.unpack_first().unwrap_list();
5933 Datum::List(list)
5934 }
5935 Range(PropRange(row, _)) => {
5936 let d = row.unpack_first();
5937 assert!(matches!(d, Datum::Range(_)));
5938 d
5939 }
5940 AclItem(i) => Datum::AclItem(*i),
5941 MzAclItem(i) => Datum::MzAclItem(*i),
5942 JsonNull => Datum::JsonNull,
5943 Uuid(u) => Datum::from(*u),
5944 Dummy => Datum::Dummy,
5945 }
5946 }
5947}
5948
5949#[mz_ore::test]
5950fn verify_base_eq_record_nullability() {
5951 let s1 = SqlScalarType::Record {
5952 fields: [(
5953 "c".into(),
5954 SqlColumnType {
5955 scalar_type: SqlScalarType::Bool,
5956 nullable: true,
5957 },
5958 )]
5959 .into(),
5960 custom_id: None,
5961 };
5962 let s2 = SqlScalarType::Record {
5963 fields: [(
5964 "c".into(),
5965 SqlColumnType {
5966 scalar_type: SqlScalarType::Bool,
5967 nullable: false,
5968 },
5969 )]
5970 .into(),
5971 custom_id: None,
5972 };
5973 let s3 = SqlScalarType::Record {
5974 fields: [].into(),
5975 custom_id: None,
5976 };
5977 assert!(s1.base_eq(&s2));
5978 assert!(!s1.base_eq(&s3));
5979}
5980
5981#[cfg(test)]
5982mod tests {
5983 use mz_ore::assert_ok;
5984 use mz_proto::protobuf_roundtrip;
5985
5986 use super::*;
5987
5988 proptest! {
5989 #[mz_ore::test]
5990 #[cfg_attr(miri, ignore)] fn scalar_type_protobuf_roundtrip(expect in any::<SqlScalarType>() ) {
5992 let actual = protobuf_roundtrip::<_, ProtoScalarType>(&expect);
5993 assert_ok!(actual);
5994 assert_eq!(actual.unwrap(), expect);
5995 }
5996 }
5997
5998 proptest! {
5999 #[mz_ore::test]
6000 #[cfg_attr(miri, ignore)]
6001 fn sql_repr_types_agree_on_valid_data(
6002 (src, datum) in any::<SqlColumnType>()
6003 .prop_flat_map(|src| {
6004 let datum = arb_datum_for_column(src.clone());
6005 (Just(src), datum)
6006 }),
6007 ) {
6008 let tgt = ReprColumnType::from(&src);
6009 let datum = Datum::from(&datum);
6010 assert_eq!(
6011 datum.is_instance_of_sql(&src),
6012 datum.is_instance_of(&tgt),
6013 "translated to repr type {tgt:#?}",
6014 );
6015 }
6016 }
6017
6018 proptest! {
6019 #![proptest_config(ProptestConfig::with_cases(10000))]
6022 #[mz_ore::test]
6023 #[cfg_attr(miri, ignore)]
6024 fn sql_repr_types_agree_on_random_data(
6025 src in any::<SqlColumnType>(),
6026 datum in arb_datum(true),
6027 ) {
6028 let tgt = ReprColumnType::from(&src);
6029 let datum = Datum::from(&datum);
6030
6031 assert_eq!(
6032 datum.is_instance_of_sql(&src),
6033 datum.is_instance_of(&tgt),
6034 "translated to repr type {tgt:#?}",
6035 );
6036 }
6037 }
6038
6039 proptest! {
6040 #![proptest_config(ProptestConfig::with_cases(10000))]
6041 #[mz_ore::test]
6042 #[cfg_attr(miri, ignore)]
6043 fn repr_type_to_sql_type_roundtrip(repr_type in any::<ReprScalarType>()) {
6044 let sql_type = SqlScalarType::from_repr(&repr_type);
6049 assert_eq!(repr_type, ReprScalarType::from(&sql_type));
6050 }
6051 }
6052
6053 proptest! {
6054 #![proptest_config(ProptestConfig::with_cases(10000))]
6055 #[mz_ore::test]
6056 #[cfg_attr(miri, ignore)]
6057 fn sql_type_base_eq_implies_repr_type_eq(
6058 sql_type1 in any::<SqlScalarType>(),
6059 sql_type2 in any::<SqlScalarType>(),
6060 ) {
6061 let repr_type1 = ReprScalarType::from(&sql_type1);
6062 let repr_type2 = ReprScalarType::from(&sql_type2);
6063 if sql_type1.base_eq(&sql_type2) {
6064 assert_eq!(repr_type1, repr_type2);
6065 }
6066 }
6067 }
6068
6069 proptest! {
6070 #![proptest_config(ProptestConfig::with_cases(10000))]
6071 #[mz_ore::test]
6072 #[cfg_attr(miri, ignore)]
6073 fn repr_type_self_union(repr_type in any::<ReprScalarType>()) {
6074 let union = repr_type.union(&repr_type);
6075 assert_ok!(
6076 union,
6077 "every type should self-union \
6078 (update ReprScalarType::union to handle this)",
6079 );
6080 assert_eq!(
6081 union.unwrap(), repr_type,
6082 "every type should self-union to itself",
6083 );
6084 }
6085 }
6086
6087 proptest! {
6088 #[mz_ore::test]
6089 #[cfg_attr(miri, ignore)] fn array_packing_unpacks_correctly(array in arb_array(arb_datum(true))) {
6091 let PropArray(row, elts) = array;
6092 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
6093 let unpacked_datums: Vec<Datum<'_>> = row
6094 .unpack_first().unwrap_array().elements().iter().collect();
6095 assert_eq!(unpacked_datums, datums);
6096 }
6097
6098 #[mz_ore::test]
6099 #[cfg_attr(miri, ignore)] fn list_packing_unpacks_correctly(array in arb_list(arb_datum(true))) {
6101 let PropList(row, elts) = array;
6102 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
6103 let unpacked_datums: Vec<Datum<'_>> = row
6104 .unpack_first().unwrap_list().iter().collect();
6105 assert_eq!(unpacked_datums, datums);
6106 }
6107
6108 #[mz_ore::test]
6109 #[cfg_attr(miri, ignore)] fn dict_packing_unpacks_correctly(array in arb_dict(arb_datum(true))) {
6111 let PropDict(row, elts) = array;
6112 let datums: Vec<(&str, Datum<'_>)> = elts.iter()
6113 .map(|(k, e)| (k.as_str(), e.into())).collect();
6114 let unpacked_datums: Vec<(&str, Datum<'_>)> = row
6115 .unpack_first().unwrap_map().iter().collect();
6116 assert_eq!(unpacked_datums, datums);
6117 }
6118
6119 #[mz_ore::test]
6120 #[cfg_attr(miri, ignore)] fn row_packing_roundtrips_single_valued(
6122 prop_datums in prop::collection::vec(arb_datum(true), 1..100),
6123 ) {
6124 let datums: Vec<Datum<'_>> = prop_datums.iter().map(|pd| pd.into()).collect();
6125 let row = Row::pack(&datums);
6126 let unpacked = row.unpack();
6127 assert_eq!(datums, unpacked);
6128 }
6129
6130 #[mz_ore::test]
6131 #[cfg_attr(miri, ignore)] fn range_packing_unpacks_correctly(range in arb_range(arb_range_data())) {
6133 let PropRange(row, prop_range) = range;
6134 let row = row.unpack_first();
6135 let d = row.unwrap_range();
6136
6137 let (
6138 ((prop_lower, prop_lower_inc), (prop_upper, prop_upper_inc)),
6139 crate::adt::range::RangeInner { lower, upper },
6140 ) = match (prop_range, d.inner) {
6141 (Some(prop_values), Some(inner_range)) => (prop_values, inner_range),
6142 (None, None) => return Ok(()),
6143 _ => panic!("inequivalent row packing"),
6144 };
6145
6146 for (prop_bound, prop_bound_inc, inner_bound, inner_bound_inc) in [
6147 (prop_lower, prop_lower_inc, lower.bound, lower.inclusive),
6148 (prop_upper, prop_upper_inc, upper.bound, upper.inclusive),
6149 ] {
6150 assert_eq!(prop_bound_inc, inner_bound_inc);
6151 match (prop_bound, inner_bound) {
6152 (None, None) => continue,
6153 (Some(p), Some(b)) => {
6154 assert_eq!(Datum::from(&*p), b);
6155 }
6156 _ => panic!("inequivalent row packing"),
6157 }
6158 }
6159 }
6160 }
6161}