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