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