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