1use std::borrow::Cow;
11use std::collections::BTreeMap;
12use std::fmt::{self, Debug};
13use std::hash::Hash;
14use std::iter;
15use std::ops::Add;
16use std::sync::LazyLock;
17
18use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
19use dec::OrderedDecimal;
20use enum_kinds::EnumKind;
21use itertools::Itertools;
22use mz_lowertest::MzReflect;
23use mz_ore::Overflowing;
24use mz_ore::cast::CastFrom;
25use mz_ore::str::StrExt;
26use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
27use ordered_float::OrderedFloat;
28use proptest::prelude::*;
29use proptest::strategy::Union;
30use serde::{Deserialize, Serialize};
31use uuid::Uuid;
32
33use crate::adt::array::{Array, ArrayDimension};
34use crate::adt::char::{Char, CharLength};
35use crate::adt::date::Date;
36use crate::adt::interval::Interval;
37use crate::adt::jsonb::{Jsonb, JsonbRef};
38use crate::adt::mz_acl_item::{AclItem, AclMode, MzAclItem};
39use crate::adt::numeric::{Numeric, NumericMaxScale};
40use crate::adt::pg_legacy_name::PgLegacyName;
41use crate::adt::range::{Range, RangeLowerBound, RangeUpperBound};
42use crate::adt::system::{Oid, PgLegacyChar, RegClass, RegProc, RegType};
43use crate::adt::timestamp::{
44 CheckedTimestamp, HIGH_DATE, LOW_DATE, TimestampError, TimestampPrecision,
45};
46use crate::adt::varchar::{VarChar, VarCharMaxLength};
47use crate::relation::ReprColumnType;
48pub use crate::relation_and_scalar::ProtoScalarType;
49pub use crate::relation_and_scalar::proto_scalar_type::ProtoRecordField;
50use crate::role_id::RoleId;
51use crate::row::DatumNested;
52use crate::{CatalogItemId, ColumnName, DatumList, DatumMap, Row, RowArena, SqlColumnType};
53
54#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, EnumKind)]
74#[enum_kind(DatumKind)]
75pub enum Datum<'a> {
76 False,
78 True,
80 Int16(i16),
82 Int32(i32),
84 Int64(i64),
86 UInt8(u8),
88 UInt16(u16),
90 UInt32(u32),
92 UInt64(u64),
94 Float32(OrderedFloat<f32>),
96 Float64(OrderedFloat<f64>),
98 Date(Date),
100 Time(NaiveTime),
102 Timestamp(CheckedTimestamp<NaiveDateTime>),
105 TimestampTz(CheckedTimestamp<DateTime<Utc>>),
107 Interval(Interval),
109 Bytes(&'a [u8]),
111 String(&'a str),
113 Array(Array<'a>),
116 List(DatumList<'a>),
120 Map(DatumMap<'a>),
122 Numeric(OrderedDecimal<Numeric>),
125 JsonNull,
130 Uuid(Uuid),
132 MzTimestamp(crate::Timestamp),
133 Range(Range<DatumNested<'a>>),
135 MzAclItem(MzAclItem),
138 AclItem(AclItem),
141 Dummy,
158 Null,
166 }
172
173impl Debug for Datum<'_> {
174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175 use mz_ore::str::*;
176 match self {
177 Datum::False => write!(f, "False"),
178 Datum::True => write!(f, "True"),
179 Datum::Int16(x) => f.debug_tuple("Int16").field(&redact(x)).finish(),
180 Datum::Int32(x) => f.debug_tuple("Int32").field(&redact(x)).finish(),
181 Datum::Int64(x) => f.debug_tuple("Int64").field(&redact(x)).finish(),
182 Datum::UInt8(x) => f.debug_tuple("UInt8").field(&redact(x)).finish(),
183 Datum::UInt16(x) => f.debug_tuple("UInt16").field(&redact(x)).finish(),
184 Datum::UInt32(x) => f.debug_tuple("UInt32").field(&redact(x)).finish(),
185 Datum::UInt64(x) => f.debug_tuple("UInt64").field(&redact(x)).finish(),
186 Datum::Float32(x) => f.debug_tuple("Float32").field(&redact(x)).finish(),
187 Datum::Float64(x) => f.debug_tuple("Float64").field(&redact(x)).finish(),
188 Datum::Date(x) => f.debug_tuple("Date").field(&redact(x)).finish(),
189 Datum::Time(x) => f.debug_tuple("Time").field(&redact(x)).finish(),
190 Datum::Timestamp(x) => f
191 .debug_tuple("Timestamp")
192 .field(&redact(x.to_naive()))
193 .finish(),
194 Datum::TimestampTz(x) => f
195 .debug_tuple("TimestampTz")
196 .field(&redact(<DateTime<Utc>>::from(*x)))
197 .finish(),
198 Datum::Interval(x) => f.debug_tuple("Interval").field(&redact(x)).finish(),
199 Datum::Bytes(x) => f.debug_tuple("Bytes").field(&redact(x)).finish(),
200 Datum::String(x) => f.debug_tuple("String").field(&redact(x)).finish(),
201 Datum::Array(x) => f.debug_tuple("Array").field(x).finish(),
202 Datum::List(x) => f.debug_tuple("List").field(x).finish(),
203 Datum::Map(x) => f.debug_tuple("Map").field(x).finish(),
204 Datum::Numeric(x) => f.debug_tuple("Numeric").field(&redact(&x.0)).finish(),
205 Datum::JsonNull => f.debug_tuple("JsonNull").finish(),
206 Datum::Uuid(x) => f.debug_tuple("Uuid").field(&redact(x)).finish(),
207 Datum::MzTimestamp(x) => f.debug_tuple("MzTimestamp").field(&redact(x)).finish(),
208 Datum::Range(x) => f.debug_tuple("Range").field(&redact(x)).finish(),
209 Datum::MzAclItem(x) => f.debug_tuple("MzAclItem").field(&redact(x)).finish(),
210 Datum::AclItem(x) => f.debug_tuple("AclItem").field(&redact(x)).finish(),
211 Datum::Dummy => f.debug_tuple("Dummy").finish(),
212 Datum::Null => f.debug_tuple("Null").finish(),
213 }
214 }
215}
216
217impl TryFrom<Datum<'_>> for bool {
218 type Error = ();
219
220 #[inline]
221 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
222 match from {
223 Datum::False => Ok(false),
224 Datum::True => Ok(true),
225 _ => Err(()),
226 }
227 }
228}
229
230impl TryFrom<Datum<'_>> for Option<bool> {
231 type Error = ();
232
233 #[inline]
234 fn try_from(datum: Datum<'_>) -> Result<Self, Self::Error> {
235 match datum {
236 Datum::Null => Ok(None),
237 Datum::False => Ok(Some(false)),
238 Datum::True => Ok(Some(true)),
239 _ => Err(()),
240 }
241 }
242}
243
244impl TryFrom<Datum<'_>> for f32 {
245 type Error = ();
246
247 #[inline]
248 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
249 match from {
250 Datum::Float32(f) => Ok(*f),
251 _ => Err(()),
252 }
253 }
254}
255
256impl TryFrom<Datum<'_>> for Option<f32> {
257 type Error = ();
258
259 #[inline]
260 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
261 match from {
262 Datum::Null => Ok(None),
263 Datum::Float32(f) => Ok(Some(*f)),
264 _ => Err(()),
265 }
266 }
267}
268
269impl TryFrom<Datum<'_>> for OrderedFloat<f32> {
270 type Error = ();
271
272 #[inline]
273 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
274 match from {
275 Datum::Float32(f) => Ok(f),
276 _ => Err(()),
277 }
278 }
279}
280
281impl TryFrom<Datum<'_>> for Option<OrderedFloat<f32>> {
282 type Error = ();
283
284 #[inline]
285 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
286 match from {
287 Datum::Null => Ok(None),
288 Datum::Float32(f) => Ok(Some(f)),
289 _ => Err(()),
290 }
291 }
292}
293
294impl TryFrom<Datum<'_>> for f64 {
295 type Error = ();
296
297 #[inline]
298 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
299 match from {
300 Datum::Float64(f) => Ok(*f),
301 _ => Err(()),
302 }
303 }
304}
305
306impl TryFrom<Datum<'_>> for Option<f64> {
307 type Error = ();
308
309 #[inline]
310 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
311 match from {
312 Datum::Null => Ok(None),
313 Datum::Float64(f) => Ok(Some(*f)),
314 _ => Err(()),
315 }
316 }
317}
318
319impl TryFrom<Datum<'_>> for OrderedFloat<f64> {
320 type Error = ();
321
322 #[inline]
323 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
324 match from {
325 Datum::Float64(f) => Ok(f),
326 _ => Err(()),
327 }
328 }
329}
330
331impl TryFrom<Datum<'_>> for Option<OrderedFloat<f64>> {
332 type Error = ();
333
334 #[inline]
335 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
336 match from {
337 Datum::Null => Ok(None),
338 Datum::Float64(f) => Ok(Some(f)),
339 _ => Err(()),
340 }
341 }
342}
343
344impl TryFrom<Datum<'_>> for i16 {
345 type Error = ();
346
347 #[inline]
348 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
349 match from {
350 Datum::Int16(i) => Ok(i),
351 _ => Err(()),
352 }
353 }
354}
355
356impl TryFrom<Datum<'_>> for Option<i16> {
357 type Error = ();
358
359 #[inline]
360 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
361 match from {
362 Datum::Null => Ok(None),
363 Datum::Int16(i) => Ok(Some(i)),
364 _ => Err(()),
365 }
366 }
367}
368
369impl TryFrom<Datum<'_>> for i32 {
370 type Error = ();
371
372 #[inline]
373 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
374 match from {
375 Datum::Int32(i) => Ok(i),
376 _ => Err(()),
377 }
378 }
379}
380
381impl TryFrom<Datum<'_>> for Option<i32> {
382 type Error = ();
383
384 #[inline]
385 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
386 match from {
387 Datum::Null => Ok(None),
388 Datum::Int32(i) => Ok(Some(i)),
389 _ => Err(()),
390 }
391 }
392}
393
394impl TryFrom<Datum<'_>> for i64 {
395 type Error = ();
396
397 #[inline]
398 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
399 match from {
400 Datum::Int64(i) => Ok(i),
401 _ => Err(()),
402 }
403 }
404}
405
406impl TryFrom<Datum<'_>> for Option<i64> {
407 type Error = ();
408
409 #[inline]
410 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
411 match from {
412 Datum::Null => Ok(None),
413 Datum::Int64(i) => Ok(Some(i)),
414 _ => Err(()),
415 }
416 }
417}
418
419impl TryFrom<Datum<'_>> for u16 {
420 type Error = ();
421
422 #[inline]
423 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
424 match from {
425 Datum::UInt16(u) => Ok(u),
426 _ => Err(()),
427 }
428 }
429}
430
431impl TryFrom<Datum<'_>> for Option<u16> {
432 type Error = ();
433
434 #[inline]
435 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
436 match from {
437 Datum::Null => Ok(None),
438 Datum::UInt16(u) => Ok(Some(u)),
439 _ => Err(()),
440 }
441 }
442}
443
444impl TryFrom<Datum<'_>> for u32 {
445 type Error = ();
446
447 #[inline]
448 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
449 match from {
450 Datum::UInt32(u) => Ok(u),
451 _ => Err(()),
452 }
453 }
454}
455
456impl TryFrom<Datum<'_>> for Option<u32> {
457 type Error = ();
458
459 #[inline]
460 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
461 match from {
462 Datum::Null => Ok(None),
463 Datum::UInt32(u) => Ok(Some(u)),
464 _ => Err(()),
465 }
466 }
467}
468
469impl TryFrom<Datum<'_>> for u64 {
470 type Error = ();
471
472 #[inline]
473 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
474 match from {
475 Datum::UInt64(u) => Ok(u),
476 _ => Err(()),
477 }
478 }
479}
480
481impl TryFrom<Datum<'_>> for Option<u64> {
482 type Error = ();
483
484 #[inline]
485 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
486 match from {
487 Datum::Null => Ok(None),
488 Datum::UInt64(u) => Ok(Some(u)),
489 _ => Err(()),
490 }
491 }
492}
493
494impl TryFrom<Datum<'_>> for CheckedTimestamp<NaiveDateTime> {
495 type Error = ();
496
497 #[inline]
498 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
499 match from {
500 Datum::Timestamp(dt) => Ok(dt),
501 _ => Err(()),
502 }
503 }
504}
505
506impl TryFrom<Datum<'_>> for CheckedTimestamp<DateTime<Utc>> {
507 type Error = ();
508
509 #[inline]
510 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
511 match from {
512 Datum::TimestampTz(dt_tz) => Ok(dt_tz),
513 _ => Err(()),
514 }
515 }
516}
517
518impl TryFrom<Datum<'_>> for Date {
519 type Error = ();
520
521 #[inline]
522 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
523 match from {
524 Datum::Date(d) => Ok(d),
525 _ => Err(()),
526 }
527 }
528}
529
530impl TryFrom<Datum<'_>> for OrderedDecimal<Numeric> {
531 type Error = ();
532
533 #[inline]
534 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
535 match from {
536 Datum::Numeric(n) => Ok(n),
537 _ => Err(()),
538 }
539 }
540}
541
542impl TryFrom<Datum<'_>> for Option<OrderedDecimal<Numeric>> {
543 type Error = ();
544
545 #[inline]
546 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
547 match from {
548 Datum::Null => Ok(None),
549 Datum::Numeric(n) => Ok(Some(n)),
550 _ => Err(()),
551 }
552 }
553}
554
555impl TryFrom<Datum<'_>> for crate::Timestamp {
556 type Error = ();
557
558 #[inline]
559 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
560 match from {
561 Datum::MzTimestamp(n) => Ok(n),
562 _ => Err(()),
563 }
564 }
565}
566
567impl TryFrom<Datum<'_>> for Option<crate::Timestamp> {
568 type Error = ();
569
570 #[inline]
571 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
572 match from {
573 Datum::Null => Ok(None),
574 Datum::MzTimestamp(n) => Ok(Some(n)),
575 _ => Err(()),
576 }
577 }
578}
579
580impl TryFrom<Datum<'_>> for Interval {
581 type Error = ();
582
583 #[inline]
584 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
585 match from {
586 Datum::Interval(i) => Ok(i),
587 _ => Err(()),
588 }
589 }
590}
591
592impl TryFrom<Datum<'_>> for Option<Interval> {
593 type Error = ();
594
595 #[inline]
596 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
597 match from {
598 Datum::Null => Ok(None),
599 Datum::Interval(i) => Ok(Some(i)),
600 _ => Err(()),
601 }
602 }
603}
604
605impl TryFrom<Datum<'_>> for NaiveTime {
606 type Error = ();
607
608 #[inline]
609 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
610 match from {
611 Datum::Time(t) => Ok(t),
612 _ => Err(()),
613 }
614 }
615}
616
617impl TryFrom<Datum<'_>> for Option<NaiveTime> {
618 type Error = ();
619
620 #[inline]
621 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
622 match from {
623 Datum::Null => Ok(None),
624 Datum::Time(t) => Ok(Some(t)),
625 _ => Err(()),
626 }
627 }
628}
629
630impl<'a> Datum<'a> {
631 pub fn is_null(&self) -> bool {
633 matches!(self, Datum::Null)
634 }
635
636 #[track_caller]
642 pub fn unwrap_bool(&self) -> bool {
643 match self {
644 Datum::False => false,
645 Datum::True => true,
646 _ => panic!("Datum::unwrap_bool called on {:?}", self),
647 }
648 }
649
650 #[track_caller]
656 pub fn unwrap_int16(&self) -> i16 {
657 match self {
658 Datum::Int16(i) => *i,
659 _ => panic!("Datum::unwrap_int16 called on {:?}", self),
660 }
661 }
662
663 #[track_caller]
669 pub fn unwrap_int32(&self) -> i32 {
670 match self {
671 Datum::Int32(i) => *i,
672 _ => panic!("Datum::unwrap_int32 called on {:?}", self),
673 }
674 }
675
676 #[track_caller]
682 pub fn unwrap_int64(&self) -> i64 {
683 match self {
684 Datum::Int64(i) => *i,
685 _ => panic!("Datum::unwrap_int64 called on {:?}", self),
686 }
687 }
688
689 #[track_caller]
695 pub fn unwrap_uint8(&self) -> u8 {
696 match self {
697 Datum::UInt8(u) => *u,
698 _ => panic!("Datum::unwrap_uint8 called on {:?}", self),
699 }
700 }
701
702 #[track_caller]
708 pub fn unwrap_uint16(&self) -> u16 {
709 match self {
710 Datum::UInt16(u) => *u,
711 _ => panic!("Datum::unwrap_uint16 called on {:?}", self),
712 }
713 }
714
715 #[track_caller]
721 pub fn unwrap_uint32(&self) -> u32 {
722 match self {
723 Datum::UInt32(u) => *u,
724 _ => panic!("Datum::unwrap_uint32 called on {:?}", self),
725 }
726 }
727
728 #[track_caller]
734 pub fn unwrap_uint64(&self) -> u64 {
735 match self {
736 Datum::UInt64(u) => *u,
737 _ => panic!("Datum::unwrap_uint64 called on {:?}", self),
738 }
739 }
740
741 #[track_caller]
742 pub fn unwrap_ordered_float32(&self) -> OrderedFloat<f32> {
743 match self {
744 Datum::Float32(f) => *f,
745 _ => panic!("Datum::unwrap_ordered_float32 called on {:?}", self),
746 }
747 }
748
749 #[track_caller]
750 pub fn unwrap_ordered_float64(&self) -> OrderedFloat<f64> {
751 match self {
752 Datum::Float64(f) => *f,
753 _ => panic!("Datum::unwrap_ordered_float64 called on {:?}", self),
754 }
755 }
756
757 #[track_caller]
763 pub fn unwrap_float32(&self) -> f32 {
764 match self {
765 Datum::Float32(f) => f.into_inner(),
766 _ => panic!("Datum::unwrap_float32 called on {:?}", self),
767 }
768 }
769
770 #[track_caller]
776 pub fn unwrap_float64(&self) -> f64 {
777 match self {
778 Datum::Float64(f) => f.into_inner(),
779 _ => panic!("Datum::unwrap_float64 called on {:?}", self),
780 }
781 }
782
783 #[track_caller]
789 pub fn unwrap_date(&self) -> Date {
790 match self {
791 Datum::Date(d) => *d,
792 _ => panic!("Datum::unwrap_date called on {:?}", self),
793 }
794 }
795
796 #[track_caller]
802 pub fn unwrap_time(&self) -> chrono::NaiveTime {
803 match self {
804 Datum::Time(t) => *t,
805 _ => panic!("Datum::unwrap_time called on {:?}", self),
806 }
807 }
808
809 #[track_caller]
815 pub fn unwrap_timestamp(&self) -> CheckedTimestamp<chrono::NaiveDateTime> {
816 match self {
817 Datum::Timestamp(ts) => *ts,
818 _ => panic!("Datum::unwrap_timestamp called on {:?}", self),
819 }
820 }
821
822 #[track_caller]
828 pub fn unwrap_timestamptz(&self) -> CheckedTimestamp<chrono::DateTime<Utc>> {
829 match self {
830 Datum::TimestampTz(ts) => *ts,
831 _ => panic!("Datum::unwrap_timestamptz called on {:?}", self),
832 }
833 }
834
835 #[track_caller]
841 pub fn unwrap_interval(&self) -> Interval {
842 match self {
843 Datum::Interval(iv) => *iv,
844 _ => panic!("Datum::unwrap_interval called on {:?}", self),
845 }
846 }
847
848 #[track_caller]
854 pub fn unwrap_str(&self) -> &'a str {
855 match self {
856 Datum::String(s) => s,
857 _ => panic!("Datum::unwrap_string called on {:?}", self),
858 }
859 }
860
861 #[track_caller]
867 pub fn unwrap_bytes(&self) -> &'a [u8] {
868 match self {
869 Datum::Bytes(b) => b,
870 _ => panic!("Datum::unwrap_bytes called on {:?}", self),
871 }
872 }
873
874 #[track_caller]
880 pub fn unwrap_uuid(&self) -> Uuid {
881 match self {
882 Datum::Uuid(u) => *u,
883 _ => panic!("Datum::unwrap_uuid called on {:?}", self),
884 }
885 }
886
887 #[track_caller]
893 pub fn unwrap_array(&self) -> Array<'a> {
894 match self {
895 Datum::Array(array) => *array,
896 _ => panic!("Datum::unwrap_array called on {:?}", self),
897 }
898 }
899
900 #[track_caller]
906 pub fn unwrap_list(&self) -> DatumList<'a> {
907 match self {
908 Datum::List(list) => *list,
909 _ => panic!("Datum::unwrap_list called on {:?}", self),
910 }
911 }
912
913 #[track_caller]
919 pub fn unwrap_map(&self) -> DatumMap<'a> {
920 match self {
921 Datum::Map(dict) => *dict,
922 _ => panic!("Datum::unwrap_dict called on {:?}", self),
923 }
924 }
925
926 #[track_caller]
932 pub fn unwrap_numeric(&self) -> OrderedDecimal<Numeric> {
933 match self {
934 Datum::Numeric(n) => *n,
935 _ => panic!("Datum::unwrap_numeric called on {:?}", self),
936 }
937 }
938
939 #[track_caller]
945 pub fn unwrap_mz_timestamp(&self) -> crate::Timestamp {
946 match self {
947 Datum::MzTimestamp(t) => *t,
948 _ => panic!("Datum::unwrap_mz_timestamp called on {:?}", self),
949 }
950 }
951
952 #[track_caller]
963 pub fn unwrap_range(&self) -> Range<Datum<'a>> {
964 match self {
965 Datum::Range(range) => range.into_bounds(|b| b.datum()),
966 _ => panic!("Datum::unwrap_range called on {:?}", self),
967 }
968 }
969
970 #[track_caller]
976 pub fn unwrap_mz_acl_item(&self) -> MzAclItem {
977 match self {
978 Datum::MzAclItem(mz_acl_item) => *mz_acl_item,
979 _ => panic!("Datum::unwrap_mz_acl_item called on {:?}", self),
980 }
981 }
982
983 #[track_caller]
989 pub fn unwrap_acl_item(&self) -> AclItem {
990 match self {
991 Datum::AclItem(acl_item) => *acl_item,
992 _ => panic!("Datum::unwrap_acl_item called on {:?}", self),
993 }
994 }
995
996 pub fn is_instance_of(self, column_type: &ReprColumnType) -> bool {
1000 fn is_instance_of_scalar(datum: Datum, scalar_type: &ReprScalarType) -> bool {
1001 if let ReprScalarType::Jsonb = scalar_type {
1002 match datum {
1004 Datum::Dummy => false,
1005 Datum::JsonNull
1006 | Datum::False
1007 | Datum::True
1008 | Datum::Numeric(_)
1009 | Datum::String(_) => true,
1010 Datum::List(list) => list
1011 .iter()
1012 .all(|elem| is_instance_of_scalar(elem, scalar_type)),
1013 Datum::Map(dict) => dict
1014 .iter()
1015 .all(|(_key, val)| is_instance_of_scalar(val, scalar_type)),
1016 _ => false,
1017 }
1018 } else {
1019 match (datum, scalar_type) {
1021 (Datum::Dummy, _) => false,
1022 (Datum::Null, _) => false,
1023 (Datum::False, ReprScalarType::Bool) => true,
1024 (Datum::False, _) => false,
1025 (Datum::True, ReprScalarType::Bool) => true,
1026 (Datum::True, _) => false,
1027 (Datum::Int16(_), ReprScalarType::Int16) => true,
1028 (Datum::Int16(_), _) => false,
1029 (Datum::Int32(_), ReprScalarType::Int32) => true,
1030 (Datum::Int32(_), _) => false,
1031 (Datum::Int64(_), ReprScalarType::Int64) => true,
1032 (Datum::Int64(_), _) => false,
1033 (Datum::UInt8(_), ReprScalarType::UInt8) => true,
1034 (Datum::UInt8(_), _) => false,
1035 (Datum::UInt16(_), ReprScalarType::UInt16) => true,
1036 (Datum::UInt16(_), _) => false,
1037 (Datum::UInt32(_), ReprScalarType::UInt32) => true,
1038 (Datum::UInt32(_), _) => false,
1039 (Datum::UInt64(_), ReprScalarType::UInt64) => true,
1040 (Datum::UInt64(_), _) => false,
1041 (Datum::Float32(_), ReprScalarType::Float32) => true,
1042 (Datum::Float32(_), _) => false,
1043 (Datum::Float64(_), ReprScalarType::Float64) => true,
1044 (Datum::Float64(_), _) => false,
1045 (Datum::Date(_), ReprScalarType::Date) => true,
1046 (Datum::Date(_), _) => false,
1047 (Datum::Time(_), ReprScalarType::Time) => true,
1048 (Datum::Time(_), _) => false,
1049 (Datum::Timestamp(_), ReprScalarType::Timestamp { .. }) => true,
1050 (Datum::Timestamp(_), _) => false,
1051 (Datum::TimestampTz(_), ReprScalarType::TimestampTz { .. }) => true,
1052 (Datum::TimestampTz(_), _) => false,
1053 (Datum::Interval(_), ReprScalarType::Interval) => true,
1054 (Datum::Interval(_), _) => false,
1055 (Datum::Bytes(_), ReprScalarType::Bytes) => true,
1056 (Datum::Bytes(_), _) => false,
1057 (Datum::String(_), ReprScalarType::String) => true,
1058 (Datum::String(_), _) => false,
1059 (Datum::Uuid(_), ReprScalarType::Uuid) => true,
1060 (Datum::Uuid(_), _) => false,
1061 (Datum::Array(array), ReprScalarType::Array(t)) => {
1062 array.elements.iter().all(|e| match e {
1063 Datum::Null => true,
1064 _ => is_instance_of_scalar(e, t),
1065 })
1066 }
1067 (Datum::Array(array), ReprScalarType::Int2Vector) => {
1068 array.dims().len() == 1
1069 && array
1070 .elements
1071 .iter()
1072 .all(|e| is_instance_of_scalar(e, &ReprScalarType::Int16))
1073 }
1074 (Datum::Array(_), _) => false,
1075 (Datum::List(list), ReprScalarType::List { element_type, .. }) => list
1076 .iter()
1077 .all(|e| e.is_null() || is_instance_of_scalar(e, element_type)),
1078 (Datum::List(list), ReprScalarType::Record { fields, .. }) => {
1079 if list.iter().count() != fields.len() {
1080 return false;
1081 }
1082
1083 list.iter().zip_eq(fields).all(|(e, t)| {
1084 (e.is_null() && t.nullable) || is_instance_of_scalar(e, &t.scalar_type)
1085 })
1086 }
1087 (Datum::List(_), _) => false,
1088 (Datum::Map(map), ReprScalarType::Map { value_type, .. }) => map
1089 .iter()
1090 .all(|(_k, v)| v.is_null() || is_instance_of_scalar(v, value_type)),
1091 (Datum::Map(_), _) => false,
1092 (Datum::JsonNull, _) => false,
1093 (Datum::Numeric(_), ReprScalarType::Numeric) => true,
1094 (Datum::Numeric(_), _) => false,
1095 (Datum::MzTimestamp(_), ReprScalarType::MzTimestamp) => true,
1096 (Datum::MzTimestamp(_), _) => false,
1097 (Datum::Range(Range { inner }), ReprScalarType::Range { element_type }) => {
1098 match inner {
1099 None => true,
1100 Some(inner) => {
1101 true && match inner.lower.bound {
1102 None => true,
1103 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1104 } && match inner.upper.bound {
1105 None => true,
1106 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1107 }
1108 }
1109 }
1110 }
1111 (Datum::Range(_), _) => false,
1112 (Datum::MzAclItem(_), ReprScalarType::MzAclItem) => true,
1113 (Datum::MzAclItem(_), _) => false,
1114 (Datum::AclItem(_), ReprScalarType::AclItem) => true,
1115 (Datum::AclItem(_), _) => false,
1116 }
1117 }
1118 }
1119 if column_type.nullable {
1120 if let Datum::Null = self {
1121 return true;
1122 }
1123 }
1124 is_instance_of_scalar(self, &column_type.scalar_type)
1125 }
1126
1127 pub fn is_instance_of_sql(self, column_type: &SqlColumnType) -> bool {
1131 fn is_instance_of_scalar(datum: Datum, scalar_type: &SqlScalarType) -> bool {
1132 if let SqlScalarType::Jsonb = scalar_type {
1133 match datum {
1135 Datum::Dummy => false,
1136 Datum::JsonNull
1137 | Datum::False
1138 | Datum::True
1139 | Datum::Numeric(_)
1140 | Datum::String(_) => true,
1141 Datum::List(list) => list
1142 .iter()
1143 .all(|elem| is_instance_of_scalar(elem, scalar_type)),
1144 Datum::Map(dict) => dict
1145 .iter()
1146 .all(|(_key, val)| is_instance_of_scalar(val, scalar_type)),
1147 _ => false,
1148 }
1149 } else {
1150 match (datum, scalar_type) {
1152 (Datum::Dummy, _) => false,
1153 (Datum::Null, _) => false,
1154 (Datum::False, SqlScalarType::Bool) => true,
1155 (Datum::False, _) => false,
1156 (Datum::True, SqlScalarType::Bool) => true,
1157 (Datum::True, _) => false,
1158 (Datum::Int16(_), SqlScalarType::Int16) => true,
1159 (Datum::Int16(_), _) => false,
1160 (Datum::Int32(_), SqlScalarType::Int32) => true,
1161 (Datum::Int32(_), _) => false,
1162 (Datum::Int64(_), SqlScalarType::Int64) => true,
1163 (Datum::Int64(_), _) => false,
1164 (Datum::UInt8(_), SqlScalarType::PgLegacyChar) => true,
1165 (Datum::UInt8(_), _) => false,
1166 (Datum::UInt16(_), SqlScalarType::UInt16) => true,
1167 (Datum::UInt16(_), _) => false,
1168 (Datum::UInt32(_), SqlScalarType::Oid) => true,
1169 (Datum::UInt32(_), SqlScalarType::RegClass) => true,
1170 (Datum::UInt32(_), SqlScalarType::RegProc) => true,
1171 (Datum::UInt32(_), SqlScalarType::RegType) => true,
1172 (Datum::UInt32(_), SqlScalarType::UInt32) => true,
1173 (Datum::UInt32(_), _) => false,
1174 (Datum::UInt64(_), SqlScalarType::UInt64) => true,
1175 (Datum::UInt64(_), _) => false,
1176 (Datum::Float32(_), SqlScalarType::Float32) => true,
1177 (Datum::Float32(_), _) => false,
1178 (Datum::Float64(_), SqlScalarType::Float64) => true,
1179 (Datum::Float64(_), _) => false,
1180 (Datum::Date(_), SqlScalarType::Date) => true,
1181 (Datum::Date(_), _) => false,
1182 (Datum::Time(_), SqlScalarType::Time) => true,
1183 (Datum::Time(_), _) => false,
1184 (Datum::Timestamp(_), SqlScalarType::Timestamp { .. }) => true,
1185 (Datum::Timestamp(_), _) => false,
1186 (Datum::TimestampTz(_), SqlScalarType::TimestampTz { .. }) => true,
1187 (Datum::TimestampTz(_), _) => false,
1188 (Datum::Interval(_), SqlScalarType::Interval) => true,
1189 (Datum::Interval(_), _) => false,
1190 (Datum::Bytes(_), SqlScalarType::Bytes) => true,
1191 (Datum::Bytes(_), _) => false,
1192 (Datum::String(_), SqlScalarType::String)
1193 | (Datum::String(_), SqlScalarType::VarChar { .. })
1194 | (Datum::String(_), SqlScalarType::Char { .. })
1195 | (Datum::String(_), SqlScalarType::PgLegacyName) => true,
1196 (Datum::String(_), _) => false,
1197 (Datum::Uuid(_), SqlScalarType::Uuid) => true,
1198 (Datum::Uuid(_), _) => false,
1199 (Datum::Array(array), SqlScalarType::Array(t)) => {
1200 array.elements.iter().all(|e| match e {
1201 Datum::Null => true,
1202 _ => is_instance_of_scalar(e, t),
1203 })
1204 }
1205 (Datum::Array(array), SqlScalarType::Int2Vector) => {
1206 array.dims().len() == 1
1207 && array
1208 .elements
1209 .iter()
1210 .all(|e| is_instance_of_scalar(e, &SqlScalarType::Int16))
1211 }
1212 (Datum::Array(_), _) => false,
1213 (Datum::List(list), SqlScalarType::List { element_type, .. }) => list
1214 .iter()
1215 .all(|e| e.is_null() || is_instance_of_scalar(e, element_type)),
1216 (Datum::List(list), SqlScalarType::Record { fields, .. }) => {
1217 if list.iter().count() != fields.len() {
1218 return false;
1219 }
1220
1221 list.iter().zip_eq(fields).all(|(e, (_, t))| {
1222 (e.is_null() && t.nullable) || is_instance_of_scalar(e, &t.scalar_type)
1223 })
1224 }
1225 (Datum::List(_), _) => false,
1226 (Datum::Map(map), SqlScalarType::Map { value_type, .. }) => map
1227 .iter()
1228 .all(|(_k, v)| v.is_null() || is_instance_of_scalar(v, value_type)),
1229 (Datum::Map(_), _) => false,
1230 (Datum::JsonNull, _) => false,
1231 (Datum::Numeric(_), SqlScalarType::Numeric { .. }) => true,
1232 (Datum::Numeric(_), _) => false,
1233 (Datum::MzTimestamp(_), SqlScalarType::MzTimestamp) => true,
1234 (Datum::MzTimestamp(_), _) => false,
1235 (Datum::Range(Range { inner }), SqlScalarType::Range { element_type }) => {
1236 match inner {
1237 None => true,
1238 Some(inner) => {
1239 true && match inner.lower.bound {
1240 None => true,
1241 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1242 } && match inner.upper.bound {
1243 None => true,
1244 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1245 }
1246 }
1247 }
1248 }
1249 (Datum::Range(_), _) => false,
1250 (Datum::MzAclItem(_), SqlScalarType::MzAclItem) => true,
1251 (Datum::MzAclItem(_), _) => false,
1252 (Datum::AclItem(_), SqlScalarType::AclItem) => true,
1253 (Datum::AclItem(_), _) => false,
1254 }
1255 }
1256 }
1257 if column_type.nullable {
1258 if let Datum::Null = self {
1259 return true;
1260 }
1261 }
1262 is_instance_of_scalar(self, &column_type.scalar_type)
1263 }
1264}
1265
1266impl<'a> From<bool> for Datum<'a> {
1267 #[inline]
1268 fn from(b: bool) -> Datum<'a> {
1269 if b { Datum::True } else { Datum::False }
1270 }
1271}
1272
1273impl<'a, T> From<Overflowing<T>> for Datum<'a>
1276where
1277 Datum<'a>: From<T>,
1278{
1279 #[inline]
1280 fn from(i: Overflowing<T>) -> Datum<'a> {
1281 Datum::from(i.into_inner())
1282 }
1283}
1284
1285impl<'a> From<i16> for Datum<'a> {
1286 #[inline]
1287 fn from(i: i16) -> Datum<'a> {
1288 Datum::Int16(i)
1289 }
1290}
1291
1292impl<'a> From<i32> for Datum<'a> {
1293 #[inline]
1294 fn from(i: i32) -> Datum<'a> {
1295 Datum::Int32(i)
1296 }
1297}
1298
1299impl<'a> From<i64> for Datum<'a> {
1300 #[inline]
1301 fn from(i: i64) -> Datum<'a> {
1302 Datum::Int64(i)
1303 }
1304}
1305
1306impl<'a> From<u8> for Datum<'a> {
1307 #[inline]
1308 fn from(u: u8) -> Datum<'a> {
1309 Datum::UInt8(u)
1310 }
1311}
1312
1313impl<'a> From<u16> for Datum<'a> {
1314 #[inline]
1315 fn from(u: u16) -> Datum<'a> {
1316 Datum::UInt16(u)
1317 }
1318}
1319
1320impl<'a> From<u32> for Datum<'a> {
1321 #[inline]
1322 fn from(u: u32) -> Datum<'a> {
1323 Datum::UInt32(u)
1324 }
1325}
1326
1327impl<'a> From<u64> for Datum<'a> {
1328 #[inline]
1329 fn from(u: u64) -> Datum<'a> {
1330 Datum::UInt64(u)
1331 }
1332}
1333
1334impl<'a> From<OrderedFloat<f32>> for Datum<'a> {
1335 #[inline]
1336 fn from(f: OrderedFloat<f32>) -> Datum<'a> {
1337 Datum::Float32(f)
1338 }
1339}
1340
1341impl<'a> From<OrderedFloat<f64>> for Datum<'a> {
1342 #[inline]
1343 fn from(f: OrderedFloat<f64>) -> Datum<'a> {
1344 Datum::Float64(f)
1345 }
1346}
1347
1348impl<'a> From<f32> for Datum<'a> {
1349 #[inline]
1350 fn from(f: f32) -> Datum<'a> {
1351 Datum::Float32(OrderedFloat(f))
1352 }
1353}
1354
1355impl<'a> From<f64> for Datum<'a> {
1356 #[inline]
1357 fn from(f: f64) -> Datum<'a> {
1358 Datum::Float64(OrderedFloat(f))
1359 }
1360}
1361
1362impl<'a> From<i128> for Datum<'a> {
1363 #[inline]
1364 fn from(d: i128) -> Datum<'a> {
1365 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1366 }
1367}
1368
1369impl<'a> From<u128> for Datum<'a> {
1370 #[inline]
1371 fn from(d: u128) -> Datum<'a> {
1372 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1373 }
1374}
1375
1376impl<'a> From<Numeric> for Datum<'a> {
1377 #[inline]
1378 fn from(n: Numeric) -> Datum<'a> {
1379 Datum::Numeric(OrderedDecimal(n))
1380 }
1381}
1382
1383impl<'a> From<OrderedDecimal<Numeric>> for Datum<'a> {
1384 #[inline]
1385 fn from(n: OrderedDecimal<Numeric>) -> Datum<'a> {
1386 Datum::Numeric(n)
1387 }
1388}
1389
1390impl<'a> From<chrono::Duration> for Datum<'a> {
1391 #[inline]
1392 fn from(duration: chrono::Duration) -> Datum<'a> {
1393 let micros = duration.num_microseconds().unwrap_or(0);
1394 Datum::Interval(Interval::new(0, 0, micros))
1395 }
1396}
1397
1398impl<'a> From<Interval> for Datum<'a> {
1399 #[inline]
1400 fn from(other: Interval) -> Datum<'a> {
1401 Datum::Interval(other)
1402 }
1403}
1404
1405impl<'a> From<&'a str> for Datum<'a> {
1406 #[inline]
1407 fn from(s: &'a str) -> Datum<'a> {
1408 Datum::String(s)
1409 }
1410}
1411
1412impl<'a> From<&'a [u8]> for Datum<'a> {
1413 #[inline]
1414 fn from(b: &'a [u8]) -> Datum<'a> {
1415 Datum::Bytes(b)
1416 }
1417}
1418
1419impl<'a> From<Date> for Datum<'a> {
1420 #[inline]
1421 fn from(d: Date) -> Datum<'a> {
1422 Datum::Date(d)
1423 }
1424}
1425
1426impl<'a> From<NaiveTime> for Datum<'a> {
1427 #[inline]
1428 fn from(t: NaiveTime) -> Datum<'a> {
1429 Datum::Time(t)
1430 }
1431}
1432
1433impl<'a> From<CheckedTimestamp<NaiveDateTime>> for Datum<'a> {
1434 #[inline]
1435 fn from(dt: CheckedTimestamp<NaiveDateTime>) -> Datum<'a> {
1436 Datum::Timestamp(dt)
1437 }
1438}
1439
1440impl<'a> From<CheckedTimestamp<DateTime<Utc>>> for Datum<'a> {
1441 #[inline]
1442 fn from(dt: CheckedTimestamp<DateTime<Utc>>) -> Datum<'a> {
1443 Datum::TimestampTz(dt)
1444 }
1445}
1446
1447impl<'a> TryInto<Datum<'a>> for NaiveDateTime {
1448 type Error = TimestampError;
1449
1450 #[inline]
1451 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1452 let t = CheckedTimestamp::from_timestamplike(self)?;
1453 Ok(t.into())
1454 }
1455}
1456
1457impl<'a> TryInto<Datum<'a>> for DateTime<Utc> {
1458 type Error = TimestampError;
1459
1460 #[inline]
1461 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1462 let t = CheckedTimestamp::from_timestamplike(self)?;
1463 Ok(t.into())
1464 }
1465}
1466
1467impl<'a> From<Uuid> for Datum<'a> {
1468 #[inline]
1469 fn from(uuid: Uuid) -> Datum<'a> {
1470 Datum::Uuid(uuid)
1471 }
1472}
1473impl<'a> From<crate::Timestamp> for Datum<'a> {
1474 #[inline]
1475 fn from(ts: crate::Timestamp) -> Datum<'a> {
1476 Datum::MzTimestamp(ts)
1477 }
1478}
1479
1480impl<'a> From<MzAclItem> for Datum<'a> {
1481 #[inline]
1482 fn from(mz_acl_item: MzAclItem) -> Self {
1483 Datum::MzAclItem(mz_acl_item)
1484 }
1485}
1486
1487impl<'a, T> From<Option<T>> for Datum<'a>
1488where
1489 Datum<'a>: From<T>,
1490{
1491 fn from(o: Option<T>) -> Datum<'a> {
1492 match o {
1493 Some(d) => d.into(),
1494 None => Datum::Null,
1495 }
1496 }
1497}
1498
1499fn write_delimited<T, TS, F>(
1500 f: &mut fmt::Formatter,
1501 delimiter: &str,
1502 things: TS,
1503 write: F,
1504) -> fmt::Result
1505where
1506 TS: IntoIterator<Item = T>,
1507 F: Fn(&mut fmt::Formatter, T) -> fmt::Result,
1508{
1509 let mut iter = things.into_iter().peekable();
1510 while let Some(thing) = iter.next() {
1511 write(f, thing)?;
1512 if iter.peek().is_some() {
1513 f.write_str(delimiter)?;
1514 }
1515 }
1516 Ok(())
1517}
1518
1519impl fmt::Display for Datum<'_> {
1520 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1521 match self {
1522 Datum::Null => f.write_str("null"),
1523 Datum::True => f.write_str("true"),
1524 Datum::False => f.write_str("false"),
1525 Datum::Int16(num) => write!(f, "{}", num),
1526 Datum::Int32(num) => write!(f, "{}", num),
1527 Datum::Int64(num) => write!(f, "{}", num),
1528 Datum::UInt8(num) => write!(f, "{}", num),
1529 Datum::UInt16(num) => write!(f, "{}", num),
1530 Datum::UInt32(num) => write!(f, "{}", num),
1531 Datum::UInt64(num) => write!(f, "{}", num),
1532 Datum::Float32(num) => write!(f, "{}", num),
1533 Datum::Float64(num) => write!(f, "{}", num),
1534 Datum::Date(d) => write!(f, "{}", d),
1535 Datum::Time(t) => write!(f, "{}", t),
1536 Datum::Timestamp(t) => write!(f, "{}", t),
1537 Datum::TimestampTz(t) => write!(f, "{}", t),
1538 Datum::Interval(iv) => write!(f, "{}", iv),
1539 Datum::Bytes(dat) => {
1540 f.write_str("0x")?;
1541 for b in dat.iter() {
1542 write!(f, "{:02x}", b)?;
1543 }
1544 Ok(())
1545 }
1546 Datum::String(s) => {
1547 write!(f, "{}", s.escaped())
1548 }
1549 Datum::Uuid(u) => write!(f, "{}", u),
1550 Datum::Array(array) => {
1551 if array.dims().into_iter().any(|dim| dim.lower_bound != 1) {
1552 write_delimited(f, "", array.dims().into_iter(), |f, e| {
1553 let (lower, upper) = e.dimension_bounds();
1554 write!(f, "[{}:{}]", lower, upper)
1555 })?;
1556 f.write_str("=")?;
1557 }
1558 f.write_str("{")?;
1559 write_delimited(f, ", ", array.elements, |f, e| write!(f, "{}", e))?;
1560 f.write_str("}")
1561 }
1562 Datum::List(list) => {
1563 f.write_str("[")?;
1564 write_delimited(f, ", ", *list, |f, e| write!(f, "{}", e))?;
1565 f.write_str("]")
1566 }
1567 Datum::Map(dict) => {
1568 f.write_str("{")?;
1569 write_delimited(f, ", ", dict, |f, (k, v)| write!(f, "{}: {}", k, v))?;
1570 f.write_str("}")
1571 }
1572 Datum::Numeric(n) => write!(f, "{}", n.0.to_standard_notation_string()),
1573 Datum::MzTimestamp(t) => write!(f, "{}", t),
1574 Datum::JsonNull => f.write_str("json_null"),
1575 Datum::Dummy => f.write_str("dummy"),
1576 Datum::Range(i) => write!(f, "{}", i),
1577 Datum::MzAclItem(mz_acl_item) => write!(f, "{mz_acl_item}"),
1578 Datum::AclItem(acl_item) => write!(f, "{acl_item}"),
1579 }
1580 }
1581}
1582
1583#[derive(
1593 Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash, EnumKind, MzReflect,
1594)]
1595#[enum_kind(SqlScalarBaseType, derive(PartialOrd, Ord, Hash))]
1596pub enum SqlScalarType {
1597 Bool,
1599 Int16,
1601 Int32,
1603 Int64,
1605 UInt16,
1607 UInt32,
1609 UInt64,
1611 Float32,
1613 Float64,
1615 Numeric {
1625 max_scale: Option<NumericMaxScale>,
1626 },
1627 Date,
1629 Time,
1631 Timestamp {
1633 precision: Option<TimestampPrecision>,
1634 },
1635 TimestampTz {
1637 precision: Option<TimestampPrecision>,
1638 },
1639 Interval,
1641 PgLegacyChar,
1646 PgLegacyName,
1652 Bytes,
1654 String,
1656 Char {
1662 length: Option<CharLength>,
1663 },
1664 VarChar {
1667 max_length: Option<VarCharMaxLength>,
1668 },
1669 Jsonb,
1681 Uuid,
1683 Array(Box<SqlScalarType>),
1689 List {
1694 element_type: Box<SqlScalarType>,
1695 custom_id: Option<CatalogItemId>,
1696 },
1697 Record {
1699 fields: Box<[(ColumnName, SqlColumnType)]>,
1704 custom_id: Option<CatalogItemId>,
1705 },
1706 Oid,
1708 Map {
1714 value_type: Box<SqlScalarType>,
1715 custom_id: Option<CatalogItemId>,
1716 },
1717 RegProc,
1719 RegType,
1721 RegClass,
1723 Int2Vector,
1726 MzTimestamp,
1728 Range {
1729 element_type: Box<SqlScalarType>,
1730 },
1731 MzAclItem,
1733 AclItem,
1735}
1736
1737impl RustType<ProtoRecordField> for (ColumnName, SqlColumnType) {
1738 fn into_proto(&self) -> ProtoRecordField {
1739 ProtoRecordField {
1740 column_name: Some(self.0.into_proto()),
1741 column_type: Some(self.1.into_proto()),
1742 }
1743 }
1744
1745 fn from_proto(proto: ProtoRecordField) -> Result<Self, TryFromProtoError> {
1746 Ok((
1747 proto
1748 .column_name
1749 .into_rust_if_some("ProtoRecordField::column_name")?,
1750 proto
1751 .column_type
1752 .into_rust_if_some("ProtoRecordField::column_type")?,
1753 ))
1754 }
1755}
1756
1757impl RustType<ProtoScalarType> for SqlScalarType {
1758 fn into_proto(&self) -> ProtoScalarType {
1759 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1760 use crate::relation_and_scalar::proto_scalar_type::*;
1761
1762 ProtoScalarType {
1763 kind: Some(match self {
1764 SqlScalarType::Bool => Bool(()),
1765 SqlScalarType::Int16 => Int16(()),
1766 SqlScalarType::Int32 => Int32(()),
1767 SqlScalarType::Int64 => Int64(()),
1768 SqlScalarType::UInt16 => UInt16(()),
1769 SqlScalarType::UInt32 => UInt32(()),
1770 SqlScalarType::UInt64 => UInt64(()),
1771 SqlScalarType::Float32 => Float32(()),
1772 SqlScalarType::Float64 => Float64(()),
1773 SqlScalarType::Date => Date(()),
1774 SqlScalarType::Time => Time(()),
1775 SqlScalarType::Timestamp { precision } => Timestamp(ProtoTimestamp {
1776 precision: precision.into_proto(),
1777 }),
1778 SqlScalarType::TimestampTz { precision } => TimestampTz(ProtoTimestampTz {
1779 precision: precision.into_proto(),
1780 }),
1781 SqlScalarType::Interval => Interval(()),
1782 SqlScalarType::PgLegacyChar => PgLegacyChar(()),
1783 SqlScalarType::PgLegacyName => PgLegacyName(()),
1784 SqlScalarType::Bytes => Bytes(()),
1785 SqlScalarType::String => String(()),
1786 SqlScalarType::Jsonb => Jsonb(()),
1787 SqlScalarType::Uuid => Uuid(()),
1788 SqlScalarType::Oid => Oid(()),
1789 SqlScalarType::RegProc => RegProc(()),
1790 SqlScalarType::RegType => RegType(()),
1791 SqlScalarType::RegClass => RegClass(()),
1792 SqlScalarType::Int2Vector => Int2Vector(()),
1793
1794 SqlScalarType::Numeric { max_scale } => Numeric(max_scale.into_proto()),
1795 SqlScalarType::Char { length } => Char(ProtoChar {
1796 length: length.into_proto(),
1797 }),
1798 SqlScalarType::VarChar { max_length } => VarChar(ProtoVarChar {
1799 max_length: max_length.into_proto(),
1800 }),
1801
1802 SqlScalarType::List {
1803 element_type,
1804 custom_id,
1805 } => List(Box::new(ProtoList {
1806 element_type: Some(element_type.into_proto()),
1807 custom_id: custom_id.map(|id| id.into_proto()),
1808 })),
1809 SqlScalarType::Record { custom_id, fields } => Record(ProtoRecord {
1810 custom_id: custom_id.map(|id| id.into_proto()),
1811 fields: fields.into_proto(),
1812 }),
1813 SqlScalarType::Array(typ) => Array(typ.into_proto()),
1814 SqlScalarType::Map {
1815 value_type,
1816 custom_id,
1817 } => Map(Box::new(ProtoMap {
1818 value_type: Some(value_type.into_proto()),
1819 custom_id: custom_id.map(|id| id.into_proto()),
1820 })),
1821 SqlScalarType::MzTimestamp => MzTimestamp(()),
1822 SqlScalarType::Range { element_type } => Range(Box::new(ProtoRange {
1823 element_type: Some(element_type.into_proto()),
1824 })),
1825 SqlScalarType::MzAclItem => MzAclItem(()),
1826 SqlScalarType::AclItem => AclItem(()),
1827 }),
1828 }
1829 }
1830
1831 fn from_proto(proto: ProtoScalarType) -> Result<Self, TryFromProtoError> {
1832 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1833
1834 let kind = proto
1835 .kind
1836 .ok_or_else(|| TryFromProtoError::missing_field("ProtoScalarType::Kind"))?;
1837
1838 match kind {
1839 Bool(()) => Ok(SqlScalarType::Bool),
1840 Int16(()) => Ok(SqlScalarType::Int16),
1841 Int32(()) => Ok(SqlScalarType::Int32),
1842 Int64(()) => Ok(SqlScalarType::Int64),
1843 UInt16(()) => Ok(SqlScalarType::UInt16),
1844 UInt32(()) => Ok(SqlScalarType::UInt32),
1845 UInt64(()) => Ok(SqlScalarType::UInt64),
1846 Float32(()) => Ok(SqlScalarType::Float32),
1847 Float64(()) => Ok(SqlScalarType::Float64),
1848 Date(()) => Ok(SqlScalarType::Date),
1849 Time(()) => Ok(SqlScalarType::Time),
1850 Timestamp(x) => Ok(SqlScalarType::Timestamp {
1851 precision: x.precision.into_rust()?,
1852 }),
1853 TimestampTz(x) => Ok(SqlScalarType::TimestampTz {
1854 precision: x.precision.into_rust()?,
1855 }),
1856 Interval(()) => Ok(SqlScalarType::Interval),
1857 PgLegacyChar(()) => Ok(SqlScalarType::PgLegacyChar),
1858 PgLegacyName(()) => Ok(SqlScalarType::PgLegacyName),
1859 Bytes(()) => Ok(SqlScalarType::Bytes),
1860 String(()) => Ok(SqlScalarType::String),
1861 Jsonb(()) => Ok(SqlScalarType::Jsonb),
1862 Uuid(()) => Ok(SqlScalarType::Uuid),
1863 Oid(()) => Ok(SqlScalarType::Oid),
1864 RegProc(()) => Ok(SqlScalarType::RegProc),
1865 RegType(()) => Ok(SqlScalarType::RegType),
1866 RegClass(()) => Ok(SqlScalarType::RegClass),
1867 Int2Vector(()) => Ok(SqlScalarType::Int2Vector),
1868
1869 Numeric(x) => Ok(SqlScalarType::Numeric {
1870 max_scale: x.into_rust()?,
1871 }),
1872 Char(x) => Ok(SqlScalarType::Char {
1873 length: x.length.into_rust()?,
1874 }),
1875
1876 VarChar(x) => Ok(SqlScalarType::VarChar {
1877 max_length: x.max_length.into_rust()?,
1878 }),
1879 Array(x) => Ok(SqlScalarType::Array({
1880 let st: SqlScalarType = (*x).into_rust()?;
1881 st.into()
1882 })),
1883 List(x) => Ok(SqlScalarType::List {
1884 element_type: Box::new(
1885 x.element_type
1886 .map(|x| *x)
1887 .into_rust_if_some("ProtoList::element_type")?,
1888 ),
1889 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1890 }),
1891 Record(x) => Ok(SqlScalarType::Record {
1892 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1893 fields: x.fields.into_rust()?,
1894 }),
1895 Map(x) => Ok(SqlScalarType::Map {
1896 value_type: Box::new(
1897 x.value_type
1898 .map(|x| *x)
1899 .into_rust_if_some("ProtoMap::value_type")?,
1900 ),
1901 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1902 }),
1903 MzTimestamp(()) => Ok(SqlScalarType::MzTimestamp),
1904 Range(x) => Ok(SqlScalarType::Range {
1905 element_type: Box::new(
1906 x.element_type
1907 .map(|x| *x)
1908 .into_rust_if_some("ProtoRange::element_type")?,
1909 ),
1910 }),
1911 MzAclItem(()) => Ok(SqlScalarType::MzAclItem),
1912 AclItem(()) => Ok(SqlScalarType::AclItem),
1913 }
1914 }
1915}
1916
1917pub trait AsColumnType {
1919 fn as_column_type() -> SqlColumnType;
1921}
1922
1923pub trait DatumType<'a, E>: Sized {
1925 fn nullable() -> bool;
1927
1928 fn fallible() -> bool;
1930
1931 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>>;
1934
1935 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E>;
1937}
1938
1939#[derive(Debug)]
1942pub struct ArrayRustType<T>(pub Vec<T>);
1943
1944impl<T> From<Vec<T>> for ArrayRustType<T> {
1945 fn from(v: Vec<T>) -> Self {
1946 Self(v)
1947 }
1948}
1949
1950impl<B: ToOwned<Owned: AsColumnType>> AsColumnType for Cow<'_, B> {
1951 fn as_column_type() -> SqlColumnType {
1952 <B::Owned>::as_column_type()
1953 }
1954}
1955
1956impl<'a, E, B: ToOwned> DatumType<'a, E> for Cow<'a, B>
1957where
1958 B::Owned: DatumType<'a, E>,
1959 for<'b> &'b B: DatumType<'a, E>,
1960{
1961 fn nullable() -> bool {
1962 B::Owned::nullable()
1963 }
1964 fn fallible() -> bool {
1965 B::Owned::fallible()
1966 }
1967 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1968 <&B>::try_from_result(res).map(|b| Cow::Borrowed(b))
1969 }
1970 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1971 match self {
1972 Cow::Owned(b) => b.into_result(temp_storage),
1973 Cow::Borrowed(b) => b.into_result(temp_storage),
1974 }
1975 }
1976}
1977
1978impl<B: AsColumnType> AsColumnType for Option<B> {
1979 fn as_column_type() -> SqlColumnType {
1980 B::as_column_type().nullable(true)
1981 }
1982}
1983
1984impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for Option<B> {
1985 fn nullable() -> bool {
1986 true
1987 }
1988 fn fallible() -> bool {
1989 false
1990 }
1991 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1992 match res {
1993 Ok(Datum::Null) => Ok(None),
1994 Ok(datum) => B::try_from_result(Ok(datum)).map(Some),
1995 _ => Err(res),
1996 }
1997 }
1998 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1999 match self {
2000 Some(inner) => inner.into_result(temp_storage),
2001 None => Ok(Datum::Null),
2002 }
2003 }
2004}
2005
2006impl<E, B: AsColumnType> AsColumnType for Result<B, E> {
2007 fn as_column_type() -> SqlColumnType {
2008 B::as_column_type()
2009 }
2010}
2011
2012impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for Result<B, E> {
2013 fn nullable() -> bool {
2014 B::nullable()
2015 }
2016 fn fallible() -> bool {
2017 true
2018 }
2019 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2020 B::try_from_result(res).map(Ok)
2021 }
2022 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2023 self.and_then(|inner| inner.into_result(temp_storage))
2024 }
2025}
2026
2027#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2034pub struct ExcludeNull<B>(B);
2035
2036impl<B: AsColumnType> AsColumnType for ExcludeNull<B> {
2037 fn as_column_type() -> SqlColumnType {
2038 B::as_column_type().nullable(false)
2039 }
2040}
2041
2042impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for ExcludeNull<B> {
2043 fn nullable() -> bool {
2044 false
2045 }
2046 fn fallible() -> bool {
2047 B::fallible()
2048 }
2049 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2050 match res {
2051 Ok(Datum::Null) => Err(Ok(Datum::Null)),
2052 _ => B::try_from_result(res).map(ExcludeNull),
2053 }
2054 }
2055 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2056 self.0.into_result(temp_storage)
2057 }
2058}
2059
2060impl<B> std::ops::Deref for ExcludeNull<B> {
2061 type Target = B;
2062
2063 fn deref(&self) -> &Self::Target {
2064 &self.0
2065 }
2066}
2067
2068macro_rules! impl_datum_type_copy {
2070 ($lt:lifetime, $native:ty, $variant:ident) => {
2071 impl<$lt> AsColumnType for $native {
2072 fn as_column_type() -> SqlColumnType {
2073 SqlScalarType::$variant.nullable(false)
2074 }
2075 }
2076
2077 impl<$lt, E> DatumType<$lt, E> for $native {
2078 fn nullable() -> bool {
2079 false
2080 }
2081
2082 fn fallible() -> bool {
2083 false
2084 }
2085
2086 fn try_from_result(res: Result<Datum<$lt>, E>) -> Result<Self, Result<Datum<$lt>, E>> {
2087 match res {
2088 Ok(Datum::$variant(f)) => Ok(f.into()),
2089 _ => Err(res),
2090 }
2091 }
2092
2093 fn into_result(self, _temp_storage: &$lt RowArena) -> Result<Datum<$lt>, E> {
2094 Ok(Datum::$variant(self.into()))
2095 }
2096 }
2097 };
2098 ($native:ty, $variant:ident) => {
2099 impl_datum_type_copy!('a, $native, $variant);
2100 };
2101}
2102
2103impl_datum_type_copy!(f32, Float32);
2104impl_datum_type_copy!(f64, Float64);
2105impl_datum_type_copy!(i16, Int16);
2106impl_datum_type_copy!(i32, Int32);
2107impl_datum_type_copy!(i64, Int64);
2108impl_datum_type_copy!(u16, UInt16);
2109impl_datum_type_copy!(u32, UInt32);
2110impl_datum_type_copy!(u64, UInt64);
2111impl_datum_type_copy!(Interval, Interval);
2112impl_datum_type_copy!(Date, Date);
2113impl_datum_type_copy!(NaiveTime, Time);
2114impl_datum_type_copy!(Uuid, Uuid);
2115impl_datum_type_copy!('a, &'a str, String);
2116impl_datum_type_copy!('a, &'a [u8], Bytes);
2117impl_datum_type_copy!(crate::Timestamp, MzTimestamp);
2118
2119impl<'a, E> DatumType<'a, E> for Datum<'a> {
2120 fn nullable() -> bool {
2121 true
2122 }
2123
2124 fn fallible() -> bool {
2125 false
2126 }
2127
2128 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2129 match res {
2130 Ok(datum) => Ok(datum),
2131 _ => Err(res),
2132 }
2133 }
2134
2135 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2136 Ok(self)
2137 }
2138}
2139
2140impl<'a, E> DatumType<'a, E> for DatumList<'a> {
2141 fn nullable() -> bool {
2142 false
2143 }
2144
2145 fn fallible() -> bool {
2146 false
2147 }
2148
2149 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2150 match res {
2151 Ok(Datum::List(list)) => Ok(list),
2152 _ => Err(res),
2153 }
2154 }
2155
2156 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2157 Ok(Datum::List(self))
2158 }
2159}
2160
2161impl<'a, E> DatumType<'a, E> for Array<'a> {
2162 fn nullable() -> bool {
2163 false
2164 }
2165
2166 fn fallible() -> bool {
2167 false
2168 }
2169
2170 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2171 match res {
2172 Ok(Datum::Array(array)) => Ok(array),
2173 _ => Err(res),
2174 }
2175 }
2176
2177 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2178 Ok(Datum::Array(self))
2179 }
2180}
2181
2182impl<'a, E> DatumType<'a, E> for DatumMap<'a> {
2183 fn nullable() -> bool {
2184 false
2185 }
2186
2187 fn fallible() -> bool {
2188 false
2189 }
2190
2191 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2192 match res {
2193 Ok(Datum::Map(map)) => Ok(map),
2194 _ => Err(res),
2195 }
2196 }
2197
2198 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2199 Ok(Datum::Map(self))
2200 }
2201}
2202
2203impl<'a, E> DatumType<'a, E> for Range<DatumNested<'a>> {
2204 fn nullable() -> bool {
2205 false
2206 }
2207
2208 fn fallible() -> bool {
2209 false
2210 }
2211
2212 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2213 match res {
2214 Ok(Datum::Range(range)) => Ok(range),
2215 _ => Err(res),
2216 }
2217 }
2218
2219 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2220 Ok(Datum::Range(self))
2221 }
2222}
2223
2224impl<'a, E> DatumType<'a, E> for Range<Datum<'a>> {
2225 fn nullable() -> bool {
2226 false
2227 }
2228
2229 fn fallible() -> bool {
2230 false
2231 }
2232
2233 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2234 match res {
2235 Ok(r @ Datum::Range(..)) => Ok(r.unwrap_range()),
2236 _ => Err(res),
2237 }
2238 }
2239
2240 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2241 let d =
2242 self.into_bounds(|bound| temp_storage.make_datum_nested(|packer| packer.push(bound)));
2243 Ok(Datum::Range(d))
2244 }
2245}
2246
2247impl AsColumnType for bool {
2248 fn as_column_type() -> SqlColumnType {
2249 SqlScalarType::Bool.nullable(false)
2250 }
2251}
2252
2253impl<'a, E> DatumType<'a, E> for bool {
2254 fn nullable() -> bool {
2255 false
2256 }
2257
2258 fn fallible() -> bool {
2259 false
2260 }
2261
2262 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2263 match res {
2264 Ok(Datum::True) => Ok(true),
2265 Ok(Datum::False) => Ok(false),
2266 _ => Err(res),
2267 }
2268 }
2269
2270 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2271 if self {
2272 Ok(Datum::True)
2273 } else {
2274 Ok(Datum::False)
2275 }
2276 }
2277}
2278
2279impl AsColumnType for String {
2280 fn as_column_type() -> SqlColumnType {
2281 SqlScalarType::String.nullable(false)
2282 }
2283}
2284
2285impl<'a, E> DatumType<'a, E> for String {
2286 fn nullable() -> bool {
2287 false
2288 }
2289
2290 fn fallible() -> bool {
2291 false
2292 }
2293
2294 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2295 match res {
2296 Ok(Datum::String(s)) => Ok(s.to_owned()),
2297 _ => Err(res),
2298 }
2299 }
2300
2301 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2302 Ok(Datum::String(temp_storage.push_string(self)))
2303 }
2304}
2305
2306impl AsColumnType for ArrayRustType<String> {
2307 fn as_column_type() -> SqlColumnType {
2308 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false)
2309 }
2310}
2311
2312impl<'a, E> DatumType<'a, E> for ArrayRustType<String> {
2313 fn nullable() -> bool {
2314 false
2315 }
2316
2317 fn fallible() -> bool {
2318 false
2319 }
2320
2321 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2322 match res {
2323 Ok(Datum::Array(arr)) => Ok(ArrayRustType(
2324 arr.elements()
2325 .into_iter()
2326 .map(|d| d.unwrap_str().to_string())
2327 .collect(),
2328 )),
2329 _ => Err(res),
2330 }
2331 }
2332
2333 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2334 Ok(temp_storage.make_datum(|packer| {
2335 packer
2336 .try_push_array(
2337 &[ArrayDimension {
2338 lower_bound: 1,
2339 length: self.0.len(),
2340 }],
2341 self.0.iter().map(|elem| Datum::String(elem.as_str())),
2342 )
2343 .expect("self is 1 dimensional, and its length is used for the array length");
2344 }))
2345 }
2346}
2347
2348impl AsColumnType for ArrayRustType<Cow<'_, str>> {
2349 fn as_column_type() -> SqlColumnType {
2350 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false)
2351 }
2352}
2353
2354impl<'a, E> DatumType<'a, E> for ArrayRustType<Cow<'a, str>> {
2355 fn nullable() -> bool {
2356 false
2357 }
2358
2359 fn fallible() -> bool {
2360 false
2361 }
2362
2363 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2364 match res {
2365 Ok(Datum::Array(arr)) => Ok(ArrayRustType(
2366 arr.elements()
2367 .into_iter()
2368 .map(|d| Cow::Borrowed(d.unwrap_str()))
2369 .collect(),
2370 )),
2371 _ => Err(res),
2372 }
2373 }
2374
2375 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2376 Ok(temp_storage.make_datum(|packer| {
2377 packer
2378 .try_push_array(
2379 &[ArrayDimension {
2380 lower_bound: 1,
2381 length: self.0.len(),
2382 }],
2383 self.0.iter().map(|elem| Datum::String(elem.as_ref())),
2384 )
2385 .expect("self is 1 dimensional, and its length is used for the array length");
2386 }))
2387 }
2388}
2389
2390impl AsColumnType for Vec<u8> {
2391 fn as_column_type() -> SqlColumnType {
2392 SqlScalarType::Bytes.nullable(false)
2393 }
2394}
2395
2396impl<'a, E> DatumType<'a, E> for Vec<u8> {
2397 fn nullable() -> bool {
2398 false
2399 }
2400
2401 fn fallible() -> bool {
2402 false
2403 }
2404
2405 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2406 match res {
2407 Ok(Datum::Bytes(b)) => Ok(b.to_owned()),
2408 _ => Err(res),
2409 }
2410 }
2411
2412 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2413 Ok(Datum::Bytes(temp_storage.push_bytes(self)))
2414 }
2415}
2416
2417impl AsColumnType for Numeric {
2418 fn as_column_type() -> SqlColumnType {
2419 SqlScalarType::Numeric { max_scale: None }.nullable(false)
2420 }
2421}
2422
2423impl<'a, E> DatumType<'a, E> for Numeric {
2424 fn nullable() -> bool {
2425 false
2426 }
2427
2428 fn fallible() -> bool {
2429 false
2430 }
2431
2432 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2433 match res {
2434 Ok(Datum::Numeric(n)) => Ok(n.into_inner()),
2435 _ => Err(res),
2436 }
2437 }
2438
2439 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2440 Ok(Datum::from(self))
2441 }
2442}
2443
2444impl<'a, E> DatumType<'a, E> for OrderedDecimal<Numeric> {
2445 fn nullable() -> bool {
2446 false
2447 }
2448
2449 fn fallible() -> bool {
2450 false
2451 }
2452
2453 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2454 match res {
2455 Ok(Datum::Numeric(n)) => Ok(n),
2456 _ => Err(res),
2457 }
2458 }
2459
2460 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2461 Ok(Datum::from(self))
2462 }
2463}
2464
2465impl AsColumnType for PgLegacyChar {
2466 fn as_column_type() -> SqlColumnType {
2467 SqlScalarType::PgLegacyChar.nullable(false)
2468 }
2469}
2470
2471impl<'a, E> DatumType<'a, E> for PgLegacyChar {
2472 fn nullable() -> bool {
2473 false
2474 }
2475
2476 fn fallible() -> bool {
2477 false
2478 }
2479
2480 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2481 match res {
2482 Ok(Datum::UInt8(a)) => Ok(PgLegacyChar(a)),
2483 _ => Err(res),
2484 }
2485 }
2486
2487 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2488 Ok(Datum::UInt8(self.0))
2489 }
2490}
2491
2492impl<S> AsColumnType for PgLegacyName<S>
2493where
2494 S: AsRef<str>,
2495{
2496 fn as_column_type() -> SqlColumnType {
2497 SqlScalarType::PgLegacyName.nullable(false)
2498 }
2499}
2500
2501impl<'a, E> DatumType<'a, E> for PgLegacyName<&'a str> {
2502 fn nullable() -> bool {
2503 false
2504 }
2505
2506 fn fallible() -> bool {
2507 false
2508 }
2509
2510 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2511 match res {
2512 Ok(Datum::String(a)) => Ok(PgLegacyName(a)),
2513 _ => Err(res),
2514 }
2515 }
2516
2517 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2518 Ok(Datum::String(self.0))
2519 }
2520}
2521
2522impl<'a, E> DatumType<'a, E> for PgLegacyName<String> {
2523 fn nullable() -> bool {
2524 false
2525 }
2526
2527 fn fallible() -> bool {
2528 false
2529 }
2530
2531 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2532 match res {
2533 Ok(Datum::String(a)) => Ok(PgLegacyName(a.to_owned())),
2534 _ => Err(res),
2535 }
2536 }
2537
2538 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2539 Ok(Datum::String(temp_storage.push_string(self.0)))
2540 }
2541}
2542
2543impl AsColumnType for Oid {
2544 fn as_column_type() -> SqlColumnType {
2545 SqlScalarType::Oid.nullable(false)
2546 }
2547}
2548
2549impl<'a, E> DatumType<'a, E> for Oid {
2550 fn nullable() -> bool {
2551 false
2552 }
2553
2554 fn fallible() -> bool {
2555 false
2556 }
2557
2558 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2559 match res {
2560 Ok(Datum::UInt32(a)) => Ok(Oid(a)),
2561 _ => Err(res),
2562 }
2563 }
2564
2565 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2566 Ok(Datum::UInt32(self.0))
2567 }
2568}
2569
2570impl AsColumnType for RegClass {
2571 fn as_column_type() -> SqlColumnType {
2572 SqlScalarType::RegClass.nullable(false)
2573 }
2574}
2575
2576impl<'a, E> DatumType<'a, E> for RegClass {
2577 fn nullable() -> bool {
2578 false
2579 }
2580
2581 fn fallible() -> bool {
2582 false
2583 }
2584
2585 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2586 match res {
2587 Ok(Datum::UInt32(a)) => Ok(RegClass(a)),
2588 _ => Err(res),
2589 }
2590 }
2591
2592 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2593 Ok(Datum::UInt32(self.0))
2594 }
2595}
2596
2597impl AsColumnType for RegProc {
2598 fn as_column_type() -> SqlColumnType {
2599 SqlScalarType::RegProc.nullable(false)
2600 }
2601}
2602
2603impl<'a, E> DatumType<'a, E> for RegProc {
2604 fn nullable() -> bool {
2605 false
2606 }
2607
2608 fn fallible() -> bool {
2609 false
2610 }
2611
2612 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2613 match res {
2614 Ok(Datum::UInt32(a)) => Ok(RegProc(a)),
2615 _ => Err(res),
2616 }
2617 }
2618
2619 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2620 Ok(Datum::UInt32(self.0))
2621 }
2622}
2623
2624impl AsColumnType for RegType {
2625 fn as_column_type() -> SqlColumnType {
2626 SqlScalarType::RegType.nullable(false)
2627 }
2628}
2629
2630impl<'a, E> DatumType<'a, E> for RegType {
2631 fn nullable() -> bool {
2632 false
2633 }
2634
2635 fn fallible() -> bool {
2636 false
2637 }
2638
2639 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2640 match res {
2641 Ok(Datum::UInt32(a)) => Ok(RegType(a)),
2642 _ => Err(res),
2643 }
2644 }
2645
2646 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2647 Ok(Datum::UInt32(self.0))
2648 }
2649}
2650
2651impl<S> AsColumnType for Char<S>
2652where
2653 S: AsRef<str>,
2654{
2655 fn as_column_type() -> SqlColumnType {
2656 SqlScalarType::Char { length: None }.nullable(false)
2657 }
2658}
2659
2660impl<'a, E> DatumType<'a, E> for Char<&'a str> {
2661 fn nullable() -> bool {
2662 false
2663 }
2664
2665 fn fallible() -> bool {
2666 false
2667 }
2668
2669 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2670 match res {
2671 Ok(Datum::String(a)) => Ok(Char(a)),
2672 _ => Err(res),
2673 }
2674 }
2675
2676 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2677 Ok(Datum::String(self.0))
2678 }
2679}
2680
2681impl<'a, E> DatumType<'a, E> for Char<String> {
2682 fn nullable() -> bool {
2683 false
2684 }
2685
2686 fn fallible() -> bool {
2687 false
2688 }
2689
2690 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2691 match res {
2692 Ok(Datum::String(a)) => Ok(Char(a.to_owned())),
2693 _ => Err(res),
2694 }
2695 }
2696
2697 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2698 Ok(Datum::String(temp_storage.push_string(self.0)))
2699 }
2700}
2701
2702impl<S> AsColumnType for VarChar<S>
2703where
2704 S: AsRef<str>,
2705{
2706 fn as_column_type() -> SqlColumnType {
2707 SqlScalarType::Char { length: None }.nullable(false)
2708 }
2709}
2710
2711impl<'a, E> DatumType<'a, E> for VarChar<&'a str> {
2712 fn nullable() -> bool {
2713 false
2714 }
2715
2716 fn fallible() -> bool {
2717 false
2718 }
2719
2720 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2721 match res {
2722 Ok(Datum::String(a)) => Ok(VarChar(a)),
2723 _ => Err(res),
2724 }
2725 }
2726
2727 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2728 Ok(Datum::String(self.0))
2729 }
2730}
2731
2732impl<'a, E> DatumType<'a, E> for VarChar<String> {
2733 fn nullable() -> bool {
2734 false
2735 }
2736
2737 fn fallible() -> bool {
2738 false
2739 }
2740
2741 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2742 match res {
2743 Ok(Datum::String(a)) => Ok(VarChar(a.to_owned())),
2744 _ => Err(res),
2745 }
2746 }
2747
2748 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2749 Ok(Datum::String(temp_storage.push_string(self.0)))
2750 }
2751}
2752
2753impl<'a, E> DatumType<'a, E> for Jsonb {
2754 fn nullable() -> bool {
2755 false
2756 }
2757
2758 fn fallible() -> bool {
2759 false
2760 }
2761
2762 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2763 Ok(JsonbRef::try_from_result(res)?.to_owned())
2764 }
2765
2766 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2767 Ok(temp_storage.push_unary_row(self.into_row()))
2768 }
2769}
2770
2771impl AsColumnType for Jsonb {
2772 fn as_column_type() -> SqlColumnType {
2773 SqlScalarType::Jsonb.nullable(false)
2774 }
2775}
2776
2777impl<'a, E> DatumType<'a, E> for JsonbRef<'a> {
2778 fn nullable() -> bool {
2779 false
2780 }
2781
2782 fn fallible() -> bool {
2783 false
2784 }
2785
2786 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2787 match res {
2788 Ok(
2789 d @ (Datum::JsonNull
2790 | Datum::True
2791 | Datum::False
2792 | Datum::Numeric(_)
2793 | Datum::String(_)
2794 | Datum::List(_)
2795 | Datum::Map(_)),
2796 ) => Ok(JsonbRef::from_datum(d)),
2797 _ => Err(res),
2798 }
2799 }
2800
2801 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2802 Ok(self.into_datum())
2803 }
2804}
2805
2806impl<'a> AsColumnType for JsonbRef<'a> {
2807 fn as_column_type() -> SqlColumnType {
2808 SqlScalarType::Jsonb.nullable(false)
2809 }
2810}
2811
2812impl AsColumnType for MzAclItem {
2813 fn as_column_type() -> SqlColumnType {
2814 SqlScalarType::MzAclItem.nullable(false)
2815 }
2816}
2817
2818impl<'a, E> DatumType<'a, E> for MzAclItem {
2819 fn nullable() -> bool {
2820 false
2821 }
2822
2823 fn fallible() -> bool {
2824 false
2825 }
2826
2827 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2828 match res {
2829 Ok(Datum::MzAclItem(mz_acl_item)) => Ok(mz_acl_item),
2830 _ => Err(res),
2831 }
2832 }
2833
2834 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2835 Ok(Datum::MzAclItem(self))
2836 }
2837}
2838
2839impl AsColumnType for AclItem {
2840 fn as_column_type() -> SqlColumnType {
2841 SqlScalarType::AclItem.nullable(false)
2842 }
2843}
2844
2845impl<'a, E> DatumType<'a, E> for AclItem {
2846 fn nullable() -> bool {
2847 false
2848 }
2849
2850 fn fallible() -> bool {
2851 false
2852 }
2853
2854 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2855 match res {
2856 Ok(Datum::AclItem(acl_item)) => Ok(acl_item),
2857 _ => Err(res),
2858 }
2859 }
2860
2861 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2862 Ok(Datum::AclItem(self))
2863 }
2864}
2865
2866impl AsColumnType for CheckedTimestamp<NaiveDateTime> {
2867 fn as_column_type() -> SqlColumnType {
2868 SqlScalarType::Timestamp { precision: None }.nullable(false)
2869 }
2870}
2871
2872impl<'a, E> DatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
2873 fn nullable() -> bool {
2874 false
2875 }
2876
2877 fn fallible() -> bool {
2878 false
2879 }
2880
2881 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2882 match res {
2883 Ok(Datum::Timestamp(a)) => Ok(a),
2884 _ => Err(res),
2885 }
2886 }
2887
2888 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2889 Ok(Datum::Timestamp(self))
2890 }
2891}
2892
2893impl AsColumnType for CheckedTimestamp<DateTime<Utc>> {
2894 fn as_column_type() -> SqlColumnType {
2895 SqlScalarType::TimestampTz { precision: None }.nullable(false)
2896 }
2897}
2898
2899impl<'a, E> DatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
2900 fn nullable() -> bool {
2901 false
2902 }
2903
2904 fn fallible() -> bool {
2905 false
2906 }
2907
2908 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2909 match res {
2910 Ok(Datum::TimestampTz(a)) => Ok(a),
2911 _ => Err(res),
2912 }
2913 }
2914
2915 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2916 Ok(Datum::TimestampTz(self))
2917 }
2918}
2919
2920impl SqlScalarType {
2921 pub fn unwrap_numeric_max_scale(&self) -> Option<NumericMaxScale> {
2927 match self {
2928 SqlScalarType::Numeric { max_scale } => *max_scale,
2929 _ => panic!("SqlScalarType::unwrap_numeric_scale called on {:?}", self),
2930 }
2931 }
2932
2933 pub fn unwrap_timestamp_precision(&self) -> Option<TimestampPrecision> {
2940 match self {
2941 SqlScalarType::Timestamp { precision } | SqlScalarType::TimestampTz { precision } => {
2942 *precision
2943 }
2944 _ => panic!(
2945 "SqlScalarType::unwrap_timestamp_precision called on {:?}",
2946 self
2947 ),
2948 }
2949 }
2950
2951 pub fn unwrap_list_element_type(&self) -> &SqlScalarType {
2957 match self {
2958 SqlScalarType::List { element_type, .. } => element_type,
2959 _ => panic!(
2960 "SqlScalarType::unwrap_list_element_type called on {:?}",
2961 self
2962 ),
2963 }
2964 }
2965
2966 pub fn unwrap_list_nth_layer_type(&self, layer: usize) -> &SqlScalarType {
2979 if layer == 0 {
2980 return self;
2981 }
2982 match self {
2983 SqlScalarType::List { element_type, .. } => {
2984 element_type.unwrap_list_nth_layer_type(layer - 1)
2985 }
2986 _ => panic!(
2987 "SqlScalarType::unwrap_list_nth_layer_type called on {:?}",
2988 self
2989 ),
2990 }
2991 }
2992
2993 pub fn unwrap_record_element_type(&self) -> Vec<&SqlScalarType> {
2999 match self {
3000 SqlScalarType::Record { fields, .. } => {
3001 fields.iter().map(|(_, t)| &t.scalar_type).collect_vec()
3002 }
3003 _ => panic!(
3004 "SqlScalarType::unwrap_record_element_type called on {:?}",
3005 self
3006 ),
3007 }
3008 }
3009
3010 pub fn unwrap_record_element_column_type(&self) -> Vec<&SqlColumnType> {
3016 match self {
3017 SqlScalarType::Record { fields, .. } => fields.iter().map(|(_, t)| t).collect_vec(),
3018 _ => panic!(
3019 "SqlScalarType::unwrap_record_element_column_type called on {:?}",
3020 self
3021 ),
3022 }
3023 }
3024
3025 pub fn unwrap_list_n_layers(&self) -> usize {
3032 let mut descender = self.unwrap_list_element_type();
3033 let mut layers = 1;
3034
3035 while let SqlScalarType::List { element_type, .. } = descender {
3036 layers += 1;
3037 descender = element_type;
3038 }
3039
3040 layers
3041 }
3042
3043 pub fn without_modifiers(&self) -> SqlScalarType {
3047 use SqlScalarType::*;
3048 match self {
3049 List {
3050 element_type,
3051 custom_id: None,
3052 } => List {
3053 element_type: Box::new(element_type.without_modifiers()),
3054 custom_id: None,
3055 },
3056 Map {
3057 value_type,
3058 custom_id: None,
3059 } => Map {
3060 value_type: Box::new(value_type.without_modifiers()),
3061 custom_id: None,
3062 },
3063 Record {
3064 fields,
3065 custom_id: None,
3066 } => {
3067 let fields = fields
3068 .iter()
3069 .map(|(column_name, column_type)| {
3070 (
3071 column_name.clone(),
3072 SqlColumnType {
3073 scalar_type: column_type.scalar_type.without_modifiers(),
3074 nullable: column_type.nullable,
3075 },
3076 )
3077 })
3078 .collect();
3079 Record {
3080 fields,
3081 custom_id: None,
3082 }
3083 }
3084 Array(a) => Array(Box::new(a.without_modifiers())),
3085 Numeric { .. } => Numeric { max_scale: None },
3086 Char { .. } => Char { length: None },
3089 VarChar { .. } => VarChar { max_length: None },
3090 Range { element_type } => Range {
3091 element_type: Box::new(element_type.without_modifiers()),
3092 },
3093 v => v.clone(),
3094 }
3095 }
3096
3097 pub fn unwrap_array_element_type(&self) -> &SqlScalarType {
3106 match self {
3107 SqlScalarType::Array(s) => &**s,
3108 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3109 _ => panic!(
3110 "SqlScalarType::unwrap_array_element_type called on {:?}",
3111 self
3112 ),
3113 }
3114 }
3115
3116 pub fn unwrap_collection_element_type(&self) -> &SqlScalarType {
3124 match self {
3125 SqlScalarType::Array(element_type) => element_type,
3126 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3127 SqlScalarType::List { element_type, .. } => element_type,
3128 _ => panic!(
3129 "SqlScalarType::unwrap_collection_element_type called on {:?}",
3130 self
3131 ),
3132 }
3133 }
3134
3135 pub fn unwrap_map_value_type(&self) -> &SqlScalarType {
3141 match self {
3142 SqlScalarType::Map { value_type, .. } => &**value_type,
3143 _ => panic!("SqlScalarType::unwrap_map_value_type called on {:?}", self),
3144 }
3145 }
3146
3147 pub fn unwrap_char_length(&self) -> Option<CharLength> {
3153 match self {
3154 SqlScalarType::Char { length, .. } => *length,
3155 _ => panic!("SqlScalarType::unwrap_char_length called on {:?}", self),
3156 }
3157 }
3158
3159 pub fn unwrap_varchar_max_length(&self) -> Option<VarCharMaxLength> {
3165 match self {
3166 SqlScalarType::VarChar { max_length, .. } => *max_length,
3167 _ => panic!(
3168 "SqlScalarType::unwrap_varchar_max_length called on {:?}",
3169 self
3170 ),
3171 }
3172 }
3173
3174 pub fn unwrap_range_element_type(&self) -> &SqlScalarType {
3180 match self {
3181 SqlScalarType::Range { element_type } => &**element_type,
3182 _ => panic!(
3183 "SqlScalarType::unwrap_range_element_type called on {:?}",
3184 self
3185 ),
3186 }
3187 }
3188
3189 pub fn near_match(&self) -> Option<&'static SqlScalarType> {
3213 match self {
3214 SqlScalarType::UInt16 => Some(&SqlScalarType::Int32),
3215 SqlScalarType::UInt32 => Some(&SqlScalarType::Int64),
3216 SqlScalarType::UInt64 => Some(&SqlScalarType::Numeric { max_scale: None }),
3217 _ => None,
3218 }
3219 }
3220
3221 pub const fn nullable(self, nullable: bool) -> SqlColumnType {
3224 SqlColumnType {
3225 nullable,
3226 scalar_type: self,
3227 }
3228 }
3229
3230 pub fn is_vec(&self) -> bool {
3234 matches!(
3235 self,
3236 SqlScalarType::Array(_) | SqlScalarType::Int2Vector | SqlScalarType::List { .. }
3237 )
3238 }
3239
3240 pub fn is_custom_type(&self) -> bool {
3241 use SqlScalarType::*;
3242 match self {
3243 List {
3244 element_type: t,
3245 custom_id,
3246 }
3247 | Map {
3248 value_type: t,
3249 custom_id,
3250 } => custom_id.is_some() || t.is_custom_type(),
3251 Record {
3252 fields, custom_id, ..
3253 } => {
3254 custom_id.is_some()
3255 || fields
3256 .iter()
3257 .map(|(_, t)| t)
3258 .any(|t| t.scalar_type.is_custom_type())
3259 }
3260 _ => false,
3261 }
3262 }
3263
3264 pub fn base_eq(&self, other: &SqlScalarType) -> bool {
3277 self.eq_inner(other, false)
3278 }
3279
3280 pub fn structural_eq(&self, other: &SqlScalarType) -> bool {
3283 self.eq_inner(other, true)
3284 }
3285
3286 pub fn eq_inner(&self, other: &SqlScalarType, structure_only: bool) -> bool {
3287 use SqlScalarType::*;
3288 match (self, other) {
3289 (
3290 List {
3291 element_type: l,
3292 custom_id: oid_l,
3293 },
3294 List {
3295 element_type: r,
3296 custom_id: oid_r,
3297 },
3298 )
3299 | (
3300 Map {
3301 value_type: l,
3302 custom_id: oid_l,
3303 },
3304 Map {
3305 value_type: r,
3306 custom_id: oid_r,
3307 },
3308 ) => l.eq_inner(r, structure_only) && (oid_l == oid_r || structure_only),
3309 (Array(a), Array(b)) | (Range { element_type: a }, Range { element_type: b }) => {
3310 a.eq_inner(b, structure_only)
3311 }
3312 (
3313 Record {
3314 fields: fields_a,
3315 custom_id: oid_a,
3316 },
3317 Record {
3318 fields: fields_b,
3319 custom_id: oid_b,
3320 },
3321 ) => {
3322 (oid_a == oid_b || structure_only)
3323 && fields_a.len() == fields_b.len()
3324 && fields_a
3325 .iter()
3326 .zip_eq(fields_b)
3327 .all(|(a, b)| {
3329 (a.0 == b.0 || structure_only)
3330 && a.1.scalar_type.eq_inner(&b.1.scalar_type, structure_only)
3331 })
3332 }
3333 (s, o) => SqlScalarBaseType::from(s) == SqlScalarBaseType::from(o),
3334 }
3335 }
3336
3337 pub fn interesting_datums(&self) -> impl Iterator<Item = Datum<'static>> {
3339 static BOOL: LazyLock<Row> =
3345 LazyLock::new(|| Row::pack_slice(&[Datum::True, Datum::False]));
3346 static INT16: LazyLock<Row> = LazyLock::new(|| {
3347 Row::pack_slice(&[
3348 Datum::Int16(0),
3349 Datum::Int16(1),
3350 Datum::Int16(-1),
3351 Datum::Int16(i16::MIN),
3352 Datum::Int16(i16::MIN + 1),
3353 Datum::Int16(i16::MAX),
3354 Datum::Int16(127),
3362 Datum::Int16(128),
3363 ])
3364 });
3365 static INT32: LazyLock<Row> = LazyLock::new(|| {
3366 Row::pack_slice(&[
3367 Datum::Int32(0),
3368 Datum::Int32(1),
3369 Datum::Int32(-1),
3370 Datum::Int32(i32::MIN),
3371 Datum::Int32(i32::MIN + 1),
3372 Datum::Int32(i32::MAX),
3373 Datum::Int32(32767),
3377 Datum::Int32(32768),
3378 ])
3379 });
3380 static INT64: LazyLock<Row> = LazyLock::new(|| {
3381 Row::pack_slice(&[
3382 Datum::Int64(0),
3383 Datum::Int64(1),
3384 Datum::Int64(-1),
3385 Datum::Int64(i64::MIN),
3386 Datum::Int64(i64::MIN + 1),
3387 Datum::Int64(i64::MAX),
3388 Datum::Int64(2147483647),
3392 Datum::Int64(2147483648),
3393 ])
3394 });
3395 static UINT16: LazyLock<Row> = LazyLock::new(|| {
3396 Row::pack_slice(&[
3397 Datum::UInt16(0),
3398 Datum::UInt16(1),
3399 Datum::UInt16(u16::MAX),
3400 Datum::UInt16(255),
3404 Datum::UInt16(256),
3405 ])
3406 });
3407 static UINT32: LazyLock<Row> = LazyLock::new(|| {
3408 Row::pack_slice(&[
3409 Datum::UInt32(0),
3410 Datum::UInt32(1),
3411 Datum::UInt32(u32::MAX),
3412 Datum::UInt32(32767),
3416 Datum::UInt32(32768),
3417 ])
3418 });
3419 static UINT64: LazyLock<Row> = LazyLock::new(|| {
3420 Row::pack_slice(&[
3421 Datum::UInt64(0),
3422 Datum::UInt64(1),
3423 Datum::UInt64(u64::MAX),
3424 Datum::UInt64(2147483647),
3428 Datum::UInt64(2147483648),
3429 ])
3430 });
3431 static FLOAT32: LazyLock<Row> = LazyLock::new(|| {
3432 Row::pack_slice(&[
3433 Datum::Float32(OrderedFloat(0.0)),
3434 Datum::Float32(OrderedFloat(1.0)),
3435 Datum::Float32(OrderedFloat(-1.0)),
3436 Datum::Float32(OrderedFloat(f32::MIN)),
3437 Datum::Float32(OrderedFloat(f32::MIN_POSITIVE)),
3438 Datum::Float32(OrderedFloat(f32::MAX)),
3439 Datum::Float32(OrderedFloat(f32::EPSILON)),
3440 Datum::Float32(OrderedFloat(f32::NAN)),
3441 Datum::Float32(OrderedFloat(f32::INFINITY)),
3442 Datum::Float32(OrderedFloat(f32::NEG_INFINITY)),
3443 ])
3444 });
3445 static FLOAT64: LazyLock<Row> = LazyLock::new(|| {
3446 Row::pack_slice(&[
3447 Datum::Float64(OrderedFloat(0.0)),
3448 Datum::Float64(OrderedFloat(1.0)),
3449 Datum::Float64(OrderedFloat(-1.0)),
3450 Datum::Float64(OrderedFloat(f64::MIN)),
3451 Datum::Float64(OrderedFloat(f64::MIN_POSITIVE)),
3452 Datum::Float64(OrderedFloat(f64::MAX)),
3453 Datum::Float64(OrderedFloat(f64::EPSILON)),
3454 Datum::Float64(OrderedFloat(f64::NAN)),
3455 Datum::Float64(OrderedFloat(f64::INFINITY)),
3456 Datum::Float64(OrderedFloat(f64::NEG_INFINITY)),
3457 ])
3458 });
3459 static NUMERIC: LazyLock<Row> = LazyLock::new(|| {
3460 cfg_if::cfg_if! {
3461 if #[cfg(miri)] {
3463 Row::pack_slice(&[])
3464 } else {
3465 Row::pack_slice(&[
3466 Datum::Numeric(OrderedDecimal(Numeric::from(0.0))),
3467 Datum::Numeric(OrderedDecimal(Numeric::from(1.0))),
3468 Datum::Numeric(OrderedDecimal(Numeric::from(-1.0))),
3469 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN))),
3470 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN_POSITIVE))),
3471 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MAX))),
3472 Datum::Numeric(OrderedDecimal(Numeric::from(f64::EPSILON))),
3473 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NAN))),
3474 Datum::Numeric(OrderedDecimal(Numeric::from(f64::INFINITY))),
3475 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NEG_INFINITY))),
3476 ])
3477 }
3478 }
3479 });
3480 static DATE: LazyLock<Row> = LazyLock::new(|| {
3481 Row::pack_slice(&[
3482 Datum::Date(Date::from_pg_epoch(0).unwrap()),
3483 Datum::Date(Date::from_pg_epoch(Date::LOW_DAYS).unwrap()),
3484 Datum::Date(Date::from_pg_epoch(Date::HIGH_DAYS).unwrap()),
3485 ])
3486 });
3487 static TIME: LazyLock<Row> = LazyLock::new(|| {
3488 Row::pack_slice(&[
3489 Datum::Time(NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap()),
3490 Datum::Time(NaiveTime::from_hms_micro_opt(23, 59, 59, 999_999).unwrap()),
3491 ])
3492 });
3493 static TIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3494 Row::pack_slice(&[
3495 Datum::Timestamp(
3496 DateTime::from_timestamp(0, 0)
3497 .unwrap()
3498 .naive_utc()
3499 .try_into()
3500 .unwrap(),
3501 ),
3502 Datum::Timestamp(
3503 crate::adt::timestamp::LOW_DATE
3504 .and_hms_opt(0, 0, 0)
3505 .unwrap()
3506 .try_into()
3507 .unwrap(),
3508 ),
3509 Datum::Timestamp(
3510 crate::adt::timestamp::HIGH_DATE
3511 .and_hms_opt(23, 59, 59)
3512 .unwrap()
3513 .try_into()
3514 .unwrap(),
3515 ),
3516 Datum::Timestamp(
3518 DateTime::from_timestamp(0, 123456789)
3519 .unwrap()
3520 .naive_utc()
3521 .try_into()
3522 .unwrap(),
3523 ),
3524 Datum::Timestamp(
3526 CheckedTimestamp::from_timestamplike(
3527 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
3528 .unwrap()
3529 .and_hms_milli_opt(23, 59, 59, 1234)
3530 .unwrap(),
3531 )
3532 .unwrap(),
3533 ),
3534 ])
3535 });
3536 static TIMESTAMPTZ: LazyLock<Row> = LazyLock::new(|| {
3537 Row::pack_slice(&[
3538 Datum::TimestampTz(DateTime::from_timestamp(0, 0).unwrap().try_into().unwrap()),
3539 Datum::TimestampTz(
3540 DateTime::from_naive_utc_and_offset(
3541 crate::adt::timestamp::LOW_DATE
3542 .and_hms_opt(0, 0, 0)
3543 .unwrap(),
3544 Utc,
3545 )
3546 .try_into()
3547 .unwrap(),
3548 ),
3549 Datum::TimestampTz(
3550 DateTime::from_naive_utc_and_offset(
3551 crate::adt::timestamp::HIGH_DATE
3552 .and_hms_opt(23, 59, 59)
3553 .unwrap(),
3554 Utc,
3555 )
3556 .try_into()
3557 .unwrap(),
3558 ),
3559 Datum::TimestampTz(
3561 DateTime::from_timestamp(0, 123456789)
3562 .unwrap()
3563 .try_into()
3564 .unwrap(),
3565 ),
3566 ])
3567 });
3568 static INTERVAL: LazyLock<Row> = LazyLock::new(|| {
3569 Row::pack_slice(&[
3570 Datum::Interval(Interval::new(0, 0, 0)),
3571 Datum::Interval(Interval::new(1, 1, 1)),
3572 Datum::Interval(Interval::new(-1, -1, -1)),
3573 Datum::Interval(Interval::new(1, 0, 0)),
3574 Datum::Interval(Interval::new(0, 1, 0)),
3575 Datum::Interval(Interval::new(0, 0, 1)),
3576 Datum::Interval(Interval::new(-1, 0, 0)),
3577 Datum::Interval(Interval::new(0, -1, 0)),
3578 Datum::Interval(Interval::new(0, 0, -1)),
3579 Datum::Interval(Interval::new(i32::MIN, i32::MIN, i64::MIN)),
3580 Datum::Interval(Interval::new(i32::MAX, i32::MAX, i64::MAX)),
3581 Datum::Interval(Interval::new(i32::MIN, 0, 0)),
3582 Datum::Interval(Interval::new(i32::MAX, 0, 0)),
3583 Datum::Interval(Interval::new(0, i32::MIN, 0)),
3584 Datum::Interval(Interval::new(0, i32::MAX, 0)),
3585 Datum::Interval(Interval::new(0, 0, i64::MIN)),
3586 Datum::Interval(Interval::new(0, 0, i64::MAX)),
3587 ])
3588 });
3589 static PGLEGACYCHAR: LazyLock<Row> =
3590 LazyLock::new(|| Row::pack_slice(&[Datum::UInt8(u8::MIN), Datum::UInt8(u8::MAX)]));
3591 static PGLEGACYNAME: LazyLock<Row> = LazyLock::new(|| {
3592 Row::pack_slice(&[
3593 Datum::String(""),
3594 Datum::String(" "),
3595 Datum::String("'"),
3596 Datum::String("\""),
3597 Datum::String("."),
3598 Datum::String(&"x".repeat(64)),
3599 ])
3600 });
3601 static BYTES: LazyLock<Row> = LazyLock::new(|| {
3602 Row::pack_slice(&[Datum::Bytes(&[]), Datum::Bytes(&[0]), Datum::Bytes(&[255])])
3603 });
3604 static STRING: LazyLock<Row> = LazyLock::new(|| {
3605 Row::pack_slice(&[
3606 Datum::String(""),
3607 Datum::String(" "),
3608 Datum::String("'"),
3609 Datum::String("\""),
3610 Datum::String("."),
3611 Datum::String("2015-09-18T23:56:04.123Z"),
3612 Datum::String(&"x".repeat(100)),
3613 Datum::String("JAPAN"),
3615 Datum::String("1,2,3"),
3616 Datum::String("\r\n"),
3617 Datum::String("\"\""),
3618 ])
3619 });
3620 static CHAR: LazyLock<Row> = LazyLock::new(|| {
3621 Row::pack_slice(&[
3622 Datum::String(" "),
3623 Datum::String("'"),
3624 Datum::String("\""),
3625 Datum::String("."),
3626 Datum::String(","),
3627 Datum::String("\t"),
3628 Datum::String("\n"),
3629 Datum::String("\r"),
3630 Datum::String("\\"),
3631 Datum::String(std::str::from_utf8(b"\x00").unwrap()),
3633 Datum::String(std::str::from_utf8(b"\x02").unwrap()),
3635 Datum::String(std::str::from_utf8(b"\x03").unwrap()),
3637 Datum::String(std::str::from_utf8(b"\x08").unwrap()),
3639 Datum::String(std::str::from_utf8(b"\x1B").unwrap()),
3641 Datum::String(std::str::from_utf8(b"\x7F").unwrap()),
3643 ])
3644 });
3645 static JSONB: LazyLock<Row> = LazyLock::new(|| {
3646 let mut datums = vec![Datum::True, Datum::False, Datum::JsonNull];
3647 datums.extend(STRING.iter());
3648 datums.extend(NUMERIC.iter().filter(|n| {
3649 let Datum::Numeric(n) = n else {
3650 panic!("expected Numeric, found {n:?}");
3651 };
3652 !(n.0.is_nan() || n.0.is_infinite())
3654 }));
3655 Row::pack_slice(&datums)
3657 });
3658 static UUID: LazyLock<Row> = LazyLock::new(|| {
3659 Row::pack_slice(&[
3660 Datum::Uuid(Uuid::from_u128(u128::MIN)),
3661 Datum::Uuid(Uuid::from_u128(u128::MAX)),
3662 ])
3663 });
3664 static ARRAY: LazyLock<BTreeMap<&'static SqlScalarType, Row>> = LazyLock::new(|| {
3665 let generate_row = |inner_type: &SqlScalarType| {
3666 let datums: Vec<_> = inner_type.interesting_datums().collect();
3667
3668 let mut row = Row::default();
3669 row.packer()
3670 .try_push_array::<_, Datum<'static>>(
3671 &[ArrayDimension {
3672 lower_bound: 1,
3673 length: 0,
3674 }],
3675 [],
3676 )
3677 .expect("failed to push empty array");
3678 row.packer()
3679 .try_push_array(
3680 &[ArrayDimension {
3681 lower_bound: 1,
3682 length: datums.len(),
3683 }],
3684 datums,
3685 )
3686 .expect("failed to push array");
3687
3688 row
3689 };
3690
3691 SqlScalarType::enumerate()
3692 .into_iter()
3693 .filter(|ty| !matches!(ty, SqlScalarType::Array(_)))
3694 .map(|ty| (ty, generate_row(ty)))
3695 .collect()
3696 });
3697 static EMPTY_ARRAY: LazyLock<Row> = LazyLock::new(|| {
3698 let mut row = Row::default();
3699 row.packer()
3700 .try_push_array::<_, Datum<'static>>(
3701 &[ArrayDimension {
3702 lower_bound: 1,
3703 length: 0,
3704 }],
3705 [],
3706 )
3707 .expect("failed to push empty array");
3708 row
3709 });
3710 static LIST: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3711 static RECORD: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3712 static OID: LazyLock<Row> =
3713 LazyLock::new(|| Row::pack_slice(&[Datum::UInt32(u32::MIN), Datum::UInt32(u32::MAX)]));
3714 static MAP: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3715 static INT2VECTOR: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3716 static MZTIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3717 Row::pack_slice(&[
3718 Datum::MzTimestamp(crate::Timestamp::MIN),
3719 Datum::MzTimestamp(crate::Timestamp::MAX),
3720 ])
3721 });
3722 static RANGE: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3723 static MZACLITEM: LazyLock<Row> = LazyLock::new(|| {
3724 Row::pack_slice(&[
3725 Datum::MzAclItem(MzAclItem {
3726 grantee: RoleId::Public,
3727 grantor: RoleId::Public,
3728 acl_mode: AclMode::empty(),
3729 }),
3730 Datum::MzAclItem(MzAclItem {
3731 grantee: RoleId::Public,
3732 grantor: RoleId::Public,
3733 acl_mode: AclMode::all(),
3734 }),
3735 Datum::MzAclItem(MzAclItem {
3736 grantee: RoleId::User(42),
3737 grantor: RoleId::Public,
3738 acl_mode: AclMode::empty(),
3739 }),
3740 Datum::MzAclItem(MzAclItem {
3741 grantee: RoleId::User(42),
3742 grantor: RoleId::Public,
3743 acl_mode: AclMode::all(),
3744 }),
3745 Datum::MzAclItem(MzAclItem {
3746 grantee: RoleId::Public,
3747 grantor: RoleId::User(42),
3748 acl_mode: AclMode::empty(),
3749 }),
3750 Datum::MzAclItem(MzAclItem {
3751 grantee: RoleId::Public,
3752 grantor: RoleId::User(42),
3753 acl_mode: AclMode::all(),
3754 }),
3755 ])
3756 });
3757 static ACLITEM: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3759
3760 let iter: Box<dyn Iterator<Item = Datum<'static>>> = match self {
3761 SqlScalarType::Bool => Box::new((*BOOL).iter()),
3762 SqlScalarType::Int16 => Box::new((*INT16).iter()),
3763 SqlScalarType::Int32 => Box::new((*INT32).iter()),
3764 SqlScalarType::Int64 => Box::new((*INT64).iter()),
3765 SqlScalarType::UInt16 => Box::new((*UINT16).iter()),
3766 SqlScalarType::UInt32 => Box::new((*UINT32).iter()),
3767 SqlScalarType::UInt64 => Box::new((*UINT64).iter()),
3768 SqlScalarType::Float32 => Box::new((*FLOAT32).iter()),
3769 SqlScalarType::Float64 => Box::new((*FLOAT64).iter()),
3770 SqlScalarType::Numeric { .. } => Box::new((*NUMERIC).iter()),
3771 SqlScalarType::Date => Box::new((*DATE).iter()),
3772 SqlScalarType::Time => Box::new((*TIME).iter()),
3773 SqlScalarType::Timestamp { .. } => Box::new((*TIMESTAMP).iter()),
3774 SqlScalarType::TimestampTz { .. } => Box::new((*TIMESTAMPTZ).iter()),
3775 SqlScalarType::Interval => Box::new((*INTERVAL).iter()),
3776 SqlScalarType::PgLegacyChar => Box::new((*PGLEGACYCHAR).iter()),
3777 SqlScalarType::PgLegacyName => Box::new((*PGLEGACYNAME).iter()),
3778 SqlScalarType::Bytes => Box::new((*BYTES).iter()),
3779 SqlScalarType::String => Box::new((*STRING).iter().chain((*CHAR).iter())),
3780 SqlScalarType::Char { .. } => Box::new((*CHAR).iter()),
3781 SqlScalarType::VarChar { .. } => Box::new((*STRING).iter().chain((*CHAR).iter())),
3782 SqlScalarType::Jsonb => Box::new((*JSONB).iter()),
3783 SqlScalarType::Uuid => Box::new((*UUID).iter()),
3784 SqlScalarType::Array(inner_type) => {
3785 if matches!(inner_type.as_ref(), SqlScalarType::Array(_)) {
3786 panic!("SqlScalarType::Array cannot have a nested Array");
3787 }
3788
3789 Box::new(
3790 (*ARRAY)
3791 .get(inner_type.as_ref())
3792 .unwrap_or(&*EMPTY_ARRAY)
3793 .iter(),
3794 )
3795 }
3796 SqlScalarType::List { .. } => Box::new((*LIST).iter()),
3797 SqlScalarType::Record { .. } => Box::new((*RECORD).iter()),
3798 SqlScalarType::Oid => Box::new((*OID).iter()),
3799 SqlScalarType::Map { .. } => Box::new((*MAP).iter()),
3800 SqlScalarType::RegProc => Box::new((*OID).iter()),
3801 SqlScalarType::RegType => Box::new((*OID).iter()),
3802 SqlScalarType::RegClass => Box::new((*OID).iter()),
3803 SqlScalarType::Int2Vector => Box::new((*INT2VECTOR).iter()),
3804 SqlScalarType::MzTimestamp => Box::new((*MZTIMESTAMP).iter()),
3805 SqlScalarType::Range { .. } => Box::new((*RANGE).iter()),
3806 SqlScalarType::MzAclItem { .. } => Box::new((*MZACLITEM).iter()),
3807 SqlScalarType::AclItem { .. } => Box::new((*ACLITEM).iter()),
3808 };
3809
3810 iter
3811 }
3812
3813 pub fn enumerate() -> &'static [Self] {
3816 &[
3819 SqlScalarType::Bool,
3820 SqlScalarType::Int16,
3821 SqlScalarType::Int32,
3822 SqlScalarType::Int64,
3823 SqlScalarType::UInt16,
3824 SqlScalarType::UInt32,
3825 SqlScalarType::UInt64,
3826 SqlScalarType::Float32,
3827 SqlScalarType::Float64,
3828 SqlScalarType::Numeric {
3829 max_scale: Some(NumericMaxScale(
3830 crate::adt::numeric::NUMERIC_DATUM_MAX_PRECISION,
3831 )),
3832 },
3833 SqlScalarType::Date,
3834 SqlScalarType::Time,
3835 SqlScalarType::Timestamp {
3836 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3837 },
3838 SqlScalarType::Timestamp {
3839 precision: Some(TimestampPrecision(0)),
3840 },
3841 SqlScalarType::Timestamp { precision: None },
3842 SqlScalarType::TimestampTz {
3843 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3844 },
3845 SqlScalarType::TimestampTz {
3846 precision: Some(TimestampPrecision(0)),
3847 },
3848 SqlScalarType::TimestampTz { precision: None },
3849 SqlScalarType::Interval,
3850 SqlScalarType::PgLegacyChar,
3851 SqlScalarType::Bytes,
3852 SqlScalarType::String,
3853 SqlScalarType::Char {
3854 length: Some(CharLength(1)),
3855 },
3856 SqlScalarType::VarChar { max_length: None },
3857 SqlScalarType::Jsonb,
3858 SqlScalarType::Uuid,
3859 SqlScalarType::Oid,
3860 SqlScalarType::RegProc,
3861 SqlScalarType::RegType,
3862 SqlScalarType::RegClass,
3863 SqlScalarType::Int2Vector,
3864 SqlScalarType::MzTimestamp,
3865 SqlScalarType::MzAclItem,
3866 ]
3887 }
3888
3889 pub fn array_of_self_elem_type(self) -> Result<SqlScalarType, SqlScalarType> {
3894 match self {
3895 t @ (SqlScalarType::AclItem
3896 | SqlScalarType::Bool
3897 | SqlScalarType::Int16
3898 | SqlScalarType::Int32
3899 | SqlScalarType::Int64
3900 | SqlScalarType::UInt16
3901 | SqlScalarType::UInt32
3902 | SqlScalarType::UInt64
3903 | SqlScalarType::Float32
3904 | SqlScalarType::Float64
3905 | SqlScalarType::Numeric { .. }
3906 | SqlScalarType::Date
3907 | SqlScalarType::Time
3908 | SqlScalarType::Timestamp { .. }
3909 | SqlScalarType::TimestampTz { .. }
3910 | SqlScalarType::Interval
3911 | SqlScalarType::PgLegacyChar
3912 | SqlScalarType::PgLegacyName
3913 | SqlScalarType::Bytes
3914 | SqlScalarType::String
3915 | SqlScalarType::VarChar { .. }
3916 | SqlScalarType::Jsonb
3917 | SqlScalarType::Uuid
3918 | SqlScalarType::Record { .. }
3919 | SqlScalarType::Oid
3920 | SqlScalarType::RegProc
3921 | SqlScalarType::RegType
3922 | SqlScalarType::RegClass
3923 | SqlScalarType::Int2Vector
3924 | SqlScalarType::MzTimestamp
3925 | SqlScalarType::Range { .. }
3926 | SqlScalarType::MzAclItem { .. }) => Ok(t),
3927
3928 SqlScalarType::Array(elem) => Ok(elem.array_of_self_elem_type()?),
3929
3930 t @ (SqlScalarType::Char { .. }
3932 | SqlScalarType::Map { .. }
3934 | SqlScalarType::List { .. }) => Err(t),
3935 }
3936 }
3937}
3938
3939impl Arbitrary for SqlScalarType {
3942 type Parameters = ();
3943 type Strategy = BoxedStrategy<SqlScalarType>;
3944
3945 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
3946 let leaf = Union::new(vec![
3948 Just(SqlScalarType::Bool).boxed(),
3949 Just(SqlScalarType::UInt16).boxed(),
3950 Just(SqlScalarType::UInt32).boxed(),
3951 Just(SqlScalarType::UInt64).boxed(),
3952 Just(SqlScalarType::Int16).boxed(),
3953 Just(SqlScalarType::Int32).boxed(),
3954 Just(SqlScalarType::Int64).boxed(),
3955 Just(SqlScalarType::Float32).boxed(),
3956 Just(SqlScalarType::Float64).boxed(),
3957 any::<Option<NumericMaxScale>>()
3958 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
3959 .boxed(),
3960 Just(SqlScalarType::Date).boxed(),
3961 Just(SqlScalarType::Time).boxed(),
3962 any::<Option<TimestampPrecision>>()
3963 .prop_map(|precision| SqlScalarType::Timestamp { precision })
3964 .boxed(),
3965 any::<Option<TimestampPrecision>>()
3966 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
3967 .boxed(),
3968 Just(SqlScalarType::MzTimestamp).boxed(),
3969 Just(SqlScalarType::Interval).boxed(),
3970 Just(SqlScalarType::PgLegacyChar).boxed(),
3971 Just(SqlScalarType::Bytes).boxed(),
3972 Just(SqlScalarType::String).boxed(),
3973 any::<Option<CharLength>>()
3974 .prop_map(|length| SqlScalarType::Char { length })
3975 .boxed(),
3976 any::<Option<VarCharMaxLength>>()
3977 .prop_map(|max_length| SqlScalarType::VarChar { max_length })
3978 .boxed(),
3979 Just(SqlScalarType::PgLegacyName).boxed(),
3980 Just(SqlScalarType::Jsonb).boxed(),
3981 Just(SqlScalarType::Uuid).boxed(),
3982 Just(SqlScalarType::AclItem).boxed(),
3983 Just(SqlScalarType::MzAclItem).boxed(),
3984 Just(SqlScalarType::Oid).boxed(),
3985 Just(SqlScalarType::RegProc).boxed(),
3986 Just(SqlScalarType::RegType).boxed(),
3987 Just(SqlScalarType::RegClass).boxed(),
3988 Just(SqlScalarType::Int2Vector).boxed(),
3989 ])
3990 .no_shrink()
3993 .boxed();
3994
3995 let range_leaf = Union::new(vec![
3997 Just(SqlScalarType::Int32).boxed(),
3998 Just(SqlScalarType::Int64).boxed(),
3999 Just(SqlScalarType::Date).boxed(),
4000 any::<Option<NumericMaxScale>>()
4001 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
4002 .boxed(),
4003 any::<Option<TimestampPrecision>>()
4004 .prop_map(|precision| SqlScalarType::Timestamp { precision })
4005 .boxed(),
4006 any::<Option<TimestampPrecision>>()
4007 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
4008 .boxed(),
4009 ]);
4010 let range = range_leaf
4011 .prop_map(|inner_type| SqlScalarType::Range {
4012 element_type: Box::new(inner_type),
4013 })
4014 .boxed();
4015
4016 let array = leaf
4018 .clone()
4019 .prop_map(|inner_type| SqlScalarType::Array(Box::new(inner_type)))
4020 .boxed();
4021
4022 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
4023
4024 leaf.prop_recursive(2, 3, 5, |inner| {
4025 Union::new(vec![
4026 (inner.clone(), any::<Option<CatalogItemId>>())
4028 .prop_map(|(x, id)| SqlScalarType::List {
4029 element_type: Box::new(x),
4030 custom_id: id,
4031 })
4032 .boxed(),
4033 (inner.clone(), any::<Option<CatalogItemId>>())
4035 .prop_map(|(x, id)| SqlScalarType::Map {
4036 value_type: Box::new(x),
4037 custom_id: id,
4038 })
4039 .boxed(),
4040 {
4042 let column_type_strat =
4045 (inner, any::<bool>()).prop_map(|(scalar_type, nullable)| SqlColumnType {
4046 scalar_type,
4047 nullable,
4048 });
4049
4050 let fields_strat =
4053 prop::collection::vec((any::<ColumnName>(), column_type_strat), 0..10);
4054
4055 (fields_strat, any::<Option<CatalogItemId>>())
4057 .prop_map(|(fields, custom_id)| SqlScalarType::Record {
4058 fields: fields.into(),
4059 custom_id,
4060 })
4061 .boxed()
4062 },
4063 ])
4064 })
4065 .boxed()
4066 }
4067}
4068
4069impl Arbitrary for ReprScalarType {
4070 type Parameters = ();
4071 type Strategy = BoxedStrategy<ReprScalarType>;
4072
4073 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
4074 let leaf = Union::new(vec![
4076 Just(ReprScalarType::Bool).boxed(),
4077 Just(ReprScalarType::UInt8).boxed(),
4078 Just(ReprScalarType::UInt16).boxed(),
4079 Just(ReprScalarType::UInt32).boxed(),
4080 Just(ReprScalarType::UInt64).boxed(),
4081 Just(ReprScalarType::Int16).boxed(),
4082 Just(ReprScalarType::Int32).boxed(),
4083 Just(ReprScalarType::Int64).boxed(),
4084 Just(ReprScalarType::Float32).boxed(),
4085 Just(ReprScalarType::Float64).boxed(),
4086 Just(ReprScalarType::Numeric).boxed(),
4087 Just(ReprScalarType::Date).boxed(),
4088 Just(ReprScalarType::Time).boxed(),
4089 Just(ReprScalarType::Timestamp).boxed(),
4090 Just(ReprScalarType::TimestampTz).boxed(),
4091 Just(ReprScalarType::MzTimestamp).boxed(),
4092 Just(ReprScalarType::Interval).boxed(),
4093 Just(ReprScalarType::Bytes).boxed(),
4094 Just(ReprScalarType::String).boxed(),
4095 Just(ReprScalarType::Jsonb).boxed(),
4096 Just(ReprScalarType::Uuid).boxed(),
4097 Just(ReprScalarType::AclItem).boxed(),
4098 Just(ReprScalarType::MzAclItem).boxed(),
4099 Just(ReprScalarType::Int2Vector).boxed(),
4100 ])
4101 .no_shrink()
4104 .boxed();
4105
4106 let range_leaf = Union::new(vec![
4108 Just(ReprScalarType::Int32).boxed(),
4109 Just(ReprScalarType::Int64).boxed(),
4110 Just(ReprScalarType::Date).boxed(),
4111 Just(ReprScalarType::Numeric).boxed(),
4112 Just(ReprScalarType::Timestamp).boxed(),
4113 Just(ReprScalarType::TimestampTz).boxed(),
4114 ]);
4115 let range = range_leaf
4116 .prop_map(|inner_type| ReprScalarType::Range {
4117 element_type: Box::new(inner_type),
4118 })
4119 .boxed();
4120
4121 let array = leaf
4123 .clone()
4124 .prop_map(|inner_type| ReprScalarType::Array(Box::new(inner_type)))
4125 .boxed();
4126
4127 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
4128
4129 leaf.prop_recursive(2, 3, 5, |inner| {
4130 Union::new(vec![
4131 inner
4133 .clone()
4134 .prop_map(|x| ReprScalarType::List {
4135 element_type: Box::new(x),
4136 })
4137 .boxed(),
4138 inner
4140 .clone()
4141 .prop_map(|x| ReprScalarType::Map {
4142 value_type: Box::new(x),
4143 })
4144 .boxed(),
4145 {
4147 let column_type_strat =
4150 (inner.clone(), any::<bool>()).prop_map(|(scalar_type, nullable)| {
4151 ReprColumnType {
4152 scalar_type,
4153 nullable,
4154 }
4155 });
4156
4157 let fields_strat = prop::collection::vec(column_type_strat, 0..10);
4160
4161 fields_strat
4163 .prop_map(|fields| ReprScalarType::Record {
4164 fields: fields.into_boxed_slice(),
4165 })
4166 .boxed()
4167 },
4168 ])
4169 })
4170 .boxed()
4171 }
4172}
4173
4174#[derive(
4182 Clone, Debug, EnumKind, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash, MzReflect,
4183)]
4184#[enum_kind(ReprScalarBaseType, derive(PartialOrd, Ord, Hash))]
4185pub enum ReprScalarType {
4186 Bool,
4187 Int16,
4188 Int32,
4189 Int64,
4190 UInt8, UInt16,
4192 UInt32, UInt64,
4194 Float32,
4195 Float64,
4196 Numeric,
4197 Date,
4198 Time,
4199 Timestamp,
4200 TimestampTz,
4201 MzTimestamp,
4202 Interval,
4203 Bytes,
4204 Jsonb,
4205 String, Uuid,
4207 Array(Box<ReprScalarType>),
4208 Int2Vector, List { element_type: Box<ReprScalarType> },
4210 Record { fields: Box<[ReprColumnType]> },
4211 Map { value_type: Box<ReprScalarType> },
4212 Range { element_type: Box<ReprScalarType> },
4213 MzAclItem,
4214 AclItem,
4215}
4216
4217impl From<&SqlScalarType> for ReprScalarType {
4218 fn from(typ: &SqlScalarType) -> Self {
4219 match typ {
4220 SqlScalarType::Bool => ReprScalarType::Bool,
4221 SqlScalarType::Int16 => ReprScalarType::Int16,
4222 SqlScalarType::Int32 => ReprScalarType::Int32,
4223 SqlScalarType::Int64 => ReprScalarType::Int64,
4224 SqlScalarType::UInt16 => ReprScalarType::UInt16,
4225 SqlScalarType::UInt32 => ReprScalarType::UInt32,
4226 SqlScalarType::UInt64 => ReprScalarType::UInt64,
4227 SqlScalarType::Float32 => ReprScalarType::Float32,
4228 SqlScalarType::Float64 => ReprScalarType::Float64,
4229 SqlScalarType::Numeric { max_scale: _ } => ReprScalarType::Numeric,
4230 SqlScalarType::Date => ReprScalarType::Date,
4231 SqlScalarType::Time => ReprScalarType::Time,
4232 SqlScalarType::Timestamp { precision: _ } => ReprScalarType::Timestamp,
4233 SqlScalarType::TimestampTz { precision: _ } => ReprScalarType::TimestampTz,
4234 SqlScalarType::Interval => ReprScalarType::Interval,
4235 SqlScalarType::PgLegacyChar => ReprScalarType::UInt8,
4236 SqlScalarType::PgLegacyName => ReprScalarType::String,
4237 SqlScalarType::Bytes => ReprScalarType::Bytes,
4238 SqlScalarType::String => ReprScalarType::String,
4239 SqlScalarType::Char { length: _ } => ReprScalarType::String,
4240 SqlScalarType::VarChar { max_length: _ } => ReprScalarType::String,
4241 SqlScalarType::Jsonb => ReprScalarType::Jsonb,
4242 SqlScalarType::Uuid => ReprScalarType::Uuid,
4243 SqlScalarType::Array(element_type) => {
4244 ReprScalarType::Array(Box::new(element_type.as_ref().into()))
4245 }
4246 SqlScalarType::List {
4247 element_type,
4248 custom_id: _,
4249 } => ReprScalarType::List {
4250 element_type: Box::new(element_type.as_ref().into()),
4251 },
4252 SqlScalarType::Record {
4253 fields,
4254 custom_id: _,
4255 } => ReprScalarType::Record {
4256 fields: fields.into_iter().map(|(_, typ)| typ.into()).collect(),
4257 },
4258 SqlScalarType::Oid => ReprScalarType::UInt32,
4259 SqlScalarType::Map {
4260 value_type,
4261 custom_id: _,
4262 } => ReprScalarType::Map {
4263 value_type: Box::new(value_type.as_ref().into()),
4264 },
4265 SqlScalarType::RegProc => ReprScalarType::UInt32,
4266 SqlScalarType::RegType => ReprScalarType::UInt32,
4267 SqlScalarType::RegClass => ReprScalarType::UInt32,
4268 SqlScalarType::Int2Vector => ReprScalarType::Int2Vector,
4269 SqlScalarType::MzTimestamp => ReprScalarType::MzTimestamp,
4270 SqlScalarType::Range { element_type } => ReprScalarType::Range {
4271 element_type: Box::new(element_type.as_ref().into()),
4272 },
4273 SqlScalarType::MzAclItem => ReprScalarType::MzAclItem,
4274 SqlScalarType::AclItem => ReprScalarType::AclItem,
4275 }
4276 }
4277}
4278
4279impl SqlScalarType {
4280 pub fn from_repr(repr: &ReprScalarType) -> Self {
4300 match repr {
4301 ReprScalarType::Bool => SqlScalarType::Bool,
4302 ReprScalarType::Int16 => SqlScalarType::Int16,
4303 ReprScalarType::Int32 => SqlScalarType::Int32,
4304 ReprScalarType::Int64 => SqlScalarType::Int64,
4305 ReprScalarType::UInt8 => SqlScalarType::PgLegacyChar,
4306 ReprScalarType::UInt16 => SqlScalarType::UInt16,
4307 ReprScalarType::UInt32 => SqlScalarType::UInt32,
4308 ReprScalarType::UInt64 => SqlScalarType::UInt64,
4309 ReprScalarType::Float32 => SqlScalarType::Float32,
4310 ReprScalarType::Float64 => SqlScalarType::Float64,
4311 ReprScalarType::Numeric => SqlScalarType::Numeric { max_scale: None },
4312 ReprScalarType::Date => SqlScalarType::Date,
4313 ReprScalarType::Time => SqlScalarType::Time,
4314 ReprScalarType::Timestamp => SqlScalarType::Timestamp { precision: None },
4315 ReprScalarType::TimestampTz => SqlScalarType::TimestampTz { precision: None },
4316 ReprScalarType::MzTimestamp => SqlScalarType::MzTimestamp,
4317 ReprScalarType::Interval => SqlScalarType::Interval,
4318 ReprScalarType::Bytes => SqlScalarType::Bytes,
4319 ReprScalarType::Jsonb => SqlScalarType::Jsonb,
4320 ReprScalarType::String => SqlScalarType::String,
4321 ReprScalarType::Uuid => SqlScalarType::Uuid,
4322 ReprScalarType::Array(element_type) => {
4323 SqlScalarType::Array(Box::new(SqlScalarType::from_repr(element_type)))
4324 }
4325 ReprScalarType::Int2Vector => SqlScalarType::Int2Vector,
4326 ReprScalarType::List { element_type } => SqlScalarType::List {
4327 element_type: Box::new(SqlScalarType::from_repr(element_type)),
4328 custom_id: None,
4329 },
4330 ReprScalarType::Record { fields } => SqlScalarType::Record {
4331 fields: fields
4332 .iter()
4333 .enumerate()
4334 .map(|typ| {
4335 (
4336 ColumnName::from(format!("field_{}", typ.0)),
4337 SqlColumnType::from_repr(typ.1),
4338 )
4339 })
4340 .collect::<Vec<_>>()
4341 .into_boxed_slice(),
4342 custom_id: None,
4343 },
4344 ReprScalarType::Map { value_type } => SqlScalarType::Map {
4345 value_type: Box::new(SqlScalarType::from_repr(value_type)),
4346 custom_id: None,
4347 },
4348 ReprScalarType::Range { element_type } => SqlScalarType::Range {
4349 element_type: Box::new(SqlScalarType::from_repr(element_type)),
4350 },
4351 ReprScalarType::MzAclItem => SqlScalarType::MzAclItem,
4352 ReprScalarType::AclItem => SqlScalarType::AclItem,
4353 }
4354 }
4355}
4356
4357static EMPTY_ARRAY_ROW: LazyLock<Row> = LazyLock::new(|| {
4358 let mut row = Row::default();
4359 row.packer()
4360 .try_push_array(&[], iter::empty::<Datum>())
4361 .expect("array known to be valid");
4362 row
4363});
4364
4365static EMPTY_LIST_ROW: LazyLock<Row> = LazyLock::new(|| {
4366 let mut row = Row::default();
4367 row.packer().push_list(iter::empty::<Datum>());
4368 row
4369});
4370
4371static EMPTY_MAP_ROW: LazyLock<Row> = LazyLock::new(|| {
4372 let mut row = Row::default();
4373 row.packer().push_dict(iter::empty::<(_, Datum)>());
4374 row
4375});
4376
4377impl Datum<'_> {
4378 pub fn empty_array() -> Datum<'static> {
4379 EMPTY_ARRAY_ROW.unpack_first()
4380 }
4381
4382 pub fn empty_list() -> Datum<'static> {
4383 EMPTY_LIST_ROW.unpack_first()
4384 }
4385
4386 pub fn empty_map() -> Datum<'static> {
4387 EMPTY_MAP_ROW.unpack_first()
4388 }
4389}
4390
4391#[derive(Debug, PartialEq, Clone)]
4393pub enum PropDatum {
4394 Null,
4395 Bool(bool),
4396 Int16(i16),
4397 Int32(i32),
4398 Int64(i64),
4399 UInt8(u8),
4400 UInt16(u16),
4401 UInt32(u32),
4402 UInt64(u64),
4403 Float32(f32),
4404 Float64(f64),
4405
4406 Date(Date),
4407 Time(chrono::NaiveTime),
4408 Timestamp(CheckedTimestamp<chrono::NaiveDateTime>),
4409 TimestampTz(CheckedTimestamp<chrono::DateTime<chrono::Utc>>),
4410 MzTimestamp(u64),
4411
4412 Interval(Interval),
4413 Numeric(Numeric),
4414
4415 Bytes(Vec<u8>),
4416 String(String),
4417
4418 Array(PropArray),
4419 List(PropList),
4420 Map(PropDict),
4421 Record(PropDict),
4422 Range(PropRange),
4423
4424 AclItem(AclItem),
4425 MzAclItem(MzAclItem),
4426
4427 JsonNull,
4428 Uuid(Uuid),
4429 Dummy,
4430}
4431
4432impl std::cmp::Eq for PropDatum {}
4433
4434impl PartialOrd for PropDatum {
4435 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
4436 Some(self.cmp(other))
4437 }
4438}
4439
4440impl Ord for PropDatum {
4441 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
4442 Datum::from(self).cmp(&Datum::from(other))
4443 }
4444}
4445
4446pub fn arb_datum() -> BoxedStrategy<PropDatum> {
4448 let leaf = Union::new(vec![
4449 Just(PropDatum::Dummy).boxed(),
4450 any::<bool>().prop_map(PropDatum::Bool).boxed(),
4451 any::<i16>().prop_map(PropDatum::Int16).boxed(),
4452 any::<i32>().prop_map(PropDatum::Int32).boxed(),
4453 any::<i64>().prop_map(PropDatum::Int64).boxed(),
4454 any::<u16>().prop_map(PropDatum::UInt16).boxed(),
4455 any::<u32>().prop_map(PropDatum::UInt32).boxed(),
4456 any::<u64>().prop_map(PropDatum::UInt64).boxed(),
4457 any::<f32>().prop_map(PropDatum::Float32).boxed(),
4458 any::<f64>().prop_map(PropDatum::Float64).boxed(),
4459 arb_date().prop_map(PropDatum::Date).boxed(),
4460 add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
4461 .prop_map(PropDatum::Time)
4462 .boxed(),
4463 arb_naive_date_time()
4464 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
4465 .boxed(),
4466 arb_utc_date_time()
4467 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
4468 .boxed(),
4469 any::<Interval>().prop_map(PropDatum::Interval).boxed(),
4470 arb_numeric().prop_map(PropDatum::Numeric).boxed(),
4471 prop::collection::vec(any::<u8>(), 1024)
4472 .prop_map(PropDatum::Bytes)
4473 .boxed(),
4474 ".*".prop_map(PropDatum::String).boxed(),
4475 Just(PropDatum::JsonNull).boxed(),
4476 any::<[u8; 16]>()
4477 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
4478 .boxed(),
4479 arb_range(arb_range_data())
4480 .prop_map(PropDatum::Range)
4481 .boxed(),
4482 Just(PropDatum::Dummy).boxed(),
4483 ]);
4484
4485 leaf.prop_recursive(3, 8, 16, |inner| {
4486 Union::new(vec![
4487 arb_array(inner.clone()).prop_map(PropDatum::Array).boxed(),
4488 arb_list(inner.clone()).prop_map(PropDatum::List).boxed(),
4489 arb_dict(inner).prop_map(PropDatum::Map).boxed(),
4490 ])
4491 })
4492 .boxed()
4493}
4494
4495pub fn arb_datum_for_column(column_type: SqlColumnType) -> impl Strategy<Value = PropDatum> {
4497 let strat = arb_datum_for_scalar(column_type.scalar_type);
4498
4499 if column_type.nullable {
4500 Union::new_weighted(vec![(1, Just(PropDatum::Null).boxed()), (5, strat.boxed())]).boxed()
4501 } else {
4502 strat.boxed()
4503 }
4504}
4505
4506pub fn arb_datum_for_scalar(scalar_type: SqlScalarType) -> impl Strategy<Value = PropDatum> {
4508 match scalar_type {
4509 SqlScalarType::Bool => any::<bool>().prop_map(PropDatum::Bool).boxed(),
4510 SqlScalarType::Int16 => any::<i16>().prop_map(PropDatum::Int16).boxed(),
4511 SqlScalarType::Int32 => any::<i32>().prop_map(PropDatum::Int32).boxed(),
4512 SqlScalarType::Int64 => any::<i64>().prop_map(PropDatum::Int64).boxed(),
4513 SqlScalarType::PgLegacyChar => any::<u8>().prop_map(PropDatum::UInt8).boxed(),
4514 SqlScalarType::UInt16 => any::<u16>().prop_map(PropDatum::UInt16).boxed(),
4515 SqlScalarType::UInt32
4516 | SqlScalarType::Oid
4517 | SqlScalarType::RegClass
4518 | SqlScalarType::RegProc
4519 | SqlScalarType::RegType => any::<u32>().prop_map(PropDatum::UInt32).boxed(),
4520 SqlScalarType::UInt64 => any::<u64>().prop_map(PropDatum::UInt64).boxed(),
4521 SqlScalarType::Float32 => any::<f32>().prop_map(PropDatum::Float32).boxed(),
4522 SqlScalarType::Float64 => any::<f64>().prop_map(PropDatum::Float64).boxed(),
4523 SqlScalarType::Numeric { .. } => arb_numeric().prop_map(PropDatum::Numeric).boxed(),
4524 SqlScalarType::String
4525 | SqlScalarType::PgLegacyName
4526 | SqlScalarType::Char { length: None }
4527 | SqlScalarType::VarChar { max_length: None } => ".*".prop_map(PropDatum::String).boxed(),
4528 SqlScalarType::Char {
4529 length: Some(length),
4530 } => {
4531 let max_len = usize::cast_from(length.into_u32()).max(1);
4532 prop::collection::vec(any::<char>(), 0..max_len)
4533 .prop_map(move |chars| {
4534 let num_blanks = max_len - chars.len();
4536 let s = chars
4537 .into_iter()
4538 .chain(std::iter::repeat(' ').take(num_blanks))
4539 .collect();
4540 PropDatum::String(s)
4541 })
4542 .boxed()
4543 }
4544 SqlScalarType::VarChar {
4545 max_length: Some(length),
4546 } => {
4547 let max_len = usize::cast_from(length.into_u32()).max(1);
4548 prop::collection::vec(any::<char>(), 0..max_len)
4549 .prop_map(|chars| PropDatum::String(chars.into_iter().collect()))
4550 .boxed()
4551 }
4552 SqlScalarType::Bytes => prop::collection::vec(any::<u8>(), 300)
4553 .prop_map(PropDatum::Bytes)
4554 .boxed(),
4555 SqlScalarType::Date => arb_date().prop_map(PropDatum::Date).boxed(),
4556 SqlScalarType::Time => add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
4557 .prop_map(PropDatum::Time)
4558 .boxed(),
4559 SqlScalarType::Timestamp { .. } => arb_naive_date_time()
4560 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
4561 .boxed(),
4562 SqlScalarType::TimestampTz { .. } => arb_utc_date_time()
4563 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
4564 .boxed(),
4565 SqlScalarType::MzTimestamp => any::<u64>().prop_map(PropDatum::MzTimestamp).boxed(),
4566 SqlScalarType::Interval => any::<Interval>().prop_map(PropDatum::Interval).boxed(),
4567 SqlScalarType::Uuid => any::<[u8; 16]>()
4568 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
4569 .boxed(),
4570 SqlScalarType::AclItem => any::<AclItem>().prop_map(PropDatum::AclItem).boxed(),
4571 SqlScalarType::MzAclItem => any::<MzAclItem>().prop_map(PropDatum::MzAclItem).boxed(),
4572 SqlScalarType::Range { element_type } => {
4573 let data_strat = (
4574 arb_datum_for_scalar(*element_type.clone()),
4575 arb_datum_for_scalar(*element_type),
4576 );
4577 arb_range(data_strat).prop_map(PropDatum::Range).boxed()
4578 }
4579 SqlScalarType::List { element_type, .. } => arb_list(arb_datum_for_scalar(*element_type))
4580 .prop_map(PropDatum::List)
4581 .boxed(),
4582 SqlScalarType::Array(element_type) => arb_array(arb_datum_for_scalar(*element_type))
4583 .prop_map(PropDatum::Array)
4584 .boxed(),
4585 SqlScalarType::Int2Vector => arb_array(any::<i16>().prop_map(PropDatum::Int16).boxed())
4586 .prop_map(PropDatum::Array)
4587 .boxed(),
4588 SqlScalarType::Map { value_type, .. } => arb_dict(arb_datum_for_scalar(*value_type))
4589 .prop_map(PropDatum::Map)
4590 .boxed(),
4591 SqlScalarType::Record { fields, .. } => {
4592 let field_strats = fields.iter().map(|(name, ty)| {
4593 (
4594 name.to_string(),
4595 arb_datum_for_scalar(ty.scalar_type.clone()),
4596 )
4597 });
4598 arb_record(field_strats).prop_map(PropDatum::Record).boxed()
4599 }
4600 SqlScalarType::Jsonb => {
4601 let int_value = any::<i128>()
4602 .prop_map(|v| Numeric::try_from(v).unwrap())
4603 .boxed();
4604 let float_value = (1e-39f64..1e39)
4606 .prop_map(|v| Numeric::try_from(v).unwrap())
4607 .boxed();
4608 let json_number = Union::new(vec![int_value, float_value]);
4611
4612 let json_leaf = Union::new(vec![
4613 any::<()>().prop_map(|_| PropDatum::JsonNull).boxed(),
4614 any::<bool>().prop_map(PropDatum::Bool).boxed(),
4615 json_number.prop_map(PropDatum::Numeric).boxed(),
4616 ".*".prop_map(PropDatum::String).boxed(),
4617 ]);
4618 json_leaf
4619 .prop_recursive(4, 32, 8, |element| {
4620 Union::new(vec![
4621 prop::collection::vec(element.clone(), 0..16)
4622 .prop_map(|elements| {
4623 let datums: Vec<_> = elements.iter().map(|pd| pd.into()).collect();
4624 let mut row = Row::default();
4625 row.packer().push_list(datums.iter());
4626 PropDatum::List(PropList(row, elements))
4627 })
4628 .boxed(),
4629 prop::collection::hash_map(".*", element, 0..16)
4630 .prop_map(|elements| {
4631 let mut elements: Vec<_> = elements.into_iter().collect();
4632 elements.sort_by_key(|(k, _)| k.clone());
4633 elements.dedup_by_key(|(k, _)| k.clone());
4634 let mut row = Row::default();
4635 let entry_iter =
4636 elements.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4637 row.packer().push_dict(entry_iter);
4638 PropDatum::Map(PropDict(row, elements))
4639 })
4640 .boxed(),
4641 ])
4642 })
4643 .boxed()
4644 }
4645 }
4646}
4647
4648pub fn arb_naive_date_time() -> impl Strategy<Value = NaiveDateTime> {
4650 add_arb_duration(chrono::DateTime::from_timestamp(0, 0).unwrap().naive_utc())
4651}
4652
4653pub fn arb_utc_date_time() -> impl Strategy<Value = DateTime<Utc>> {
4655 add_arb_duration(chrono::Utc.timestamp_opt(0, 0).unwrap())
4656}
4657
4658fn arb_array_dimension() -> BoxedStrategy<ArrayDimension> {
4659 (1..4_usize)
4660 .prop_map(|length| ArrayDimension {
4661 lower_bound: 1,
4662 length,
4663 })
4664 .boxed()
4665}
4666
4667#[derive(Debug, PartialEq, Clone)]
4668pub struct PropArray(Row, Vec<PropDatum>);
4669
4670fn arb_array(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropArray> {
4671 let element_strategy = Union::new_weighted(vec![
4673 (20, element_strategy),
4674 (1, Just(PropDatum::Null).boxed()),
4675 ]);
4676
4677 prop::collection::vec(
4678 arb_array_dimension(),
4679 1..usize::from(crate::adt::array::MAX_ARRAY_DIMENSIONS),
4680 )
4681 .prop_flat_map(move |dimensions| {
4682 let n_elts: usize = dimensions.iter().map(|d| d.length).product();
4683 (
4684 Just(dimensions),
4685 prop::collection::vec(element_strategy.clone(), n_elts),
4686 )
4687 })
4688 .prop_map(|(dimensions, elements)| {
4689 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4690 let mut row = Row::default();
4691 row.packer()
4692 .try_push_array(&dimensions, element_datums)
4693 .unwrap();
4694 PropArray(row, elements)
4695 })
4696 .boxed()
4697}
4698
4699#[derive(Debug, PartialEq, Clone)]
4700pub struct PropList(Row, Vec<PropDatum>);
4701
4702fn arb_list(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropList> {
4703 let element_strategy = Union::new_weighted(vec![
4705 (20, element_strategy),
4706 (1, Just(PropDatum::Null).boxed()),
4707 ]);
4708
4709 prop::collection::vec(element_strategy, 1..50)
4710 .prop_map(|elements| {
4711 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4712 let mut row = Row::default();
4713 row.packer().push_list(element_datums.iter());
4714 PropList(row, elements)
4715 })
4716 .boxed()
4717}
4718
4719#[derive(Debug, PartialEq, Clone)]
4720pub struct PropRange(
4721 Row,
4722 Option<(
4723 (Option<Box<PropDatum>>, bool),
4724 (Option<Box<PropDatum>>, bool),
4725 )>,
4726);
4727
4728pub fn arb_range_type() -> Union<BoxedStrategy<SqlScalarType>> {
4729 Union::new(vec![
4730 Just(SqlScalarType::Int32).boxed(),
4731 Just(SqlScalarType::Int64).boxed(),
4732 Just(SqlScalarType::Date).boxed(),
4733 ])
4734}
4735
4736fn arb_range_data() -> Union<BoxedStrategy<(PropDatum, PropDatum)>> {
4737 Union::new(vec![
4738 (
4739 any::<i32>().prop_map(PropDatum::Int32),
4740 any::<i32>().prop_map(PropDatum::Int32),
4741 )
4742 .boxed(),
4743 (
4744 any::<i64>().prop_map(PropDatum::Int64),
4745 any::<i64>().prop_map(PropDatum::Int64),
4746 )
4747 .boxed(),
4748 (
4749 arb_date().prop_map(PropDatum::Date),
4750 arb_date().prop_map(PropDatum::Date),
4751 )
4752 .boxed(),
4753 ])
4754}
4755
4756fn arb_range(
4757 data: impl Strategy<Value = (PropDatum, PropDatum)> + 'static,
4758) -> BoxedStrategy<PropRange> {
4759 (
4760 any::<u16>(),
4761 any::<bool>(),
4762 any::<bool>(),
4763 any::<bool>(),
4764 any::<bool>(),
4765 data,
4766 )
4767 .prop_map(
4768 |(split, lower_inf, lower_inc, upper_inf, upper_inc, (a, b))| {
4769 let mut row = Row::default();
4770 let mut packer = row.packer();
4771 let r = if split % 32 == 0 {
4772 packer
4773 .push_range(Range::new(None))
4774 .expect("pushing empty ranges never fails");
4775 None
4776 } else {
4777 let b_is_lower = Datum::from(&b) < Datum::from(&a);
4778
4779 let (lower, upper) = if b_is_lower { (b, a) } else { (a, b) };
4780 let mut range = Range::new(Some((
4781 RangeLowerBound {
4782 inclusive: lower_inc,
4783 bound: if lower_inf {
4784 None
4785 } else {
4786 Some(Datum::from(&lower))
4787 },
4788 },
4789 RangeUpperBound {
4790 inclusive: upper_inc,
4791 bound: if upper_inf {
4792 None
4793 } else {
4794 Some(Datum::from(&upper))
4795 },
4796 },
4797 )));
4798
4799 range.canonicalize().unwrap();
4800
4801 let (empty, lower_inf, lower_inc, upper_inf, upper_inc) = match range.inner {
4804 None => (true, false, false, false, false),
4805 Some(inner) => (
4806 false
4807 || match inner.lower.bound {
4808 Some(b) => b != Datum::from(&lower),
4809 None => !lower_inf,
4810 }
4811 || match inner.upper.bound {
4812 Some(b) => b != Datum::from(&upper),
4813 None => !upper_inf,
4814 },
4815 inner.lower.bound.is_none(),
4816 inner.lower.inclusive,
4817 inner.upper.bound.is_none(),
4818 inner.upper.inclusive,
4819 ),
4820 };
4821
4822 if empty {
4823 packer.push_range(Range { inner: None }).unwrap();
4824 None
4825 } else {
4826 packer.push_range(range).unwrap();
4827 Some((
4828 (
4829 if lower_inf {
4830 None
4831 } else {
4832 Some(Box::new(lower))
4833 },
4834 lower_inc,
4835 ),
4836 (
4837 if upper_inf {
4838 None
4839 } else {
4840 Some(Box::new(upper))
4841 },
4842 upper_inc,
4843 ),
4844 ))
4845 }
4846 };
4847
4848 PropRange(row, r)
4849 },
4850 )
4851 .boxed()
4852}
4853
4854#[derive(Debug, PartialEq, Clone)]
4855pub struct PropDict(Row, Vec<(String, PropDatum)>);
4856
4857fn arb_dict(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropDict> {
4858 let element_strategy = Union::new_weighted(vec![
4860 (20, element_strategy),
4861 (1, Just(PropDatum::Null).boxed()),
4862 ]);
4863
4864 prop::collection::vec((".*", element_strategy), 1..50)
4865 .prop_map(|mut entries| {
4866 entries.sort_by_key(|(k, _)| k.clone());
4867 entries.dedup_by_key(|(k, _)| k.clone());
4868 let mut row = Row::default();
4869 let entry_iter = entries.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4870 row.packer().push_dict(entry_iter);
4871 PropDict(row, entries)
4872 })
4873 .boxed()
4874}
4875
4876fn arb_record(
4877 fields: impl Iterator<Item = (String, BoxedStrategy<PropDatum>)>,
4878) -> BoxedStrategy<PropDict> {
4879 let (names, strategies): (Vec<_>, Vec<_>) = fields.unzip();
4880
4881 strategies
4882 .prop_map(move |x| {
4883 let mut row = Row::default();
4884 row.packer().push_list(x.iter().map(Datum::from));
4885 let entries: Vec<_> = names.clone().into_iter().zip_eq(x).collect();
4886 PropDict(row, entries)
4887 })
4888 .boxed()
4889}
4890
4891fn arb_date() -> BoxedStrategy<Date> {
4892 (Date::LOW_DAYS..Date::HIGH_DAYS)
4893 .prop_map(move |days| Date::from_pg_epoch(days).unwrap())
4894 .boxed()
4895}
4896
4897pub fn add_arb_duration<T: 'static + Copy + Add<chrono::Duration> + std::fmt::Debug>(
4898 to: T,
4899) -> BoxedStrategy<T::Output>
4900where
4901 T::Output: std::fmt::Debug,
4902{
4903 let lower = LOW_DATE
4904 .and_hms_opt(0, 0, 0)
4905 .unwrap()
4906 .and_utc()
4907 .timestamp_micros();
4908 let upper = HIGH_DATE
4909 .and_hms_opt(0, 0, 0)
4910 .unwrap()
4911 .and_utc()
4912 .timestamp_micros();
4913 (lower..upper)
4914 .prop_map(move |v| to + chrono::Duration::microseconds(v))
4915 .boxed()
4916}
4917
4918pub(crate) fn arb_numeric() -> BoxedStrategy<Numeric> {
4919 let int_value = any::<i128>()
4920 .prop_map(|v| Numeric::try_from(v).unwrap())
4921 .boxed();
4922 let float_value = (-1e39f64..1e39)
4923 .prop_map(|v| Numeric::try_from(v).unwrap())
4924 .boxed();
4925
4926 let tiny_floats = ((-10.0..10.0), (1u32..10))
4929 .prop_map(|(v, num_digits)| {
4930 let num_digits: f64 = 10u32.pow(num_digits).try_into().unwrap();
4932 let trunc = f64::trunc(v * num_digits) / num_digits;
4933 Numeric::try_from(trunc).unwrap()
4934 })
4935 .boxed();
4936 let small_ints = (-1_000_000..1_000_000)
4937 .prop_map(|v| Numeric::try_from(v).unwrap())
4938 .boxed();
4939 let small_floats = (-1_000_000.0..1_000_000.0)
4940 .prop_map(|v| Numeric::try_from(v).unwrap())
4941 .boxed();
4942
4943 Union::new_weighted(vec![
4944 (20, tiny_floats),
4945 (20, small_ints),
4946 (20, small_floats),
4947 (10, int_value),
4948 (10, float_value),
4949 (1, Just(Numeric::infinity()).boxed()),
4950 (1, Just(-Numeric::infinity()).boxed()),
4951 (1, Just(Numeric::nan()).boxed()),
4952 (1, Just(Numeric::zero()).boxed()),
4953 ])
4954 .boxed()
4955}
4956
4957impl<'a> From<&'a PropDatum> for Datum<'a> {
4958 #[inline]
4959 fn from(pd: &'a PropDatum) -> Self {
4960 use PropDatum::*;
4961 match pd {
4962 Null => Datum::Null,
4963 Bool(b) => Datum::from(*b),
4964 Int16(i) => Datum::from(*i),
4965 Int32(i) => Datum::from(*i),
4966 Int64(i) => Datum::from(*i),
4967 UInt8(u) => Datum::from(*u),
4968 UInt16(u) => Datum::from(*u),
4969 UInt32(u) => Datum::from(*u),
4970 UInt64(u) => Datum::from(*u),
4971 Float32(f) => Datum::from(*f),
4972 Float64(f) => Datum::from(*f),
4973 Date(d) => Datum::from(*d),
4974 Time(t) => Datum::from(*t),
4975 Timestamp(t) => Datum::from(*t),
4976 TimestampTz(t) => Datum::from(*t),
4977 MzTimestamp(t) => Datum::MzTimestamp((*t).into()),
4978 Interval(i) => Datum::from(*i),
4979 Numeric(s) => Datum::from(*s),
4980 Bytes(b) => Datum::from(&b[..]),
4981 String(s) => Datum::from(s.as_str()),
4982 Array(PropArray(row, _)) => {
4983 let array = row.unpack_first().unwrap_array();
4984 Datum::Array(array)
4985 }
4986 List(PropList(row, _)) => {
4987 let list = row.unpack_first().unwrap_list();
4988 Datum::List(list)
4989 }
4990 Map(PropDict(row, _)) => {
4991 let map = row.unpack_first().unwrap_map();
4992 Datum::Map(map)
4993 }
4994 Record(PropDict(row, _)) => {
4995 let list = row.unpack_first().unwrap_list();
4996 Datum::List(list)
4997 }
4998 Range(PropRange(row, _)) => {
4999 let d = row.unpack_first();
5000 assert!(matches!(d, Datum::Range(_)));
5001 d
5002 }
5003 AclItem(i) => Datum::AclItem(*i),
5004 MzAclItem(i) => Datum::MzAclItem(*i),
5005 JsonNull => Datum::JsonNull,
5006 Uuid(u) => Datum::from(*u),
5007 Dummy => Datum::Dummy,
5008 }
5009 }
5010}
5011
5012#[mz_ore::test]
5013fn verify_base_eq_record_nullability() {
5014 let s1 = SqlScalarType::Record {
5015 fields: [(
5016 "c".into(),
5017 SqlColumnType {
5018 scalar_type: SqlScalarType::Bool,
5019 nullable: true,
5020 },
5021 )]
5022 .into(),
5023 custom_id: None,
5024 };
5025 let s2 = SqlScalarType::Record {
5026 fields: [(
5027 "c".into(),
5028 SqlColumnType {
5029 scalar_type: SqlScalarType::Bool,
5030 nullable: false,
5031 },
5032 )]
5033 .into(),
5034 custom_id: None,
5035 };
5036 let s3 = SqlScalarType::Record {
5037 fields: [].into(),
5038 custom_id: None,
5039 };
5040 assert!(s1.base_eq(&s2));
5041 assert!(!s1.base_eq(&s3));
5042}
5043
5044#[cfg(test)]
5045mod tests {
5046 use mz_ore::assert_ok;
5047 use mz_proto::protobuf_roundtrip;
5048
5049 use super::*;
5050
5051 proptest! {
5052 #[mz_ore::test]
5053 #[cfg_attr(miri, ignore)] fn scalar_type_protobuf_roundtrip(expect in any::<SqlScalarType>() ) {
5055 let actual = protobuf_roundtrip::<_, ProtoScalarType>(&expect);
5056 assert_ok!(actual);
5057 assert_eq!(actual.unwrap(), expect);
5058 }
5059 }
5060
5061 proptest! {
5062 #[mz_ore::test]
5063 #[cfg_attr(miri, ignore)]
5064 fn sql_repr_types_agree_on_valid_data((src, datum) in any::<SqlColumnType>().prop_flat_map(|src| {
5065 let datum = arb_datum_for_column(src.clone());
5066 (Just(src), datum) }
5067 )) {
5068 let tgt = ReprColumnType::from(&src);
5069 let datum = Datum::from(&datum);
5070 assert_eq!(datum.is_instance_of_sql(&src), datum.is_instance_of(&tgt), "translated to repr type {tgt:#?}");
5071 }
5072 }
5073
5074 proptest! {
5075 #![proptest_config(ProptestConfig::with_cases(10000))]
5078 #[mz_ore::test]
5079 #[cfg_attr(miri, ignore)]
5080 fn sql_repr_types_agree_on_random_data(src in any::<SqlColumnType>(), datum in arb_datum()) {
5081 let tgt = ReprColumnType::from(&src);
5082 let datum = Datum::from(&datum);
5083
5084 assert_eq!(datum.is_instance_of_sql(&src), datum.is_instance_of(&tgt), "translated to repr type {tgt:#?}");
5085 }
5086 }
5087
5088 proptest! {
5089 #![proptest_config(ProptestConfig::with_cases(10000))]
5090 #[mz_ore::test]
5091 #[cfg_attr(miri, ignore)]
5092 fn repr_type_to_sql_type_roundtrip(repr_type in any::<ReprScalarType>()) {
5093 let sql_type = SqlScalarType::from_repr(&repr_type);
5098 assert_eq!(repr_type, ReprScalarType::from(&sql_type));
5099 }
5100 }
5101
5102 proptest! {
5103 #![proptest_config(ProptestConfig::with_cases(10000))]
5104 #[mz_ore::test]
5105 #[cfg_attr(miri, ignore)]
5106 fn sql_type_base_eq_implies_repr_type_eq(sql_type1 in any::<SqlScalarType>(), sql_type2 in any::<SqlScalarType>()) {
5107 let repr_type1 = ReprScalarType::from(&sql_type1);
5108 let repr_type2 = ReprScalarType::from(&sql_type2);
5109 if sql_type1.base_eq(&sql_type2) {
5110 assert_eq!(repr_type1, repr_type2);
5111 }
5112 }
5113 }
5114
5115 proptest! {
5116 #[mz_ore::test]
5117 #[cfg_attr(miri, ignore)] fn array_packing_unpacks_correctly(array in arb_array(arb_datum())) {
5119 let PropArray(row, elts) = array;
5120 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
5121 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_array().elements().iter().collect();
5122 assert_eq!(unpacked_datums, datums);
5123 }
5124
5125 #[mz_ore::test]
5126 #[cfg_attr(miri, ignore)] fn list_packing_unpacks_correctly(array in arb_list(arb_datum())) {
5128 let PropList(row, elts) = array;
5129 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
5130 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_list().iter().collect();
5131 assert_eq!(unpacked_datums, datums);
5132 }
5133
5134 #[mz_ore::test]
5135 #[cfg_attr(miri, ignore)] fn dict_packing_unpacks_correctly(array in arb_dict(arb_datum())) {
5137 let PropDict(row, elts) = array;
5138 let datums: Vec<(&str, Datum<'_>)> = elts.iter().map(|(k, e)| (k.as_str(), e.into())).collect();
5139 let unpacked_datums: Vec<(&str, Datum<'_>)> = row.unpack_first().unwrap_map().iter().collect();
5140 assert_eq!(unpacked_datums, datums);
5141 }
5142
5143 #[mz_ore::test]
5144 #[cfg_attr(miri, ignore)] fn row_packing_roundtrips_single_valued(prop_datums in prop::collection::vec(arb_datum(), 1..100)) {
5146 let datums: Vec<Datum<'_>> = prop_datums.iter().map(|pd| pd.into()).collect();
5147 let row = Row::pack(&datums);
5148 let unpacked = row.unpack();
5149 assert_eq!(datums, unpacked);
5150 }
5151
5152 #[mz_ore::test]
5153 #[cfg_attr(miri, ignore)] fn range_packing_unpacks_correctly(range in arb_range(arb_range_data())) {
5155 let PropRange(row, prop_range) = range;
5156 let row = row.unpack_first();
5157 let d = row.unwrap_range();
5158
5159 let (((prop_lower, prop_lower_inc), (prop_upper, prop_upper_inc)), crate::adt::range::RangeInner {lower, upper}) = match (prop_range, d.inner) {
5160 (Some(prop_values), Some(inner_range)) => (prop_values, inner_range),
5161 (None, None) => return Ok(()),
5162 _ => panic!("inequivalent row packing"),
5163 };
5164
5165 for (prop_bound, prop_bound_inc, inner_bound, inner_bound_inc) in [
5166 (prop_lower, prop_lower_inc, lower.bound, lower.inclusive),
5167 (prop_upper, prop_upper_inc, upper.bound, upper.inclusive),
5168 ] {
5169 assert_eq!(prop_bound_inc, inner_bound_inc);
5170 match (prop_bound, inner_bound) {
5171 (None, None) => continue,
5172 (Some(p), Some(b)) => {
5173 assert_eq!(Datum::from(&*p), b);
5174 }
5175 _ => panic!("inequivalent row packing"),
5176 }
5177 }
5178 }
5179 }
5180}