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;
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 AsColumnType {
1938 fn as_column_type() -> SqlColumnType;
1940}
1941
1942pub trait InputDatumType<'a, E>: Sized {
1944 fn nullable() -> bool;
1946
1947 fn all_nullable() -> bool {
1953 Self::nullable()
1954 }
1955
1956 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>>;
1959
1960 fn try_from_iter(
1963 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
1964 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
1965 match iter.next() {
1968 Some(next) => Self::try_from_result(next).map_err(|e| e.map(Some)),
1969 None => Err(Ok(None)),
1970 }
1971 }
1972}
1973
1974pub trait OutputDatumType<'a, E>: Sized {
1976 fn nullable() -> bool;
1978
1979 fn fallible() -> bool;
1981
1982 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E>;
1984}
1985
1986#[derive(Debug)]
1989pub struct ArrayRustType<T>(pub Vec<T>);
1990
1991impl<T> From<Vec<T>> for ArrayRustType<T> {
1992 fn from(v: Vec<T>) -> Self {
1993 Self(v)
1994 }
1995}
1996
1997impl<B: ToOwned<Owned: AsColumnType> + ?Sized> AsColumnType for Cow<'_, B> {
1999 fn as_column_type() -> SqlColumnType {
2000 <B::Owned>::as_column_type()
2001 }
2002}
2003
2004impl<'a, E, B: ToOwned + ?Sized> InputDatumType<'a, E> for Cow<'a, B>
2005where
2006 for<'b> B::Owned: InputDatumType<'b, E>,
2007 for<'b> &'b B: InputDatumType<'b, E>,
2008{
2009 fn nullable() -> bool {
2010 B::Owned::nullable()
2011 }
2012 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2013 <&B>::try_from_result(res).map(|b| Cow::Borrowed(b))
2014 }
2015}
2016
2017impl<'a, E, B: ToOwned + ?Sized> OutputDatumType<'a, E> for Cow<'a, B>
2018where
2019 for<'b> B::Owned: OutputDatumType<'b, E>,
2020 for<'b> &'b B: OutputDatumType<'b, E>,
2021{
2022 fn nullable() -> bool {
2023 B::Owned::nullable()
2024 }
2025 fn fallible() -> bool {
2026 B::Owned::fallible()
2027 }
2028 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2029 match self {
2030 Cow::Owned(b) => b.into_result(temp_storage),
2031 Cow::Borrowed(b) => b.into_result(temp_storage),
2032 }
2033 }
2034}
2035
2036impl<B: AsColumnType> AsColumnType for Option<B> {
2037 fn as_column_type() -> SqlColumnType {
2038 B::as_column_type().nullable(true)
2039 }
2040}
2041
2042impl<'a, E, B: InputDatumType<'a, E>> InputDatumType<'a, E> for Option<B> {
2043 fn nullable() -> bool {
2044 true
2045 }
2046 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2047 match res {
2048 Ok(Datum::Null) => Ok(None),
2049 Ok(datum) => B::try_from_result(Ok(datum)).map(Some),
2050 _ => Err(res),
2051 }
2052 }
2053}
2054
2055impl<'a, E, B: OutputDatumType<'a, E>> OutputDatumType<'a, E> for Option<B> {
2056 fn nullable() -> bool {
2057 true
2058 }
2059 fn fallible() -> bool {
2060 false
2061 }
2062 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2063 match self {
2064 Some(inner) => inner.into_result(temp_storage),
2065 None => Ok(Datum::Null),
2066 }
2067 }
2068}
2069
2070impl<E, B: AsColumnType> AsColumnType for Result<B, E> {
2071 fn as_column_type() -> SqlColumnType {
2072 B::as_column_type()
2073 }
2074}
2075
2076impl<'a, E, B: InputDatumType<'a, E>> InputDatumType<'a, E> for Result<B, E> {
2077 fn nullable() -> bool {
2078 B::nullable()
2079 }
2080 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2081 B::try_from_result(res).map(Ok)
2082 }
2083 fn try_from_iter(
2084 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
2085 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
2086 B::try_from_iter(iter).map(Ok)
2087 }
2088}
2089
2090impl<'a, E, B: OutputDatumType<'a, E>> OutputDatumType<'a, E> for Result<B, E> {
2091 fn nullable() -> bool {
2092 B::nullable()
2093 }
2094 fn fallible() -> bool {
2095 true
2096 }
2097 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2098 self.and_then(|inner| inner.into_result(temp_storage))
2099 }
2100}
2101
2102macro_rules! impl_tuple_input_datum_type {
2103 ($($T:ident),+) => {
2104 #[allow(non_snake_case)]
2105 impl<'a, E, $($T: InputDatumType<'a, E>),+> InputDatumType<'a, E> for ($($T,)+) {
2106 fn try_from_result(_res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2107 unimplemented!("Not possible")
2108 }
2109 fn try_from_iter(
2110 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
2111 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
2112 $(
2119 let $T = <$T>::try_from_iter(iter);
2120 )+
2121 $(
2123 let $T = match $T {
2124 Err(Ok(None)) => return Err(Ok(None)),
2125 Err(Ok(Some(datum))) if !datum.is_null() => return Err(Ok(Some(datum))),
2126 els => els,
2127 };
2128 )+
2129 $(
2131 let $T = match $T {
2132 Err(Err(err)) => return Err(Err(err)),
2133 els => els,
2134 };
2135 )+
2136 $(
2138 let $T = $T?;
2139 )+
2140 Ok(($($T,)+))
2141 }
2142 fn nullable() -> bool {
2143 $( <$T>::nullable() )||+
2148 }
2149 fn all_nullable() -> bool {
2150 $( <$T>::nullable() )&&+
2155 }
2156 }
2157 }
2158}
2159
2160impl_tuple_input_datum_type!(T0);
2161impl_tuple_input_datum_type!(T0, T1);
2162impl_tuple_input_datum_type!(T0, T1, T2);
2163impl_tuple_input_datum_type!(T0, T1, T2, T3);
2164impl_tuple_input_datum_type!(T0, T1, T2, T3, T4);
2165impl_tuple_input_datum_type!(T0, T1, T2, T3, T4, T5);
2166
2167#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2169pub struct Variadic<T>(pub Vec<T>);
2170
2171impl<T> From<Vec<T>> for Variadic<T> {
2172 #[inline(always)]
2173 fn from(v: Vec<T>) -> Self {
2174 Self(v)
2175 }
2176}
2177
2178impl<T> std::ops::Deref for Variadic<T> {
2179 type Target = Vec<T>;
2180
2181 #[inline(always)]
2182 fn deref(&self) -> &Self::Target {
2183 &self.0
2184 }
2185}
2186
2187impl<T> IntoIterator for Variadic<T> {
2188 type Item = T;
2189 type IntoIter = std::vec::IntoIter<T>;
2190
2191 #[inline(always)]
2192 fn into_iter(self) -> Self::IntoIter {
2193 self.0.into_iter()
2194 }
2195}
2196
2197impl<'a, T> IntoIterator for &'a Variadic<T> {
2198 type Item = &'a T;
2199 type IntoIter = std::slice::Iter<'a, T>;
2200
2201 #[inline(always)]
2202 fn into_iter(self) -> Self::IntoIter {
2203 (&self.0).into_iter()
2204 }
2205}
2206
2207impl<'a, E, T: InputDatumType<'a, E>> InputDatumType<'a, E> for Variadic<T> {
2208 fn nullable() -> bool {
2209 T::nullable()
2210 }
2211 #[inline]
2212 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2213 Ok(vec![T::try_from_result(res)?].into())
2214 }
2215 #[inline]
2216 fn try_from_iter(
2217 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
2218 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
2219 let mut res = Vec::with_capacity(iter.size_hint().0);
2220 loop {
2221 match T::try_from_iter(iter) {
2222 Ok(t) => res.push(t),
2223 Err(Ok(None)) => break,
2224 Err(err) => return Err(err),
2225 }
2226 }
2227 Ok(Self(res))
2228 }
2229}
2230
2231#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
2233pub struct OptionalArg<T>(pub Option<T>);
2234
2235impl<T> std::ops::Deref for OptionalArg<T> {
2236 type Target = Option<T>;
2237
2238 #[inline(always)]
2239 fn deref(&self) -> &Self::Target {
2240 &self.0
2241 }
2242}
2243
2244impl<T> From<Option<T>> for OptionalArg<T> {
2245 #[inline(always)]
2246 fn from(opt: Option<T>) -> Self {
2247 Self(opt)
2248 }
2249}
2250
2251impl<'a, E, T: InputDatumType<'a, E>> InputDatumType<'a, E> for OptionalArg<T> {
2252 fn nullable() -> bool {
2253 T::nullable()
2254 }
2255 #[inline]
2256 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2257 Ok(Some(T::try_from_result(res)?).into())
2258 }
2259 #[inline]
2260 fn try_from_iter(
2261 iter: &mut impl Iterator<Item = Result<Datum<'a>, E>>,
2262 ) -> Result<Self, Result<Option<Datum<'a>>, E>> {
2263 match iter.next() {
2264 Some(datum) => {
2265 let val = T::try_from_result(datum).map_err(|r| r.map(Some))?;
2266 Ok(Some(val).into())
2267 }
2268 None => Ok(None.into()),
2269 }
2270 }
2271}
2272
2273#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2280pub struct ExcludeNull<B>(B);
2281
2282impl<B: AsColumnType> AsColumnType for ExcludeNull<B> {
2283 fn as_column_type() -> SqlColumnType {
2284 B::as_column_type().nullable(false)
2285 }
2286}
2287
2288impl<'a, E, B: InputDatumType<'a, E>> InputDatumType<'a, E> for ExcludeNull<B> {
2289 fn nullable() -> bool {
2290 false
2291 }
2292 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2293 match res {
2294 Ok(Datum::Null) => Err(Ok(Datum::Null)),
2295 _ => B::try_from_result(res).map(ExcludeNull),
2296 }
2297 }
2298}
2299
2300impl<'a, E, B: OutputDatumType<'a, E>> OutputDatumType<'a, E> for ExcludeNull<B> {
2301 fn nullable() -> bool {
2302 false
2303 }
2304 fn fallible() -> bool {
2305 B::fallible()
2306 }
2307 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2308 self.0.into_result(temp_storage)
2309 }
2310}
2311
2312impl<B> std::ops::Deref for ExcludeNull<B> {
2313 type Target = B;
2314
2315 fn deref(&self) -> &Self::Target {
2316 &self.0
2317 }
2318}
2319
2320macro_rules! impl_datum_type_copy {
2322 ($lt:lifetime, $native:ty, $variant:ident) => {
2323 impl<$lt> AsColumnType for $native {
2324 fn as_column_type() -> SqlColumnType {
2325 SqlScalarType::$variant.nullable(false)
2326 }
2327 }
2328
2329 impl<$lt, E> InputDatumType<$lt, E> for $native {
2330 fn nullable() -> bool {
2331 false
2332 }
2333
2334 fn try_from_result(res: Result<Datum<$lt>, E>) -> Result<Self, Result<Datum<$lt>, E>> {
2335 match res {
2336 Ok(Datum::$variant(f)) => Ok(f.into()),
2337 _ => Err(res),
2338 }
2339 }
2340 }
2341
2342 impl<$lt, E> OutputDatumType<$lt, E> for $native {
2343 fn nullable() -> bool {
2344 false
2345 }
2346
2347 fn fallible() -> bool {
2348 false
2349 }
2350
2351 fn into_result(self, _temp_storage: &$lt RowArena) -> Result<Datum<$lt>, E> {
2352 Ok(Datum::$variant(self.into()))
2353 }
2354 }
2355 };
2356 ($native:ty, $variant:ident) => {
2357 impl_datum_type_copy!('a, $native, $variant);
2358 };
2359}
2360
2361impl_datum_type_copy!(f32, Float32);
2362impl_datum_type_copy!(f64, Float64);
2363impl_datum_type_copy!(i16, Int16);
2364impl_datum_type_copy!(i32, Int32);
2365impl_datum_type_copy!(i64, Int64);
2366impl_datum_type_copy!(u16, UInt16);
2367impl_datum_type_copy!(u32, UInt32);
2368impl_datum_type_copy!(u64, UInt64);
2369impl_datum_type_copy!(Interval, Interval);
2370impl_datum_type_copy!(Date, Date);
2371impl_datum_type_copy!(NaiveTime, Time);
2372impl_datum_type_copy!(Uuid, Uuid);
2373impl_datum_type_copy!('a, &'a str, String);
2374impl_datum_type_copy!('a, &'a [u8], Bytes);
2375impl_datum_type_copy!(crate::Timestamp, MzTimestamp);
2376
2377impl<'a, E> InputDatumType<'a, E> for Datum<'a> {
2378 fn nullable() -> bool {
2379 true
2380 }
2381
2382 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2383 match res {
2384 Ok(datum) => Ok(datum),
2385 _ => Err(res),
2386 }
2387 }
2388}
2389
2390impl<'a, E> OutputDatumType<'a, E> for Datum<'a> {
2391 fn nullable() -> bool {
2392 true
2393 }
2394
2395 fn fallible() -> bool {
2396 false
2397 }
2398
2399 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2400 Ok(self)
2401 }
2402}
2403
2404impl<'a, E> InputDatumType<'a, E> for DatumList<'a> {
2405 fn nullable() -> bool {
2406 false
2407 }
2408
2409 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2410 match res {
2411 Ok(Datum::List(list)) => Ok(list),
2412 _ => Err(res),
2413 }
2414 }
2415}
2416
2417impl<'a, E> OutputDatumType<'a, E> for DatumList<'a> {
2418 fn nullable() -> bool {
2419 false
2420 }
2421
2422 fn fallible() -> bool {
2423 false
2424 }
2425
2426 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2427 Ok(Datum::List(self))
2428 }
2429}
2430
2431impl<'a, E> InputDatumType<'a, E> for Array<'a> {
2432 fn nullable() -> bool {
2433 false
2434 }
2435
2436 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2437 match res {
2438 Ok(Datum::Array(array)) => Ok(array),
2439 _ => Err(res),
2440 }
2441 }
2442}
2443
2444impl<'a, E> OutputDatumType<'a, E> for Array<'a> {
2445 fn nullable() -> bool {
2446 false
2447 }
2448
2449 fn fallible() -> bool {
2450 false
2451 }
2452
2453 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2454 Ok(Datum::Array(self))
2455 }
2456}
2457
2458#[derive(Debug)]
2463pub struct Int2Vector<'a>(pub Array<'a>);
2464
2465impl AsColumnType for Int2Vector<'_> {
2466 fn as_column_type() -> SqlColumnType {
2467 SqlScalarType::Int2Vector.nullable(false)
2468 }
2469}
2470
2471impl<'a, E> InputDatumType<'a, E> for Int2Vector<'a> {
2472 fn nullable() -> bool {
2473 false
2474 }
2475
2476 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2477 match res {
2478 Ok(Datum::Array(array)) => Ok(Int2Vector(array)),
2479 _ => Err(res),
2480 }
2481 }
2482}
2483
2484impl<'a, E> OutputDatumType<'a, E> for Int2Vector<'a> {
2485 fn nullable() -> bool {
2486 false
2487 }
2488
2489 fn fallible() -> bool {
2490 false
2491 }
2492
2493 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2494 Ok(Datum::Array(self.0))
2495 }
2496}
2497
2498impl<'a, E> InputDatumType<'a, E> for DatumMap<'a> {
2499 fn nullable() -> bool {
2500 false
2501 }
2502
2503 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2504 match res {
2505 Ok(Datum::Map(map)) => Ok(map),
2506 _ => Err(res),
2507 }
2508 }
2509}
2510
2511impl<'a, E> OutputDatumType<'a, E> for DatumMap<'a> {
2512 fn nullable() -> bool {
2513 false
2514 }
2515
2516 fn fallible() -> bool {
2517 false
2518 }
2519
2520 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2521 Ok(Datum::Map(self))
2522 }
2523}
2524
2525impl<'a, E> InputDatumType<'a, E> for Range<DatumNested<'a>> {
2526 fn nullable() -> bool {
2527 false
2528 }
2529
2530 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2531 match res {
2532 Ok(Datum::Range(range)) => Ok(range),
2533 _ => Err(res),
2534 }
2535 }
2536}
2537
2538impl<'a, E> OutputDatumType<'a, E> for Range<DatumNested<'a>> {
2539 fn nullable() -> bool {
2540 false
2541 }
2542
2543 fn fallible() -> bool {
2544 false
2545 }
2546
2547 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2548 Ok(Datum::Range(self))
2549 }
2550}
2551
2552impl<'a, E> InputDatumType<'a, E> for Range<Datum<'a>> {
2553 fn nullable() -> bool {
2554 false
2555 }
2556
2557 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2558 match res {
2559 Ok(r @ Datum::Range(..)) => Ok(r.unwrap_range()),
2560 _ => Err(res),
2561 }
2562 }
2563}
2564
2565impl<'a, E> OutputDatumType<'a, E> for Range<Datum<'a>> {
2566 fn nullable() -> bool {
2567 false
2568 }
2569
2570 fn fallible() -> bool {
2571 false
2572 }
2573
2574 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2575 let d =
2576 self.into_bounds(|bound| temp_storage.make_datum_nested(|packer| packer.push(bound)));
2577 Ok(Datum::Range(d))
2578 }
2579}
2580
2581impl AsColumnType for bool {
2582 fn as_column_type() -> SqlColumnType {
2583 SqlScalarType::Bool.nullable(false)
2584 }
2585}
2586
2587impl<'a, E> InputDatumType<'a, E> for bool {
2588 fn nullable() -> bool {
2589 false
2590 }
2591
2592 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2593 match res {
2594 Ok(Datum::True) => Ok(true),
2595 Ok(Datum::False) => Ok(false),
2596 _ => Err(res),
2597 }
2598 }
2599}
2600
2601impl<'a, E> OutputDatumType<'a, E> for bool {
2602 fn nullable() -> bool {
2603 false
2604 }
2605
2606 fn fallible() -> bool {
2607 false
2608 }
2609
2610 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2611 if self {
2612 Ok(Datum::True)
2613 } else {
2614 Ok(Datum::False)
2615 }
2616 }
2617}
2618
2619impl AsColumnType for String {
2620 fn as_column_type() -> SqlColumnType {
2621 SqlScalarType::String.nullable(false)
2622 }
2623}
2624
2625impl<'a, E> InputDatumType<'a, E> for String {
2626 fn nullable() -> bool {
2627 false
2628 }
2629
2630 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2631 match res {
2632 Ok(Datum::String(s)) => Ok(s.to_owned()),
2633 _ => Err(res),
2634 }
2635 }
2636}
2637
2638impl<'a, E> OutputDatumType<'a, E> for String {
2639 fn nullable() -> bool {
2640 false
2641 }
2642
2643 fn fallible() -> bool {
2644 false
2645 }
2646
2647 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2648 Ok(Datum::String(temp_storage.push_string(self)))
2649 }
2650}
2651
2652impl AsColumnType for ArrayRustType<String> {
2653 fn as_column_type() -> SqlColumnType {
2654 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false)
2655 }
2656}
2657
2658impl<'a, E> InputDatumType<'a, E> for ArrayRustType<String> {
2659 fn nullable() -> bool {
2660 false
2661 }
2662
2663 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2664 match res {
2665 Ok(Datum::Array(arr)) => Ok(ArrayRustType(
2666 arr.elements()
2667 .into_iter()
2668 .map(|d| d.unwrap_str().to_string())
2669 .collect(),
2670 )),
2671 _ => Err(res),
2672 }
2673 }
2674}
2675
2676impl<'a, E> OutputDatumType<'a, E> for ArrayRustType<String> {
2677 fn nullable() -> bool {
2678 false
2679 }
2680
2681 fn fallible() -> bool {
2682 false
2683 }
2684
2685 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2686 Ok(temp_storage.make_datum(|packer| {
2687 packer
2688 .try_push_array(
2689 &[ArrayDimension {
2690 lower_bound: 1,
2691 length: self.0.len(),
2692 }],
2693 self.0.iter().map(|elem| Datum::String(elem.as_str())),
2694 )
2695 .expect("self is 1 dimensional, and its length is used for the array length");
2696 }))
2697 }
2698}
2699
2700impl AsColumnType for ArrayRustType<Cow<'_, str>> {
2701 fn as_column_type() -> SqlColumnType {
2702 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false)
2703 }
2704}
2705
2706impl<'a, E> InputDatumType<'a, E> for ArrayRustType<Cow<'a, str>> {
2707 fn nullable() -> bool {
2708 false
2709 }
2710
2711 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2712 match res {
2713 Ok(Datum::Array(arr)) => Ok(ArrayRustType(
2714 arr.elements()
2715 .into_iter()
2716 .map(|d| Cow::Borrowed(d.unwrap_str()))
2717 .collect(),
2718 )),
2719 _ => Err(res),
2720 }
2721 }
2722}
2723
2724impl<'a, E> OutputDatumType<'a, E> for ArrayRustType<Cow<'a, str>> {
2725 fn nullable() -> bool {
2726 false
2727 }
2728
2729 fn fallible() -> bool {
2730 false
2731 }
2732
2733 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2734 Ok(temp_storage.make_datum(|packer| {
2735 packer
2736 .try_push_array(
2737 &[ArrayDimension {
2738 lower_bound: 1,
2739 length: self.0.len(),
2740 }],
2741 self.0.iter().map(|elem| Datum::String(elem.as_ref())),
2742 )
2743 .expect("self is 1 dimensional, and its length is used for the array length");
2744 }))
2745 }
2746}
2747
2748impl AsColumnType for Vec<u8> {
2749 fn as_column_type() -> SqlColumnType {
2750 SqlScalarType::Bytes.nullable(false)
2751 }
2752}
2753
2754impl<'a, E> InputDatumType<'a, E> for Vec<u8> {
2755 fn nullable() -> bool {
2756 false
2757 }
2758
2759 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2760 match res {
2761 Ok(Datum::Bytes(b)) => Ok(b.to_owned()),
2762 _ => Err(res),
2763 }
2764 }
2765}
2766
2767impl<'a, E> OutputDatumType<'a, E> for Vec<u8> {
2768 fn nullable() -> bool {
2769 false
2770 }
2771
2772 fn fallible() -> bool {
2773 false
2774 }
2775
2776 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2777 Ok(Datum::Bytes(temp_storage.push_bytes(self)))
2778 }
2779}
2780
2781impl AsColumnType for Numeric {
2782 fn as_column_type() -> SqlColumnType {
2783 SqlScalarType::Numeric { max_scale: None }.nullable(false)
2784 }
2785}
2786
2787impl<'a, E> InputDatumType<'a, E> for Numeric {
2788 fn nullable() -> bool {
2789 false
2790 }
2791
2792 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2793 match res {
2794 Ok(Datum::Numeric(n)) => Ok(n.into_inner()),
2795 _ => Err(res),
2796 }
2797 }
2798}
2799
2800impl<'a, E> OutputDatumType<'a, E> for Numeric {
2801 fn nullable() -> bool {
2802 false
2803 }
2804
2805 fn fallible() -> bool {
2806 false
2807 }
2808
2809 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2810 Ok(Datum::from(self))
2811 }
2812}
2813
2814impl<'a, E> InputDatumType<'a, E> for OrderedDecimal<Numeric> {
2815 fn nullable() -> bool {
2816 false
2817 }
2818
2819 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2820 match res {
2821 Ok(Datum::Numeric(n)) => Ok(n),
2822 _ => Err(res),
2823 }
2824 }
2825}
2826
2827impl<'a, E> OutputDatumType<'a, E> for OrderedDecimal<Numeric> {
2828 fn nullable() -> bool {
2829 false
2830 }
2831
2832 fn fallible() -> bool {
2833 false
2834 }
2835
2836 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2837 Ok(Datum::from(self))
2838 }
2839}
2840
2841impl AsColumnType for PgLegacyChar {
2842 fn as_column_type() -> SqlColumnType {
2843 SqlScalarType::PgLegacyChar.nullable(false)
2844 }
2845}
2846
2847impl<'a, E> InputDatumType<'a, E> for PgLegacyChar {
2848 fn nullable() -> bool {
2849 false
2850 }
2851
2852 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2853 match res {
2854 Ok(Datum::UInt8(a)) => Ok(PgLegacyChar(a)),
2855 _ => Err(res),
2856 }
2857 }
2858}
2859
2860impl<'a, E> OutputDatumType<'a, E> for PgLegacyChar {
2861 fn nullable() -> bool {
2862 false
2863 }
2864
2865 fn fallible() -> bool {
2866 false
2867 }
2868
2869 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2870 Ok(Datum::UInt8(self.0))
2871 }
2872}
2873
2874impl<S> AsColumnType for PgLegacyName<S>
2875where
2876 S: AsRef<str>,
2877{
2878 fn as_column_type() -> SqlColumnType {
2879 SqlScalarType::PgLegacyName.nullable(false)
2880 }
2881}
2882
2883impl<'a, E> InputDatumType<'a, E> for PgLegacyName<&'a str> {
2884 fn nullable() -> bool {
2885 false
2886 }
2887
2888 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2889 match res {
2890 Ok(Datum::String(a)) => Ok(PgLegacyName(a)),
2891 _ => Err(res),
2892 }
2893 }
2894}
2895
2896impl<'a, E> OutputDatumType<'a, E> for PgLegacyName<&'a str> {
2897 fn nullable() -> bool {
2898 false
2899 }
2900
2901 fn fallible() -> bool {
2902 false
2903 }
2904
2905 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2906 Ok(Datum::String(self.0))
2907 }
2908}
2909
2910impl<'a, E> InputDatumType<'a, E> for PgLegacyName<String> {
2911 fn nullable() -> bool {
2912 false
2913 }
2914
2915 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2916 match res {
2917 Ok(Datum::String(a)) => Ok(PgLegacyName(a.to_owned())),
2918 _ => Err(res),
2919 }
2920 }
2921}
2922
2923impl<'a, E> OutputDatumType<'a, E> for PgLegacyName<String> {
2924 fn nullable() -> bool {
2925 false
2926 }
2927
2928 fn fallible() -> bool {
2929 false
2930 }
2931
2932 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2933 Ok(Datum::String(temp_storage.push_string(self.0)))
2934 }
2935}
2936
2937impl AsColumnType for Oid {
2938 fn as_column_type() -> SqlColumnType {
2939 SqlScalarType::Oid.nullable(false)
2940 }
2941}
2942
2943impl<'a, E> InputDatumType<'a, E> for Oid {
2944 fn nullable() -> bool {
2945 false
2946 }
2947
2948 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2949 match res {
2950 Ok(Datum::UInt32(a)) => Ok(Oid(a)),
2951 _ => Err(res),
2952 }
2953 }
2954}
2955
2956impl<'a, E> OutputDatumType<'a, E> for Oid {
2957 fn nullable() -> bool {
2958 false
2959 }
2960
2961 fn fallible() -> bool {
2962 false
2963 }
2964
2965 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2966 Ok(Datum::UInt32(self.0))
2967 }
2968}
2969
2970impl AsColumnType for RegClass {
2971 fn as_column_type() -> SqlColumnType {
2972 SqlScalarType::RegClass.nullable(false)
2973 }
2974}
2975
2976impl<'a, E> InputDatumType<'a, E> for RegClass {
2977 fn nullable() -> bool {
2978 false
2979 }
2980
2981 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2982 match res {
2983 Ok(Datum::UInt32(a)) => Ok(RegClass(a)),
2984 _ => Err(res),
2985 }
2986 }
2987}
2988
2989impl<'a, E> OutputDatumType<'a, E> for RegClass {
2990 fn nullable() -> bool {
2991 false
2992 }
2993
2994 fn fallible() -> bool {
2995 false
2996 }
2997
2998 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2999 Ok(Datum::UInt32(self.0))
3000 }
3001}
3002
3003impl AsColumnType for RegProc {
3004 fn as_column_type() -> SqlColumnType {
3005 SqlScalarType::RegProc.nullable(false)
3006 }
3007}
3008
3009impl<'a, E> InputDatumType<'a, E> for RegProc {
3010 fn nullable() -> bool {
3011 false
3012 }
3013
3014 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3015 match res {
3016 Ok(Datum::UInt32(a)) => Ok(RegProc(a)),
3017 _ => Err(res),
3018 }
3019 }
3020}
3021
3022impl<'a, E> OutputDatumType<'a, E> for RegProc {
3023 fn nullable() -> bool {
3024 false
3025 }
3026
3027 fn fallible() -> bool {
3028 false
3029 }
3030
3031 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3032 Ok(Datum::UInt32(self.0))
3033 }
3034}
3035
3036impl AsColumnType for RegType {
3037 fn as_column_type() -> SqlColumnType {
3038 SqlScalarType::RegType.nullable(false)
3039 }
3040}
3041
3042impl<'a, E> InputDatumType<'a, E> for RegType {
3043 fn nullable() -> bool {
3044 false
3045 }
3046
3047 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3048 match res {
3049 Ok(Datum::UInt32(a)) => Ok(RegType(a)),
3050 _ => Err(res),
3051 }
3052 }
3053}
3054
3055impl<'a, E> OutputDatumType<'a, E> for RegType {
3056 fn nullable() -> bool {
3057 false
3058 }
3059
3060 fn fallible() -> bool {
3061 false
3062 }
3063
3064 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3065 Ok(Datum::UInt32(self.0))
3066 }
3067}
3068
3069impl<S> AsColumnType for Char<S>
3070where
3071 S: AsRef<str>,
3072{
3073 fn as_column_type() -> SqlColumnType {
3074 SqlScalarType::Char { length: None }.nullable(false)
3075 }
3076}
3077
3078impl<'a, E> InputDatumType<'a, E> for Char<&'a str> {
3079 fn nullable() -> bool {
3080 false
3081 }
3082
3083 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3084 match res {
3085 Ok(Datum::String(a)) => Ok(Char(a)),
3086 _ => Err(res),
3087 }
3088 }
3089}
3090
3091impl<'a, E> OutputDatumType<'a, E> for Char<&'a str> {
3092 fn nullable() -> bool {
3093 false
3094 }
3095
3096 fn fallible() -> bool {
3097 false
3098 }
3099
3100 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3101 Ok(Datum::String(self.0))
3102 }
3103}
3104
3105impl<'a, E> InputDatumType<'a, E> for Char<String> {
3106 fn nullable() -> bool {
3107 false
3108 }
3109
3110 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3111 match res {
3112 Ok(Datum::String(a)) => Ok(Char(a.to_owned())),
3113 _ => Err(res),
3114 }
3115 }
3116}
3117
3118impl<'a, E> OutputDatumType<'a, E> for Char<String> {
3119 fn nullable() -> bool {
3120 false
3121 }
3122
3123 fn fallible() -> bool {
3124 false
3125 }
3126
3127 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3128 Ok(Datum::String(temp_storage.push_string(self.0)))
3129 }
3130}
3131
3132impl<S> AsColumnType for VarChar<S>
3133where
3134 S: AsRef<str>,
3135{
3136 fn as_column_type() -> SqlColumnType {
3137 SqlScalarType::Char { length: None }.nullable(false)
3138 }
3139}
3140
3141impl<'a, E> InputDatumType<'a, E> for VarChar<&'a str> {
3142 fn nullable() -> bool {
3143 false
3144 }
3145
3146 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3147 match res {
3148 Ok(Datum::String(a)) => Ok(VarChar(a)),
3149 _ => Err(res),
3150 }
3151 }
3152}
3153
3154impl<'a, E> OutputDatumType<'a, E> for VarChar<&'a str> {
3155 fn nullable() -> bool {
3156 false
3157 }
3158
3159 fn fallible() -> bool {
3160 false
3161 }
3162
3163 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3164 Ok(Datum::String(self.0))
3165 }
3166}
3167
3168impl<'a, E> InputDatumType<'a, E> for VarChar<String> {
3169 fn nullable() -> bool {
3170 false
3171 }
3172
3173 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3174 match res {
3175 Ok(Datum::String(a)) => Ok(VarChar(a.to_owned())),
3176 _ => Err(res),
3177 }
3178 }
3179}
3180
3181impl<'a, E> OutputDatumType<'a, E> for VarChar<String> {
3182 fn nullable() -> bool {
3183 false
3184 }
3185
3186 fn fallible() -> bool {
3187 false
3188 }
3189
3190 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3191 Ok(Datum::String(temp_storage.push_string(self.0)))
3192 }
3193}
3194
3195impl<'a, E> InputDatumType<'a, E> for Jsonb {
3196 fn nullable() -> bool {
3197 false
3198 }
3199
3200 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3201 Ok(JsonbRef::try_from_result(res)?.to_owned())
3202 }
3203}
3204
3205impl<'a, E> OutputDatumType<'a, E> for Jsonb {
3206 fn nullable() -> bool {
3207 false
3208 }
3209
3210 fn fallible() -> bool {
3211 false
3212 }
3213
3214 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3215 Ok(temp_storage.push_unary_row(self.into_row()))
3216 }
3217}
3218
3219impl AsColumnType for Jsonb {
3220 fn as_column_type() -> SqlColumnType {
3221 SqlScalarType::Jsonb.nullable(false)
3222 }
3223}
3224
3225impl<'a, E> InputDatumType<'a, E> for JsonbRef<'a> {
3226 fn nullable() -> bool {
3227 false
3228 }
3229
3230 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3231 match res {
3232 Ok(
3233 d @ (Datum::JsonNull
3234 | Datum::True
3235 | Datum::False
3236 | Datum::Numeric(_)
3237 | Datum::String(_)
3238 | Datum::List(_)
3239 | Datum::Map(_)),
3240 ) => Ok(JsonbRef::from_datum(d)),
3241 _ => Err(res),
3242 }
3243 }
3244}
3245
3246impl<'a, E> OutputDatumType<'a, E> for JsonbRef<'a> {
3247 fn nullable() -> bool {
3248 false
3249 }
3250
3251 fn fallible() -> bool {
3252 false
3253 }
3254
3255 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3256 Ok(self.into_datum())
3257 }
3258}
3259
3260impl<'a> AsColumnType for JsonbRef<'a> {
3261 fn as_column_type() -> SqlColumnType {
3262 SqlScalarType::Jsonb.nullable(false)
3263 }
3264}
3265
3266impl AsColumnType for MzAclItem {
3267 fn as_column_type() -> SqlColumnType {
3268 SqlScalarType::MzAclItem.nullable(false)
3269 }
3270}
3271
3272impl<'a, E> InputDatumType<'a, E> for MzAclItem {
3273 fn nullable() -> bool {
3274 false
3275 }
3276
3277 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3278 match res {
3279 Ok(Datum::MzAclItem(mz_acl_item)) => Ok(mz_acl_item),
3280 _ => Err(res),
3281 }
3282 }
3283}
3284
3285impl<'a, E> OutputDatumType<'a, E> for MzAclItem {
3286 fn nullable() -> bool {
3287 false
3288 }
3289
3290 fn fallible() -> bool {
3291 false
3292 }
3293
3294 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3295 Ok(Datum::MzAclItem(self))
3296 }
3297}
3298
3299impl AsColumnType for AclItem {
3300 fn as_column_type() -> SqlColumnType {
3301 SqlScalarType::AclItem.nullable(false)
3302 }
3303}
3304
3305impl<'a, E> InputDatumType<'a, E> for AclItem {
3306 fn nullable() -> bool {
3307 false
3308 }
3309
3310 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3311 match res {
3312 Ok(Datum::AclItem(acl_item)) => Ok(acl_item),
3313 _ => Err(res),
3314 }
3315 }
3316}
3317
3318impl<'a, E> OutputDatumType<'a, E> for AclItem {
3319 fn nullable() -> bool {
3320 false
3321 }
3322
3323 fn fallible() -> bool {
3324 false
3325 }
3326
3327 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3328 Ok(Datum::AclItem(self))
3329 }
3330}
3331
3332impl AsColumnType for CheckedTimestamp<NaiveDateTime> {
3333 fn as_column_type() -> SqlColumnType {
3334 SqlScalarType::Timestamp { precision: None }.nullable(false)
3335 }
3336}
3337
3338impl<'a, E> InputDatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
3339 fn nullable() -> bool {
3340 false
3341 }
3342
3343 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3344 match res {
3345 Ok(Datum::Timestamp(a)) => Ok(a),
3346 _ => Err(res),
3347 }
3348 }
3349}
3350
3351impl<'a, E> OutputDatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
3352 fn nullable() -> bool {
3353 false
3354 }
3355
3356 fn fallible() -> bool {
3357 false
3358 }
3359
3360 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3361 Ok(Datum::Timestamp(self))
3362 }
3363}
3364
3365impl AsColumnType for CheckedTimestamp<DateTime<Utc>> {
3366 fn as_column_type() -> SqlColumnType {
3367 SqlScalarType::TimestampTz { precision: None }.nullable(false)
3368 }
3369}
3370
3371impl<'a, E> InputDatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
3372 fn nullable() -> bool {
3373 false
3374 }
3375
3376 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
3377 match res {
3378 Ok(Datum::TimestampTz(a)) => Ok(a),
3379 _ => Err(res),
3380 }
3381 }
3382}
3383
3384impl<'a, E> OutputDatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
3385 fn nullable() -> bool {
3386 false
3387 }
3388
3389 fn fallible() -> bool {
3390 false
3391 }
3392
3393 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
3394 Ok(Datum::TimestampTz(self))
3395 }
3396}
3397
3398impl SqlScalarType {
3399 pub fn unwrap_numeric_max_scale(&self) -> Option<NumericMaxScale> {
3405 match self {
3406 SqlScalarType::Numeric { max_scale } => *max_scale,
3407 _ => panic!("SqlScalarType::unwrap_numeric_scale called on {:?}", self),
3408 }
3409 }
3410
3411 pub fn unwrap_timestamp_precision(&self) -> Option<TimestampPrecision> {
3418 match self {
3419 SqlScalarType::Timestamp { precision } | SqlScalarType::TimestampTz { precision } => {
3420 *precision
3421 }
3422 _ => panic!(
3423 "SqlScalarType::unwrap_timestamp_precision called on {:?}",
3424 self
3425 ),
3426 }
3427 }
3428
3429 pub fn unwrap_list_element_type(&self) -> &SqlScalarType {
3435 match self {
3436 SqlScalarType::List { element_type, .. } => element_type,
3437 _ => panic!(
3438 "SqlScalarType::unwrap_list_element_type called on {:?}",
3439 self
3440 ),
3441 }
3442 }
3443
3444 pub fn unwrap_list_nth_layer_type(&self, layer: usize) -> &SqlScalarType {
3457 if layer == 0 {
3458 return self;
3459 }
3460 match self {
3461 SqlScalarType::List { element_type, .. } => {
3462 element_type.unwrap_list_nth_layer_type(layer - 1)
3463 }
3464 _ => panic!(
3465 "SqlScalarType::unwrap_list_nth_layer_type called on {:?}",
3466 self
3467 ),
3468 }
3469 }
3470
3471 pub fn unwrap_record_element_type(&self) -> Vec<&SqlScalarType> {
3477 match self {
3478 SqlScalarType::Record { fields, .. } => {
3479 fields.iter().map(|(_, t)| &t.scalar_type).collect_vec()
3480 }
3481 _ => panic!(
3482 "SqlScalarType::unwrap_record_element_type called on {:?}",
3483 self
3484 ),
3485 }
3486 }
3487
3488 pub fn unwrap_record_element_column_type(&self) -> Vec<&SqlColumnType> {
3494 match self {
3495 SqlScalarType::Record { fields, .. } => fields.iter().map(|(_, t)| t).collect_vec(),
3496 _ => panic!(
3497 "SqlScalarType::unwrap_record_element_column_type called on {:?}",
3498 self
3499 ),
3500 }
3501 }
3502
3503 pub fn unwrap_list_n_layers(&self) -> usize {
3510 let mut descender = self.unwrap_list_element_type();
3511 let mut layers = 1;
3512
3513 while let SqlScalarType::List { element_type, .. } = descender {
3514 layers += 1;
3515 descender = element_type;
3516 }
3517
3518 layers
3519 }
3520
3521 pub fn without_modifiers(&self) -> SqlScalarType {
3525 use SqlScalarType::*;
3526 match self {
3527 List {
3528 element_type,
3529 custom_id: None,
3530 } => List {
3531 element_type: Box::new(element_type.without_modifiers()),
3532 custom_id: None,
3533 },
3534 Map {
3535 value_type,
3536 custom_id: None,
3537 } => Map {
3538 value_type: Box::new(value_type.without_modifiers()),
3539 custom_id: None,
3540 },
3541 Record {
3542 fields,
3543 custom_id: None,
3544 } => {
3545 let fields = fields
3546 .iter()
3547 .map(|(column_name, column_type)| {
3548 (
3549 column_name.clone(),
3550 SqlColumnType {
3551 scalar_type: column_type.scalar_type.without_modifiers(),
3552 nullable: column_type.nullable,
3553 },
3554 )
3555 })
3556 .collect();
3557 Record {
3558 fields,
3559 custom_id: None,
3560 }
3561 }
3562 Array(a) => Array(Box::new(a.without_modifiers())),
3563 Numeric { .. } => Numeric { max_scale: None },
3564 Char { .. } => Char { length: None },
3567 VarChar { .. } => VarChar { max_length: None },
3568 Range { element_type } => Range {
3569 element_type: Box::new(element_type.without_modifiers()),
3570 },
3571 v => v.clone(),
3572 }
3573 }
3574
3575 pub fn unwrap_array_element_type(&self) -> &SqlScalarType {
3584 match self {
3585 SqlScalarType::Array(s) => &**s,
3586 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3587 _ => panic!(
3588 "SqlScalarType::unwrap_array_element_type called on {:?}",
3589 self
3590 ),
3591 }
3592 }
3593
3594 pub fn unwrap_collection_element_type(&self) -> &SqlScalarType {
3602 match self {
3603 SqlScalarType::Array(element_type) => element_type,
3604 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3605 SqlScalarType::List { element_type, .. } => element_type,
3606 _ => panic!(
3607 "SqlScalarType::unwrap_collection_element_type called on {:?}",
3608 self
3609 ),
3610 }
3611 }
3612
3613 pub fn unwrap_map_value_type(&self) -> &SqlScalarType {
3619 match self {
3620 SqlScalarType::Map { value_type, .. } => &**value_type,
3621 _ => panic!("SqlScalarType::unwrap_map_value_type called on {:?}", self),
3622 }
3623 }
3624
3625 pub fn unwrap_char_length(&self) -> Option<CharLength> {
3631 match self {
3632 SqlScalarType::Char { length, .. } => *length,
3633 _ => panic!("SqlScalarType::unwrap_char_length called on {:?}", self),
3634 }
3635 }
3636
3637 pub fn unwrap_varchar_max_length(&self) -> Option<VarCharMaxLength> {
3643 match self {
3644 SqlScalarType::VarChar { max_length, .. } => *max_length,
3645 _ => panic!(
3646 "SqlScalarType::unwrap_varchar_max_length called on {:?}",
3647 self
3648 ),
3649 }
3650 }
3651
3652 pub fn unwrap_range_element_type(&self) -> &SqlScalarType {
3658 match self {
3659 SqlScalarType::Range { element_type } => &**element_type,
3660 _ => panic!(
3661 "SqlScalarType::unwrap_range_element_type called on {:?}",
3662 self
3663 ),
3664 }
3665 }
3666
3667 pub fn near_match(&self) -> Option<&'static SqlScalarType> {
3691 match self {
3692 SqlScalarType::UInt16 => Some(&SqlScalarType::Int32),
3693 SqlScalarType::UInt32 => Some(&SqlScalarType::Int64),
3694 SqlScalarType::UInt64 => Some(&SqlScalarType::Numeric { max_scale: None }),
3695 _ => None,
3696 }
3697 }
3698
3699 pub const fn nullable(self, nullable: bool) -> SqlColumnType {
3702 SqlColumnType {
3703 nullable,
3704 scalar_type: self,
3705 }
3706 }
3707
3708 pub fn is_vec(&self) -> bool {
3712 matches!(
3713 self,
3714 SqlScalarType::Array(_) | SqlScalarType::Int2Vector | SqlScalarType::List { .. }
3715 )
3716 }
3717
3718 pub fn is_custom_type(&self) -> bool {
3719 use SqlScalarType::*;
3720 match self {
3721 List {
3722 element_type: t,
3723 custom_id,
3724 }
3725 | Map {
3726 value_type: t,
3727 custom_id,
3728 } => custom_id.is_some() || t.is_custom_type(),
3729 Record {
3730 fields, custom_id, ..
3731 } => {
3732 custom_id.is_some()
3733 || fields
3734 .iter()
3735 .map(|(_, t)| t)
3736 .any(|t| t.scalar_type.is_custom_type())
3737 }
3738 _ => false,
3739 }
3740 }
3741
3742 pub fn base_eq(&self, other: &SqlScalarType) -> bool {
3755 self.eq_inner(other, false)
3756 }
3757
3758 pub fn structural_eq(&self, other: &SqlScalarType) -> bool {
3761 self.eq_inner(other, true)
3762 }
3763
3764 pub fn eq_inner(&self, other: &SqlScalarType, structure_only: bool) -> bool {
3765 use SqlScalarType::*;
3766 match (self, other) {
3767 (
3768 List {
3769 element_type: l,
3770 custom_id: oid_l,
3771 },
3772 List {
3773 element_type: r,
3774 custom_id: oid_r,
3775 },
3776 )
3777 | (
3778 Map {
3779 value_type: l,
3780 custom_id: oid_l,
3781 },
3782 Map {
3783 value_type: r,
3784 custom_id: oid_r,
3785 },
3786 ) => l.eq_inner(r, structure_only) && (oid_l == oid_r || structure_only),
3787 (Array(a), Array(b)) | (Range { element_type: a }, Range { element_type: b }) => {
3788 a.eq_inner(b, structure_only)
3789 }
3790 (
3791 Record {
3792 fields: fields_a,
3793 custom_id: oid_a,
3794 },
3795 Record {
3796 fields: fields_b,
3797 custom_id: oid_b,
3798 },
3799 ) => {
3800 (oid_a == oid_b || structure_only)
3801 && fields_a.len() == fields_b.len()
3802 && fields_a
3803 .iter()
3804 .zip_eq(fields_b)
3805 .all(|(a, b)| {
3807 (a.0 == b.0 || structure_only)
3808 && a.1.scalar_type.eq_inner(&b.1.scalar_type, structure_only)
3809 })
3810 }
3811 (s, o) => SqlScalarBaseType::from(s) == SqlScalarBaseType::from(o),
3812 }
3813 }
3814
3815 pub fn backport_nullability(&mut self, backport_typ: &ReprScalarType) {
3818 match (self, backport_typ) {
3819 (
3820 SqlScalarType::List { element_type, .. },
3821 ReprScalarType::List {
3822 element_type: backport_element_type,
3823 ..
3824 },
3825 ) => {
3826 element_type.backport_nullability(backport_element_type);
3827 }
3828 (
3829 SqlScalarType::Map { value_type, .. },
3830 ReprScalarType::Map {
3831 value_type: backport_value_type,
3832 ..
3833 },
3834 ) => {
3835 value_type.backport_nullability(backport_value_type);
3836 }
3837 (
3838 SqlScalarType::Record { fields, .. },
3839 ReprScalarType::Record {
3840 fields: backport_fields,
3841 ..
3842 },
3843 ) => {
3844 assert_eq!(
3845 fields.len(),
3846 backport_fields.len(),
3847 "HIR and MIR types should have the same number of fields"
3848 );
3849 fields
3850 .iter_mut()
3851 .zip_eq(backport_fields)
3852 .for_each(|(field, backport_field)| {
3853 field.1.backport_nullability(backport_field);
3854 });
3855 }
3856 (SqlScalarType::Array(a), ReprScalarType::Array(b)) => {
3857 a.backport_nullability(b);
3858 }
3859 (
3860 SqlScalarType::Range { element_type },
3861 ReprScalarType::Range {
3862 element_type: backport_element_type,
3863 },
3864 ) => {
3865 element_type.backport_nullability(backport_element_type);
3866 }
3867 _ => (),
3868 }
3869 }
3870
3871 pub fn interesting_datums(&self) -> impl Iterator<Item = Datum<'static>> {
3873 static BOOL: LazyLock<Row> =
3879 LazyLock::new(|| Row::pack_slice(&[Datum::True, Datum::False]));
3880 static INT16: LazyLock<Row> = LazyLock::new(|| {
3881 Row::pack_slice(&[
3882 Datum::Int16(0),
3883 Datum::Int16(1),
3884 Datum::Int16(-1),
3885 Datum::Int16(i16::MIN),
3886 Datum::Int16(i16::MIN + 1),
3887 Datum::Int16(i16::MAX),
3888 Datum::Int16(127),
3896 Datum::Int16(128),
3897 ])
3898 });
3899 static INT32: LazyLock<Row> = LazyLock::new(|| {
3900 Row::pack_slice(&[
3901 Datum::Int32(0),
3902 Datum::Int32(1),
3903 Datum::Int32(-1),
3904 Datum::Int32(i32::MIN),
3905 Datum::Int32(i32::MIN + 1),
3906 Datum::Int32(i32::MAX),
3907 Datum::Int32(32767),
3911 Datum::Int32(32768),
3912 ])
3913 });
3914 static INT64: LazyLock<Row> = LazyLock::new(|| {
3915 Row::pack_slice(&[
3916 Datum::Int64(0),
3917 Datum::Int64(1),
3918 Datum::Int64(-1),
3919 Datum::Int64(i64::MIN),
3920 Datum::Int64(i64::MIN + 1),
3921 Datum::Int64(i64::MAX),
3922 Datum::Int64(2147483647),
3926 Datum::Int64(2147483648),
3927 ])
3928 });
3929 static UINT16: LazyLock<Row> = LazyLock::new(|| {
3930 Row::pack_slice(&[
3931 Datum::UInt16(0),
3932 Datum::UInt16(1),
3933 Datum::UInt16(u16::MAX),
3934 Datum::UInt16(255),
3938 Datum::UInt16(256),
3939 ])
3940 });
3941 static UINT32: LazyLock<Row> = LazyLock::new(|| {
3942 Row::pack_slice(&[
3943 Datum::UInt32(0),
3944 Datum::UInt32(1),
3945 Datum::UInt32(u32::MAX),
3946 Datum::UInt32(32767),
3950 Datum::UInt32(32768),
3951 ])
3952 });
3953 static UINT64: LazyLock<Row> = LazyLock::new(|| {
3954 Row::pack_slice(&[
3955 Datum::UInt64(0),
3956 Datum::UInt64(1),
3957 Datum::UInt64(u64::MAX),
3958 Datum::UInt64(2147483647),
3962 Datum::UInt64(2147483648),
3963 ])
3964 });
3965 static FLOAT32: LazyLock<Row> = LazyLock::new(|| {
3966 Row::pack_slice(&[
3967 Datum::Float32(OrderedFloat(0.0)),
3968 Datum::Float32(OrderedFloat(1.0)),
3969 Datum::Float32(OrderedFloat(-1.0)),
3970 Datum::Float32(OrderedFloat(f32::MIN)),
3971 Datum::Float32(OrderedFloat(f32::MIN_POSITIVE)),
3972 Datum::Float32(OrderedFloat(f32::MAX)),
3973 Datum::Float32(OrderedFloat(f32::EPSILON)),
3974 Datum::Float32(OrderedFloat(f32::NAN)),
3975 Datum::Float32(OrderedFloat(f32::INFINITY)),
3976 Datum::Float32(OrderedFloat(f32::NEG_INFINITY)),
3977 ])
3978 });
3979 static FLOAT64: LazyLock<Row> = LazyLock::new(|| {
3980 Row::pack_slice(&[
3981 Datum::Float64(OrderedFloat(0.0)),
3982 Datum::Float64(OrderedFloat(1.0)),
3983 Datum::Float64(OrderedFloat(-1.0)),
3984 Datum::Float64(OrderedFloat(f64::MIN)),
3985 Datum::Float64(OrderedFloat(f64::MIN_POSITIVE)),
3986 Datum::Float64(OrderedFloat(f64::MAX)),
3987 Datum::Float64(OrderedFloat(f64::EPSILON)),
3988 Datum::Float64(OrderedFloat(f64::NAN)),
3989 Datum::Float64(OrderedFloat(f64::INFINITY)),
3990 Datum::Float64(OrderedFloat(f64::NEG_INFINITY)),
3991 ])
3992 });
3993 static NUMERIC: LazyLock<Row> = LazyLock::new(|| {
3994 cfg_if::cfg_if! {
3995 if #[cfg(miri)] {
3997 Row::pack_slice(&[])
3998 } else {
3999 Row::pack_slice(&[
4000 Datum::Numeric(OrderedDecimal(Numeric::from(0.0))),
4001 Datum::Numeric(OrderedDecimal(Numeric::from(1.0))),
4002 Datum::Numeric(OrderedDecimal(Numeric::from(-1.0))),
4003 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN))),
4004 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN_POSITIVE))),
4005 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MAX))),
4006 Datum::Numeric(OrderedDecimal(Numeric::from(f64::EPSILON))),
4007 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NAN))),
4008 Datum::Numeric(OrderedDecimal(Numeric::from(f64::INFINITY))),
4009 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NEG_INFINITY))),
4010 ])
4011 }
4012 }
4013 });
4014 static DATE: LazyLock<Row> = LazyLock::new(|| {
4015 Row::pack_slice(&[
4016 Datum::Date(Date::from_pg_epoch(0).unwrap()),
4017 Datum::Date(Date::from_pg_epoch(Date::LOW_DAYS).unwrap()),
4018 Datum::Date(Date::from_pg_epoch(Date::HIGH_DAYS).unwrap()),
4019 ])
4020 });
4021 static TIME: LazyLock<Row> = LazyLock::new(|| {
4022 Row::pack_slice(&[
4023 Datum::Time(NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap()),
4024 Datum::Time(NaiveTime::from_hms_micro_opt(23, 59, 59, 999_999).unwrap()),
4025 ])
4026 });
4027 static TIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
4028 Row::pack_slice(&[
4029 Datum::Timestamp(
4030 DateTime::from_timestamp(0, 0)
4031 .unwrap()
4032 .naive_utc()
4033 .try_into()
4034 .unwrap(),
4035 ),
4036 Datum::Timestamp(
4037 crate::adt::timestamp::LOW_DATE
4038 .and_hms_opt(0, 0, 0)
4039 .unwrap()
4040 .try_into()
4041 .unwrap(),
4042 ),
4043 Datum::Timestamp(
4044 crate::adt::timestamp::HIGH_DATE
4045 .and_hms_opt(23, 59, 59)
4046 .unwrap()
4047 .try_into()
4048 .unwrap(),
4049 ),
4050 Datum::Timestamp(
4052 DateTime::from_timestamp(0, 123456789)
4053 .unwrap()
4054 .naive_utc()
4055 .try_into()
4056 .unwrap(),
4057 ),
4058 Datum::Timestamp(
4060 CheckedTimestamp::from_timestamplike(
4061 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
4062 .unwrap()
4063 .and_hms_milli_opt(23, 59, 59, 1234)
4064 .unwrap(),
4065 )
4066 .unwrap(),
4067 ),
4068 ])
4069 });
4070 static TIMESTAMPTZ: LazyLock<Row> = LazyLock::new(|| {
4071 Row::pack_slice(&[
4072 Datum::TimestampTz(DateTime::from_timestamp(0, 0).unwrap().try_into().unwrap()),
4073 Datum::TimestampTz(
4074 DateTime::from_naive_utc_and_offset(
4075 crate::adt::timestamp::LOW_DATE
4076 .and_hms_opt(0, 0, 0)
4077 .unwrap(),
4078 Utc,
4079 )
4080 .try_into()
4081 .unwrap(),
4082 ),
4083 Datum::TimestampTz(
4084 DateTime::from_naive_utc_and_offset(
4085 crate::adt::timestamp::HIGH_DATE
4086 .and_hms_opt(23, 59, 59)
4087 .unwrap(),
4088 Utc,
4089 )
4090 .try_into()
4091 .unwrap(),
4092 ),
4093 Datum::TimestampTz(
4095 DateTime::from_timestamp(0, 123456789)
4096 .unwrap()
4097 .try_into()
4098 .unwrap(),
4099 ),
4100 ])
4101 });
4102 static INTERVAL: LazyLock<Row> = LazyLock::new(|| {
4103 Row::pack_slice(&[
4104 Datum::Interval(Interval::new(0, 0, 0)),
4105 Datum::Interval(Interval::new(1, 1, 1)),
4106 Datum::Interval(Interval::new(-1, -1, -1)),
4107 Datum::Interval(Interval::new(1, 0, 0)),
4108 Datum::Interval(Interval::new(0, 1, 0)),
4109 Datum::Interval(Interval::new(0, 0, 1)),
4110 Datum::Interval(Interval::new(-1, 0, 0)),
4111 Datum::Interval(Interval::new(0, -1, 0)),
4112 Datum::Interval(Interval::new(0, 0, -1)),
4113 Datum::Interval(Interval::new(i32::MIN, i32::MIN, i64::MIN)),
4114 Datum::Interval(Interval::new(i32::MAX, i32::MAX, i64::MAX)),
4115 Datum::Interval(Interval::new(i32::MIN, 0, 0)),
4116 Datum::Interval(Interval::new(i32::MAX, 0, 0)),
4117 Datum::Interval(Interval::new(0, i32::MIN, 0)),
4118 Datum::Interval(Interval::new(0, i32::MAX, 0)),
4119 Datum::Interval(Interval::new(0, 0, i64::MIN)),
4120 Datum::Interval(Interval::new(0, 0, i64::MAX)),
4121 ])
4122 });
4123 static PGLEGACYCHAR: LazyLock<Row> =
4124 LazyLock::new(|| Row::pack_slice(&[Datum::UInt8(u8::MIN), Datum::UInt8(u8::MAX)]));
4125 static PGLEGACYNAME: LazyLock<Row> = LazyLock::new(|| {
4126 Row::pack_slice(&[
4127 Datum::String(""),
4128 Datum::String(" "),
4129 Datum::String("'"),
4130 Datum::String("\""),
4131 Datum::String("."),
4132 Datum::String(&"x".repeat(64)),
4133 ])
4134 });
4135 static BYTES: LazyLock<Row> = LazyLock::new(|| {
4136 Row::pack_slice(&[Datum::Bytes(&[]), Datum::Bytes(&[0]), Datum::Bytes(&[255])])
4137 });
4138 static STRING: LazyLock<Row> = LazyLock::new(|| {
4139 Row::pack_slice(&[
4140 Datum::String(""),
4141 Datum::String(" "),
4142 Datum::String("'"),
4143 Datum::String("\""),
4144 Datum::String("."),
4145 Datum::String("2015-09-18T23:56:04.123Z"),
4146 Datum::String(&"x".repeat(100)),
4147 Datum::String("JAPAN"),
4149 Datum::String("1,2,3"),
4150 Datum::String("\r\n"),
4151 Datum::String("\"\""),
4152 ])
4153 });
4154 static CHAR: LazyLock<Row> = LazyLock::new(|| {
4155 Row::pack_slice(&[
4156 Datum::String(" "),
4157 Datum::String("'"),
4158 Datum::String("\""),
4159 Datum::String("."),
4160 Datum::String(","),
4161 Datum::String("\t"),
4162 Datum::String("\n"),
4163 Datum::String("\r"),
4164 Datum::String("\\"),
4165 Datum::String(std::str::from_utf8(b"\x00").unwrap()),
4167 Datum::String(std::str::from_utf8(b"\x02").unwrap()),
4169 Datum::String(std::str::from_utf8(b"\x03").unwrap()),
4171 Datum::String(std::str::from_utf8(b"\x08").unwrap()),
4173 Datum::String(std::str::from_utf8(b"\x1B").unwrap()),
4175 Datum::String(std::str::from_utf8(b"\x7F").unwrap()),
4177 ])
4178 });
4179 static JSONB: LazyLock<Row> = LazyLock::new(|| {
4180 let mut datums = vec![Datum::True, Datum::False, Datum::JsonNull];
4181 datums.extend(STRING.iter());
4182 datums.extend(NUMERIC.iter().filter(|n| {
4183 let Datum::Numeric(n) = n else {
4184 panic!("expected Numeric, found {n:?}");
4185 };
4186 !(n.0.is_nan() || n.0.is_infinite())
4188 }));
4189 Row::pack_slice(&datums)
4191 });
4192 static UUID: LazyLock<Row> = LazyLock::new(|| {
4193 Row::pack_slice(&[
4194 Datum::Uuid(Uuid::from_u128(u128::MIN)),
4195 Datum::Uuid(Uuid::from_u128(u128::MAX)),
4196 ])
4197 });
4198 static ARRAY: LazyLock<BTreeMap<&'static SqlScalarType, Row>> = LazyLock::new(|| {
4199 let generate_row = |inner_type: &SqlScalarType| {
4200 let datums: Vec<_> = inner_type.interesting_datums().collect();
4201
4202 let mut row = Row::default();
4203 row.packer()
4204 .try_push_array::<_, Datum<'static>>(
4205 &[ArrayDimension {
4206 lower_bound: 1,
4207 length: 0,
4208 }],
4209 [],
4210 )
4211 .expect("failed to push empty array");
4212 row.packer()
4213 .try_push_array(
4214 &[ArrayDimension {
4215 lower_bound: 1,
4216 length: datums.len(),
4217 }],
4218 datums,
4219 )
4220 .expect("failed to push array");
4221
4222 row
4223 };
4224
4225 SqlScalarType::enumerate()
4226 .into_iter()
4227 .filter(|ty| !matches!(ty, SqlScalarType::Array(_)))
4228 .map(|ty| (ty, generate_row(ty)))
4229 .collect()
4230 });
4231 static EMPTY_ARRAY: LazyLock<Row> = LazyLock::new(|| {
4232 let mut row = Row::default();
4233 row.packer()
4234 .try_push_array::<_, Datum<'static>>(
4235 &[ArrayDimension {
4236 lower_bound: 1,
4237 length: 0,
4238 }],
4239 [],
4240 )
4241 .expect("failed to push empty array");
4242 row
4243 });
4244 static LIST: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4245 static RECORD: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4246 static OID: LazyLock<Row> =
4247 LazyLock::new(|| Row::pack_slice(&[Datum::UInt32(u32::MIN), Datum::UInt32(u32::MAX)]));
4248 static MAP: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4249 static INT2VECTOR: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4250 static MZTIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
4251 Row::pack_slice(&[
4252 Datum::MzTimestamp(crate::Timestamp::MIN),
4253 Datum::MzTimestamp(crate::Timestamp::MAX),
4254 ])
4255 });
4256 static RANGE: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4257 static MZACLITEM: LazyLock<Row> = LazyLock::new(|| {
4258 Row::pack_slice(&[
4259 Datum::MzAclItem(MzAclItem {
4260 grantee: RoleId::Public,
4261 grantor: RoleId::Public,
4262 acl_mode: AclMode::empty(),
4263 }),
4264 Datum::MzAclItem(MzAclItem {
4265 grantee: RoleId::Public,
4266 grantor: RoleId::Public,
4267 acl_mode: AclMode::all(),
4268 }),
4269 Datum::MzAclItem(MzAclItem {
4270 grantee: RoleId::User(42),
4271 grantor: RoleId::Public,
4272 acl_mode: AclMode::empty(),
4273 }),
4274 Datum::MzAclItem(MzAclItem {
4275 grantee: RoleId::User(42),
4276 grantor: RoleId::Public,
4277 acl_mode: AclMode::all(),
4278 }),
4279 Datum::MzAclItem(MzAclItem {
4280 grantee: RoleId::Public,
4281 grantor: RoleId::User(42),
4282 acl_mode: AclMode::empty(),
4283 }),
4284 Datum::MzAclItem(MzAclItem {
4285 grantee: RoleId::Public,
4286 grantor: RoleId::User(42),
4287 acl_mode: AclMode::all(),
4288 }),
4289 ])
4290 });
4291 static ACLITEM: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
4293
4294 let iter: Box<dyn Iterator<Item = Datum<'static>>> = match self {
4295 SqlScalarType::Bool => Box::new((*BOOL).iter()),
4296 SqlScalarType::Int16 => Box::new((*INT16).iter()),
4297 SqlScalarType::Int32 => Box::new((*INT32).iter()),
4298 SqlScalarType::Int64 => Box::new((*INT64).iter()),
4299 SqlScalarType::UInt16 => Box::new((*UINT16).iter()),
4300 SqlScalarType::UInt32 => Box::new((*UINT32).iter()),
4301 SqlScalarType::UInt64 => Box::new((*UINT64).iter()),
4302 SqlScalarType::Float32 => Box::new((*FLOAT32).iter()),
4303 SqlScalarType::Float64 => Box::new((*FLOAT64).iter()),
4304 SqlScalarType::Numeric { .. } => Box::new((*NUMERIC).iter()),
4305 SqlScalarType::Date => Box::new((*DATE).iter()),
4306 SqlScalarType::Time => Box::new((*TIME).iter()),
4307 SqlScalarType::Timestamp { .. } => Box::new((*TIMESTAMP).iter()),
4308 SqlScalarType::TimestampTz { .. } => Box::new((*TIMESTAMPTZ).iter()),
4309 SqlScalarType::Interval => Box::new((*INTERVAL).iter()),
4310 SqlScalarType::PgLegacyChar => Box::new((*PGLEGACYCHAR).iter()),
4311 SqlScalarType::PgLegacyName => Box::new((*PGLEGACYNAME).iter()),
4312 SqlScalarType::Bytes => Box::new((*BYTES).iter()),
4313 SqlScalarType::String => Box::new((*STRING).iter().chain((*CHAR).iter())),
4314 SqlScalarType::Char { .. } => Box::new((*CHAR).iter()),
4315 SqlScalarType::VarChar { .. } => Box::new((*STRING).iter().chain((*CHAR).iter())),
4316 SqlScalarType::Jsonb => Box::new((*JSONB).iter()),
4317 SqlScalarType::Uuid => Box::new((*UUID).iter()),
4318 SqlScalarType::Array(inner_type) => {
4319 if matches!(inner_type.as_ref(), SqlScalarType::Array(_)) {
4320 panic!("SqlScalarType::Array cannot have a nested Array");
4321 }
4322
4323 Box::new(
4324 (*ARRAY)
4325 .get(inner_type.as_ref())
4326 .unwrap_or(&*EMPTY_ARRAY)
4327 .iter(),
4328 )
4329 }
4330 SqlScalarType::List { .. } => Box::new((*LIST).iter()),
4331 SqlScalarType::Record { .. } => Box::new((*RECORD).iter()),
4332 SqlScalarType::Oid => Box::new((*OID).iter()),
4333 SqlScalarType::Map { .. } => Box::new((*MAP).iter()),
4334 SqlScalarType::RegProc => Box::new((*OID).iter()),
4335 SqlScalarType::RegType => Box::new((*OID).iter()),
4336 SqlScalarType::RegClass => Box::new((*OID).iter()),
4337 SqlScalarType::Int2Vector => Box::new((*INT2VECTOR).iter()),
4338 SqlScalarType::MzTimestamp => Box::new((*MZTIMESTAMP).iter()),
4339 SqlScalarType::Range { .. } => Box::new((*RANGE).iter()),
4340 SqlScalarType::MzAclItem { .. } => Box::new((*MZACLITEM).iter()),
4341 SqlScalarType::AclItem { .. } => Box::new((*ACLITEM).iter()),
4342 };
4343
4344 iter
4345 }
4346
4347 pub fn enumerate() -> &'static [Self] {
4350 &[
4353 SqlScalarType::Bool,
4354 SqlScalarType::Int16,
4355 SqlScalarType::Int32,
4356 SqlScalarType::Int64,
4357 SqlScalarType::UInt16,
4358 SqlScalarType::UInt32,
4359 SqlScalarType::UInt64,
4360 SqlScalarType::Float32,
4361 SqlScalarType::Float64,
4362 SqlScalarType::Numeric {
4363 max_scale: Some(NumericMaxScale(
4364 crate::adt::numeric::NUMERIC_DATUM_MAX_PRECISION,
4365 )),
4366 },
4367 SqlScalarType::Date,
4368 SqlScalarType::Time,
4369 SqlScalarType::Timestamp {
4370 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
4371 },
4372 SqlScalarType::Timestamp {
4373 precision: Some(TimestampPrecision(0)),
4374 },
4375 SqlScalarType::Timestamp { precision: None },
4376 SqlScalarType::TimestampTz {
4377 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
4378 },
4379 SqlScalarType::TimestampTz {
4380 precision: Some(TimestampPrecision(0)),
4381 },
4382 SqlScalarType::TimestampTz { precision: None },
4383 SqlScalarType::Interval,
4384 SqlScalarType::PgLegacyChar,
4385 SqlScalarType::Bytes,
4386 SqlScalarType::String,
4387 SqlScalarType::Char {
4388 length: Some(CharLength(1)),
4389 },
4390 SqlScalarType::VarChar { max_length: None },
4391 SqlScalarType::Jsonb,
4392 SqlScalarType::Uuid,
4393 SqlScalarType::Oid,
4394 SqlScalarType::RegProc,
4395 SqlScalarType::RegType,
4396 SqlScalarType::RegClass,
4397 SqlScalarType::Int2Vector,
4398 SqlScalarType::MzTimestamp,
4399 SqlScalarType::MzAclItem,
4400 ]
4421 }
4422
4423 pub fn array_of_self_elem_type(self) -> Result<SqlScalarType, SqlScalarType> {
4428 match self {
4429 t @ (SqlScalarType::AclItem
4430 | SqlScalarType::Bool
4431 | SqlScalarType::Int16
4432 | SqlScalarType::Int32
4433 | SqlScalarType::Int64
4434 | SqlScalarType::UInt16
4435 | SqlScalarType::UInt32
4436 | SqlScalarType::UInt64
4437 | SqlScalarType::Float32
4438 | SqlScalarType::Float64
4439 | SqlScalarType::Numeric { .. }
4440 | SqlScalarType::Date
4441 | SqlScalarType::Time
4442 | SqlScalarType::Timestamp { .. }
4443 | SqlScalarType::TimestampTz { .. }
4444 | SqlScalarType::Interval
4445 | SqlScalarType::PgLegacyChar
4446 | SqlScalarType::PgLegacyName
4447 | SqlScalarType::Bytes
4448 | SqlScalarType::String
4449 | SqlScalarType::VarChar { .. }
4450 | SqlScalarType::Jsonb
4451 | SqlScalarType::Uuid
4452 | SqlScalarType::Record { .. }
4453 | SqlScalarType::Oid
4454 | SqlScalarType::RegProc
4455 | SqlScalarType::RegType
4456 | SqlScalarType::RegClass
4457 | SqlScalarType::Int2Vector
4458 | SqlScalarType::MzTimestamp
4459 | SqlScalarType::Range { .. }
4460 | SqlScalarType::MzAclItem { .. }) => Ok(t),
4461
4462 SqlScalarType::Array(elem) => Ok(elem.array_of_self_elem_type()?),
4463
4464 t @ (SqlScalarType::Char { .. }
4466 | SqlScalarType::Map { .. }
4468 | SqlScalarType::List { .. }) => Err(t),
4469 }
4470 }
4471}
4472
4473impl Arbitrary for SqlScalarType {
4476 type Parameters = ();
4477 type Strategy = BoxedStrategy<SqlScalarType>;
4478
4479 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
4480 let leaf = Union::new(vec![
4482 Just(SqlScalarType::Bool).boxed(),
4483 Just(SqlScalarType::UInt16).boxed(),
4484 Just(SqlScalarType::UInt32).boxed(),
4485 Just(SqlScalarType::UInt64).boxed(),
4486 Just(SqlScalarType::Int16).boxed(),
4487 Just(SqlScalarType::Int32).boxed(),
4488 Just(SqlScalarType::Int64).boxed(),
4489 Just(SqlScalarType::Float32).boxed(),
4490 Just(SqlScalarType::Float64).boxed(),
4491 any::<Option<NumericMaxScale>>()
4492 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
4493 .boxed(),
4494 Just(SqlScalarType::Date).boxed(),
4495 Just(SqlScalarType::Time).boxed(),
4496 any::<Option<TimestampPrecision>>()
4497 .prop_map(|precision| SqlScalarType::Timestamp { precision })
4498 .boxed(),
4499 any::<Option<TimestampPrecision>>()
4500 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
4501 .boxed(),
4502 Just(SqlScalarType::MzTimestamp).boxed(),
4503 Just(SqlScalarType::Interval).boxed(),
4504 Just(SqlScalarType::PgLegacyChar).boxed(),
4505 Just(SqlScalarType::Bytes).boxed(),
4506 Just(SqlScalarType::String).boxed(),
4507 any::<Option<CharLength>>()
4508 .prop_map(|length| SqlScalarType::Char { length })
4509 .boxed(),
4510 any::<Option<VarCharMaxLength>>()
4511 .prop_map(|max_length| SqlScalarType::VarChar { max_length })
4512 .boxed(),
4513 Just(SqlScalarType::PgLegacyName).boxed(),
4514 Just(SqlScalarType::Jsonb).boxed(),
4515 Just(SqlScalarType::Uuid).boxed(),
4516 Just(SqlScalarType::AclItem).boxed(),
4517 Just(SqlScalarType::MzAclItem).boxed(),
4518 Just(SqlScalarType::Oid).boxed(),
4519 Just(SqlScalarType::RegProc).boxed(),
4520 Just(SqlScalarType::RegType).boxed(),
4521 Just(SqlScalarType::RegClass).boxed(),
4522 Just(SqlScalarType::Int2Vector).boxed(),
4523 ])
4524 .no_shrink()
4527 .boxed();
4528
4529 let range_leaf = Union::new(vec![
4531 Just(SqlScalarType::Int32).boxed(),
4532 Just(SqlScalarType::Int64).boxed(),
4533 Just(SqlScalarType::Date).boxed(),
4534 any::<Option<NumericMaxScale>>()
4535 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
4536 .boxed(),
4537 any::<Option<TimestampPrecision>>()
4538 .prop_map(|precision| SqlScalarType::Timestamp { precision })
4539 .boxed(),
4540 any::<Option<TimestampPrecision>>()
4541 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
4542 .boxed(),
4543 ]);
4544 let range = range_leaf
4545 .prop_map(|inner_type| SqlScalarType::Range {
4546 element_type: Box::new(inner_type),
4547 })
4548 .boxed();
4549
4550 let array = leaf
4552 .clone()
4553 .prop_map(|inner_type| SqlScalarType::Array(Box::new(inner_type)))
4554 .boxed();
4555
4556 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
4557
4558 leaf.prop_recursive(2, 3, 5, |inner| {
4559 Union::new(vec![
4560 (inner.clone(), any::<Option<CatalogItemId>>())
4562 .prop_map(|(x, id)| SqlScalarType::List {
4563 element_type: Box::new(x),
4564 custom_id: id,
4565 })
4566 .boxed(),
4567 (inner.clone(), any::<Option<CatalogItemId>>())
4569 .prop_map(|(x, id)| SqlScalarType::Map {
4570 value_type: Box::new(x),
4571 custom_id: id,
4572 })
4573 .boxed(),
4574 {
4576 let column_type_strat =
4579 (inner, any::<bool>()).prop_map(|(scalar_type, nullable)| SqlColumnType {
4580 scalar_type,
4581 nullable,
4582 });
4583
4584 let fields_strat =
4587 prop::collection::vec((any::<ColumnName>(), column_type_strat), 0..10);
4588
4589 (fields_strat, any::<Option<CatalogItemId>>())
4591 .prop_map(|(fields, custom_id)| SqlScalarType::Record {
4592 fields: fields.into(),
4593 custom_id,
4594 })
4595 .boxed()
4596 },
4597 ])
4598 })
4599 .boxed()
4600 }
4601}
4602
4603impl Arbitrary for ReprScalarType {
4604 type Parameters = ();
4605 type Strategy = BoxedStrategy<ReprScalarType>;
4606
4607 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
4608 let leaf = Union::new(vec![
4610 Just(ReprScalarType::Bool).boxed(),
4611 Just(ReprScalarType::UInt8).boxed(),
4612 Just(ReprScalarType::UInt16).boxed(),
4613 Just(ReprScalarType::UInt32).boxed(),
4614 Just(ReprScalarType::UInt64).boxed(),
4615 Just(ReprScalarType::Int16).boxed(),
4616 Just(ReprScalarType::Int32).boxed(),
4617 Just(ReprScalarType::Int64).boxed(),
4618 Just(ReprScalarType::Float32).boxed(),
4619 Just(ReprScalarType::Float64).boxed(),
4620 Just(ReprScalarType::Numeric).boxed(),
4621 Just(ReprScalarType::Date).boxed(),
4622 Just(ReprScalarType::Time).boxed(),
4623 Just(ReprScalarType::Timestamp).boxed(),
4624 Just(ReprScalarType::TimestampTz).boxed(),
4625 Just(ReprScalarType::MzTimestamp).boxed(),
4626 Just(ReprScalarType::Interval).boxed(),
4627 Just(ReprScalarType::Bytes).boxed(),
4628 Just(ReprScalarType::String).boxed(),
4629 Just(ReprScalarType::Jsonb).boxed(),
4630 Just(ReprScalarType::Uuid).boxed(),
4631 Just(ReprScalarType::AclItem).boxed(),
4632 Just(ReprScalarType::MzAclItem).boxed(),
4633 Just(ReprScalarType::Int2Vector).boxed(),
4634 ])
4635 .no_shrink()
4638 .boxed();
4639
4640 let range_leaf = Union::new(vec![
4642 Just(ReprScalarType::Int32).boxed(),
4643 Just(ReprScalarType::Int64).boxed(),
4644 Just(ReprScalarType::Date).boxed(),
4645 Just(ReprScalarType::Numeric).boxed(),
4646 Just(ReprScalarType::Timestamp).boxed(),
4647 Just(ReprScalarType::TimestampTz).boxed(),
4648 ]);
4649 let range = range_leaf
4650 .prop_map(|inner_type| ReprScalarType::Range {
4651 element_type: Box::new(inner_type),
4652 })
4653 .boxed();
4654
4655 let array = leaf
4657 .clone()
4658 .prop_map(|inner_type| ReprScalarType::Array(Box::new(inner_type)))
4659 .boxed();
4660
4661 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
4662
4663 leaf.prop_recursive(2, 3, 5, |inner| {
4664 Union::new(vec![
4665 inner
4667 .clone()
4668 .prop_map(|x| ReprScalarType::List {
4669 element_type: Box::new(x),
4670 })
4671 .boxed(),
4672 inner
4674 .clone()
4675 .prop_map(|x| ReprScalarType::Map {
4676 value_type: Box::new(x),
4677 })
4678 .boxed(),
4679 {
4681 let column_type_strat =
4684 (inner.clone(), any::<bool>()).prop_map(|(scalar_type, nullable)| {
4685 ReprColumnType {
4686 scalar_type,
4687 nullable,
4688 }
4689 });
4690
4691 let fields_strat = prop::collection::vec(column_type_strat, 0..10);
4694
4695 fields_strat
4697 .prop_map(|fields| ReprScalarType::Record {
4698 fields: fields.into_boxed_slice(),
4699 })
4700 .boxed()
4701 },
4702 ])
4703 })
4704 .boxed()
4705 }
4706}
4707
4708#[derive(Clone, Debug, EnumKind, Serialize, Deserialize, MzReflect)]
4719#[enum_kind(ReprScalarBaseType, derive(PartialOrd, Ord, Hash))]
4720pub enum ReprScalarType {
4721 Bool,
4722 Int16,
4723 Int32,
4724 Int64,
4725 UInt8, UInt16,
4727 UInt32, UInt64,
4729 Float32,
4730 Float64,
4731 Numeric,
4732 Date,
4733 Time,
4734 Timestamp,
4735 TimestampTz,
4736 MzTimestamp,
4737 Interval,
4738 Bytes,
4739 Jsonb,
4740 String, Uuid,
4742 Array(Box<ReprScalarType>),
4743 Int2Vector, List { element_type: Box<ReprScalarType> },
4745 Record { fields: Box<[ReprColumnType]> },
4746 Map { value_type: Box<ReprScalarType> },
4747 Range { element_type: Box<ReprScalarType> },
4748 MzAclItem,
4749 AclItem,
4750}
4751
4752impl PartialEq for ReprScalarType {
4753 fn eq(&self, other: &Self) -> bool {
4754 match (self, other) {
4755 (ReprScalarType::Array(a), ReprScalarType::Array(b)) => a.eq(b),
4756 (
4757 ReprScalarType::List { element_type: a },
4758 ReprScalarType::List { element_type: b },
4759 ) => a.eq(b),
4760 (ReprScalarType::Record { fields: a }, ReprScalarType::Record { fields: b }) => {
4761 a.len() == b.len()
4762 && a.iter()
4763 .zip_eq(b.iter())
4764 .all(|(af, bf)| af.scalar_type.eq(&bf.scalar_type))
4765 }
4766 (ReprScalarType::Map { value_type: a }, ReprScalarType::Map { value_type: b }) => {
4767 a.eq(b)
4768 }
4769 (
4770 ReprScalarType::Range { element_type: a },
4771 ReprScalarType::Range { element_type: b },
4772 ) => a.eq(b),
4773 _ => ReprScalarBaseType::from(self) == ReprScalarBaseType::from(other),
4774 }
4775 }
4776}
4777impl Eq for ReprScalarType {}
4778
4779impl Hash for ReprScalarType {
4780 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
4781 match self {
4782 ReprScalarType::Array(a) => a.hash(state),
4783 ReprScalarType::List { element_type: a } => a.hash(state),
4784 ReprScalarType::Record { fields: a } => {
4785 for field in a {
4786 field.scalar_type.hash(state);
4787 }
4788 }
4789 ReprScalarType::Map { value_type: a } => a.hash(state),
4790 ReprScalarType::Range { element_type: a } => a.hash(state),
4791 _ => ReprScalarBaseType::from(self).hash(state),
4792 }
4793 }
4794}
4795
4796impl PartialOrd for ReprScalarType {
4797 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
4798 Some(self.cmp(other))
4799 }
4800}
4801
4802impl Ord for ReprScalarType {
4803 fn cmp(&self, other: &Self) -> Ordering {
4804 match (self, other) {
4805 (ReprScalarType::Array(a), ReprScalarType::Array(b)) => a.cmp(b),
4806 (
4807 ReprScalarType::List { element_type: a },
4808 ReprScalarType::List { element_type: b },
4809 ) => a.cmp(b),
4810 (ReprScalarType::Record { fields: a }, ReprScalarType::Record { fields: b }) => {
4811 let len_ordering = a.len().cmp(&b.len());
4812 if len_ordering != Ordering::Equal {
4813 return len_ordering;
4814 }
4815
4816 for (af, bf) in a.iter().zip_eq(b.iter()) {
4818 let scalar_type_ordering = af.scalar_type.cmp(&bf.scalar_type);
4819 if scalar_type_ordering != Ordering::Equal {
4820 return scalar_type_ordering;
4821 }
4822 }
4823
4824 Ordering::Equal
4825 }
4826 (ReprScalarType::Map { value_type: a }, ReprScalarType::Map { value_type: b }) => {
4827 a.cmp(b)
4828 }
4829 (
4830 ReprScalarType::Range { element_type: a },
4831 ReprScalarType::Range { element_type: b },
4832 ) => a.cmp(b),
4833 _ => ReprScalarBaseType::from(self).cmp(&ReprScalarBaseType::from(other)),
4834 }
4835 }
4836}
4837
4838impl ReprScalarType {
4839 pub fn nullable(self, nullable: bool) -> ReprColumnType {
4841 ReprColumnType {
4842 scalar_type: self,
4843 nullable,
4844 }
4845 }
4846
4847 pub fn union(&self, scalar_type: &ReprScalarType) -> Result<Self, anyhow::Error> {
4853 match (self, scalar_type) {
4854 (ReprScalarType::Bool, ReprScalarType::Bool) => Ok(ReprScalarType::Bool),
4855 (ReprScalarType::Int16, ReprScalarType::Int16) => Ok(ReprScalarType::Int16),
4856 (ReprScalarType::Int32, ReprScalarType::Int32) => Ok(ReprScalarType::Int32),
4857 (ReprScalarType::Int64, ReprScalarType::Int64) => Ok(ReprScalarType::Int64),
4858 (ReprScalarType::UInt8, ReprScalarType::UInt8) => Ok(ReprScalarType::UInt8),
4859 (ReprScalarType::UInt16, ReprScalarType::UInt16) => Ok(ReprScalarType::UInt16),
4860 (ReprScalarType::UInt32, ReprScalarType::UInt32) => Ok(ReprScalarType::UInt32),
4861 (ReprScalarType::UInt64, ReprScalarType::UInt64) => Ok(ReprScalarType::UInt64),
4862 (ReprScalarType::Float32, ReprScalarType::Float32) => Ok(ReprScalarType::Float32),
4863 (ReprScalarType::Float64, ReprScalarType::Float64) => Ok(ReprScalarType::Float64),
4864 (ReprScalarType::Numeric, ReprScalarType::Numeric) => Ok(ReprScalarType::Numeric),
4865 (ReprScalarType::Date, ReprScalarType::Date) => Ok(ReprScalarType::Date),
4866 (ReprScalarType::Time, ReprScalarType::Time) => Ok(ReprScalarType::Time),
4867 (ReprScalarType::Timestamp, ReprScalarType::Timestamp) => Ok(ReprScalarType::Timestamp),
4868 (ReprScalarType::TimestampTz, ReprScalarType::TimestampTz) => {
4869 Ok(ReprScalarType::TimestampTz)
4870 }
4871 (ReprScalarType::MzTimestamp, ReprScalarType::MzTimestamp) => {
4872 Ok(ReprScalarType::MzTimestamp)
4873 }
4874 (ReprScalarType::AclItem, ReprScalarType::AclItem) => Ok(ReprScalarType::AclItem),
4875 (ReprScalarType::MzAclItem, ReprScalarType::MzAclItem) => Ok(ReprScalarType::MzAclItem),
4876 (ReprScalarType::Interval, ReprScalarType::Interval) => Ok(ReprScalarType::Interval),
4877 (ReprScalarType::Bytes, ReprScalarType::Bytes) => Ok(ReprScalarType::Bytes),
4878 (ReprScalarType::Jsonb, ReprScalarType::Jsonb) => Ok(ReprScalarType::Jsonb),
4879 (ReprScalarType::String, ReprScalarType::String) => Ok(ReprScalarType::String),
4880 (ReprScalarType::Uuid, ReprScalarType::Uuid) => Ok(ReprScalarType::Uuid),
4881 (ReprScalarType::Array(element_type), ReprScalarType::Array(other_element_type)) => Ok(
4882 ReprScalarType::Array(Box::new(element_type.union(other_element_type)?)),
4883 ),
4884 (ReprScalarType::Int2Vector, ReprScalarType::Int2Vector) => {
4885 Ok(ReprScalarType::Int2Vector)
4886 }
4887 (
4888 ReprScalarType::List { element_type },
4889 ReprScalarType::List {
4890 element_type: other_element_type,
4891 },
4892 ) => Ok(ReprScalarType::List {
4893 element_type: Box::new(element_type.union(other_element_type)?),
4894 }),
4895 (
4896 ReprScalarType::Record { fields },
4897 ReprScalarType::Record {
4898 fields: other_fields,
4899 },
4900 ) => {
4901 if fields.len() != other_fields.len() {
4902 bail!("Can't union record types: {:?} and {:?}", self, scalar_type);
4903 }
4904
4905 let mut union_fields = Vec::with_capacity(fields.len());
4906 for (field, other_field) in fields.iter().zip_eq(other_fields.iter()) {
4907 union_fields.push(field.union(other_field)?);
4908 }
4909 Ok(ReprScalarType::Record {
4910 fields: union_fields.into_boxed_slice(),
4911 })
4912 }
4913 (
4914 ReprScalarType::Map { value_type },
4915 ReprScalarType::Map {
4916 value_type: other_value_type,
4917 },
4918 ) => Ok(ReprScalarType::Map {
4919 value_type: Box::new(value_type.union(other_value_type)?),
4920 }),
4921 (
4922 ReprScalarType::Range { element_type },
4923 ReprScalarType::Range {
4924 element_type: other_element_type,
4925 },
4926 ) => Ok(ReprScalarType::Range {
4927 element_type: Box::new(element_type.union(other_element_type)?),
4928 }),
4929 (_, _) => bail!("Can't union scalar types: {:?} and {:?}", self, scalar_type),
4930 }
4931 }
4932
4933 pub fn unwrap_list_element_type(&self) -> &ReprScalarType {
4939 match self {
4940 ReprScalarType::List { element_type, .. } => element_type,
4941 _ => panic!(
4942 "ReprScalarType::unwrap_list_element_type called on {:?}",
4943 self
4944 ),
4945 }
4946 }
4947
4948 pub fn unwrap_record_element_type(&self) -> Vec<&ReprScalarType> {
4954 match self {
4955 ReprScalarType::Record { fields, .. } => {
4956 fields.iter().map(|t| &t.scalar_type).collect_vec()
4957 }
4958 _ => panic!(
4959 "SqlScalarType::unwrap_record_element_type called on {:?}",
4960 self
4961 ),
4962 }
4963 }
4964}
4965
4966impl From<&SqlScalarType> for ReprScalarType {
4967 fn from(typ: &SqlScalarType) -> Self {
4968 match typ {
4969 SqlScalarType::Bool => ReprScalarType::Bool,
4970 SqlScalarType::Int16 => ReprScalarType::Int16,
4971 SqlScalarType::Int32 => ReprScalarType::Int32,
4972 SqlScalarType::Int64 => ReprScalarType::Int64,
4973 SqlScalarType::UInt16 => ReprScalarType::UInt16,
4974 SqlScalarType::UInt32 => ReprScalarType::UInt32,
4975 SqlScalarType::UInt64 => ReprScalarType::UInt64,
4976 SqlScalarType::Float32 => ReprScalarType::Float32,
4977 SqlScalarType::Float64 => ReprScalarType::Float64,
4978 SqlScalarType::Numeric { max_scale: _ } => ReprScalarType::Numeric,
4979 SqlScalarType::Date => ReprScalarType::Date,
4980 SqlScalarType::Time => ReprScalarType::Time,
4981 SqlScalarType::Timestamp { precision: _ } => ReprScalarType::Timestamp,
4982 SqlScalarType::TimestampTz { precision: _ } => ReprScalarType::TimestampTz,
4983 SqlScalarType::Interval => ReprScalarType::Interval,
4984 SqlScalarType::PgLegacyChar => ReprScalarType::UInt8,
4985 SqlScalarType::PgLegacyName => ReprScalarType::String,
4986 SqlScalarType::Bytes => ReprScalarType::Bytes,
4987 SqlScalarType::String => ReprScalarType::String,
4988 SqlScalarType::Char { length: _ } => ReprScalarType::String,
4989 SqlScalarType::VarChar { max_length: _ } => ReprScalarType::String,
4990 SqlScalarType::Jsonb => ReprScalarType::Jsonb,
4991 SqlScalarType::Uuid => ReprScalarType::Uuid,
4992 SqlScalarType::Array(element_type) => {
4993 ReprScalarType::Array(Box::new(element_type.as_ref().into()))
4994 }
4995 SqlScalarType::List {
4996 element_type,
4997 custom_id: _,
4998 } => ReprScalarType::List {
4999 element_type: Box::new(element_type.as_ref().into()),
5000 },
5001 SqlScalarType::Record {
5002 fields,
5003 custom_id: _,
5004 } => ReprScalarType::Record {
5005 fields: fields.into_iter().map(|(_, typ)| typ.into()).collect(),
5006 },
5007 SqlScalarType::Oid => ReprScalarType::UInt32,
5008 SqlScalarType::Map {
5009 value_type,
5010 custom_id: _,
5011 } => ReprScalarType::Map {
5012 value_type: Box::new(value_type.as_ref().into()),
5013 },
5014 SqlScalarType::RegProc => ReprScalarType::UInt32,
5015 SqlScalarType::RegType => ReprScalarType::UInt32,
5016 SqlScalarType::RegClass => ReprScalarType::UInt32,
5017 SqlScalarType::Int2Vector => ReprScalarType::Int2Vector,
5018 SqlScalarType::MzTimestamp => ReprScalarType::MzTimestamp,
5019 SqlScalarType::Range { element_type } => ReprScalarType::Range {
5020 element_type: Box::new(element_type.as_ref().into()),
5021 },
5022 SqlScalarType::MzAclItem => ReprScalarType::MzAclItem,
5023 SqlScalarType::AclItem => ReprScalarType::AclItem,
5024 }
5025 }
5026}
5027
5028impl SqlScalarType {
5029 pub fn from_repr(repr: &ReprScalarType) -> Self {
5049 match repr {
5050 ReprScalarType::Bool => SqlScalarType::Bool,
5051 ReprScalarType::Int16 => SqlScalarType::Int16,
5052 ReprScalarType::Int32 => SqlScalarType::Int32,
5053 ReprScalarType::Int64 => SqlScalarType::Int64,
5054 ReprScalarType::UInt8 => SqlScalarType::PgLegacyChar,
5055 ReprScalarType::UInt16 => SqlScalarType::UInt16,
5056 ReprScalarType::UInt32 => SqlScalarType::UInt32,
5057 ReprScalarType::UInt64 => SqlScalarType::UInt64,
5058 ReprScalarType::Float32 => SqlScalarType::Float32,
5059 ReprScalarType::Float64 => SqlScalarType::Float64,
5060 ReprScalarType::Numeric => SqlScalarType::Numeric { max_scale: None },
5061 ReprScalarType::Date => SqlScalarType::Date,
5062 ReprScalarType::Time => SqlScalarType::Time,
5063 ReprScalarType::Timestamp => SqlScalarType::Timestamp { precision: None },
5064 ReprScalarType::TimestampTz => SqlScalarType::TimestampTz { precision: None },
5065 ReprScalarType::MzTimestamp => SqlScalarType::MzTimestamp,
5066 ReprScalarType::Interval => SqlScalarType::Interval,
5067 ReprScalarType::Bytes => SqlScalarType::Bytes,
5068 ReprScalarType::Jsonb => SqlScalarType::Jsonb,
5069 ReprScalarType::String => SqlScalarType::String,
5070 ReprScalarType::Uuid => SqlScalarType::Uuid,
5071 ReprScalarType::Array(element_type) => {
5072 SqlScalarType::Array(Box::new(SqlScalarType::from_repr(element_type)))
5073 }
5074 ReprScalarType::Int2Vector => SqlScalarType::Int2Vector,
5075 ReprScalarType::List { element_type } => SqlScalarType::List {
5076 element_type: Box::new(SqlScalarType::from_repr(element_type)),
5077 custom_id: None,
5078 },
5079 ReprScalarType::Record { fields } => SqlScalarType::Record {
5080 fields: fields
5081 .iter()
5082 .enumerate()
5083 .map(|typ| {
5084 (
5085 ColumnName::from(format!("field_{}", typ.0)),
5086 SqlColumnType::from_repr(typ.1),
5087 )
5088 })
5089 .collect::<Vec<_>>()
5090 .into_boxed_slice(),
5091 custom_id: None,
5092 },
5093 ReprScalarType::Map { value_type } => SqlScalarType::Map {
5094 value_type: Box::new(SqlScalarType::from_repr(value_type)),
5095 custom_id: None,
5096 },
5097 ReprScalarType::Range { element_type } => SqlScalarType::Range {
5098 element_type: Box::new(SqlScalarType::from_repr(element_type)),
5099 },
5100 ReprScalarType::MzAclItem => SqlScalarType::MzAclItem,
5101 ReprScalarType::AclItem => SqlScalarType::AclItem,
5102 }
5103 }
5104}
5105
5106static EMPTY_ARRAY_ROW: LazyLock<Row> = LazyLock::new(|| {
5107 let mut row = Row::default();
5108 row.packer()
5109 .try_push_array(&[], iter::empty::<Datum>())
5110 .expect("array known to be valid");
5111 row
5112});
5113
5114static EMPTY_LIST_ROW: LazyLock<Row> = LazyLock::new(|| {
5115 let mut row = Row::default();
5116 row.packer().push_list(iter::empty::<Datum>());
5117 row
5118});
5119
5120static EMPTY_MAP_ROW: LazyLock<Row> = LazyLock::new(|| {
5121 let mut row = Row::default();
5122 row.packer().push_dict(iter::empty::<(_, Datum)>());
5123 row
5124});
5125
5126impl Datum<'_> {
5127 pub fn empty_array() -> Datum<'static> {
5128 EMPTY_ARRAY_ROW.unpack_first()
5129 }
5130
5131 pub fn empty_list() -> Datum<'static> {
5132 EMPTY_LIST_ROW.unpack_first()
5133 }
5134
5135 pub fn empty_map() -> Datum<'static> {
5136 EMPTY_MAP_ROW.unpack_first()
5137 }
5138
5139 pub fn contains_dummy(&self) -> bool {
5140 match self {
5141 Datum::Dummy => true,
5142 Datum::List(list) => list.iter().any(|d| d.contains_dummy()),
5143 Datum::Map(map) => map.iter().any(|(_, d)| d.contains_dummy()),
5144 Datum::Array(array) => array.elements().iter().any(|d| d.contains_dummy()),
5145 Datum::Range(range) => range.inner.map_or(false, |range| {
5146 range
5147 .lower
5148 .bound
5149 .map_or(false, |d| d.datum().contains_dummy())
5150 || range
5151 .upper
5152 .bound
5153 .map_or(false, |d| d.datum().contains_dummy())
5154 }),
5155 _ => false,
5156 }
5157 }
5158}
5159
5160#[derive(Debug, PartialEq, Clone)]
5162pub enum PropDatum {
5163 Null,
5164 Bool(bool),
5165 Int16(i16),
5166 Int32(i32),
5167 Int64(i64),
5168 UInt8(u8),
5169 UInt16(u16),
5170 UInt32(u32),
5171 UInt64(u64),
5172 Float32(f32),
5173 Float64(f64),
5174
5175 Date(Date),
5176 Time(chrono::NaiveTime),
5177 Timestamp(CheckedTimestamp<chrono::NaiveDateTime>),
5178 TimestampTz(CheckedTimestamp<chrono::DateTime<chrono::Utc>>),
5179 MzTimestamp(u64),
5180
5181 Interval(Interval),
5182 Numeric(Numeric),
5183
5184 Bytes(Vec<u8>),
5185 String(String),
5186
5187 Array(PropArray),
5188 List(PropList),
5189 Map(PropDict),
5190 Record(PropDict),
5191 Range(PropRange),
5192
5193 AclItem(AclItem),
5194 MzAclItem(MzAclItem),
5195
5196 JsonNull,
5197 Uuid(Uuid),
5198 Dummy,
5199}
5200
5201impl std::cmp::Eq for PropDatum {}
5202
5203impl PartialOrd for PropDatum {
5204 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
5205 Some(self.cmp(other))
5206 }
5207}
5208
5209impl Ord for PropDatum {
5210 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
5211 Datum::from(self).cmp(&Datum::from(other))
5212 }
5213}
5214
5215pub fn arb_datum(allow_dummy: bool) -> BoxedStrategy<PropDatum> {
5217 let mut leaf_options = vec![
5218 any::<bool>().prop_map(PropDatum::Bool).boxed(),
5219 any::<i16>().prop_map(PropDatum::Int16).boxed(),
5220 any::<i32>().prop_map(PropDatum::Int32).boxed(),
5221 any::<i64>().prop_map(PropDatum::Int64).boxed(),
5222 any::<u16>().prop_map(PropDatum::UInt16).boxed(),
5223 any::<u32>().prop_map(PropDatum::UInt32).boxed(),
5224 any::<u64>().prop_map(PropDatum::UInt64).boxed(),
5225 any::<f32>().prop_map(PropDatum::Float32).boxed(),
5226 any::<f64>().prop_map(PropDatum::Float64).boxed(),
5227 arb_date().prop_map(PropDatum::Date).boxed(),
5228 add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
5229 .prop_map(PropDatum::Time)
5230 .boxed(),
5231 arb_naive_date_time()
5232 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
5233 .boxed(),
5234 arb_utc_date_time()
5235 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
5236 .boxed(),
5237 any::<Interval>().prop_map(PropDatum::Interval).boxed(),
5238 arb_numeric().prop_map(PropDatum::Numeric).boxed(),
5239 prop::collection::vec(any::<u8>(), 1024)
5240 .prop_map(PropDatum::Bytes)
5241 .boxed(),
5242 ".*".prop_map(PropDatum::String).boxed(),
5243 Just(PropDatum::JsonNull).boxed(),
5244 any::<[u8; 16]>()
5245 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
5246 .boxed(),
5247 arb_range(arb_range_data())
5248 .prop_map(PropDatum::Range)
5249 .boxed(),
5250 ];
5251
5252 if allow_dummy {
5253 leaf_options.push(Just(PropDatum::Dummy).boxed());
5254 }
5255 let leaf = Union::new(leaf_options);
5256
5257 leaf.prop_recursive(3, 8, 16, |inner| {
5258 Union::new(vec![
5259 arb_array(inner.clone()).prop_map(PropDatum::Array).boxed(),
5260 arb_list(inner.clone()).prop_map(PropDatum::List).boxed(),
5261 arb_dict(inner).prop_map(PropDatum::Map).boxed(),
5262 ])
5263 })
5264 .boxed()
5265}
5266
5267pub fn arb_datum_for_column(column_type: SqlColumnType) -> impl Strategy<Value = PropDatum> {
5269 let strat = arb_datum_for_scalar(column_type.scalar_type);
5270
5271 if column_type.nullable {
5272 Union::new_weighted(vec![(1, Just(PropDatum::Null).boxed()), (5, strat.boxed())]).boxed()
5273 } else {
5274 strat.boxed()
5275 }
5276}
5277
5278pub fn arb_datum_for_scalar(scalar_type: SqlScalarType) -> impl Strategy<Value = PropDatum> {
5280 match scalar_type {
5281 SqlScalarType::Bool => any::<bool>().prop_map(PropDatum::Bool).boxed(),
5282 SqlScalarType::Int16 => any::<i16>().prop_map(PropDatum::Int16).boxed(),
5283 SqlScalarType::Int32 => any::<i32>().prop_map(PropDatum::Int32).boxed(),
5284 SqlScalarType::Int64 => any::<i64>().prop_map(PropDatum::Int64).boxed(),
5285 SqlScalarType::PgLegacyChar => any::<u8>().prop_map(PropDatum::UInt8).boxed(),
5286 SqlScalarType::UInt16 => any::<u16>().prop_map(PropDatum::UInt16).boxed(),
5287 SqlScalarType::UInt32
5288 | SqlScalarType::Oid
5289 | SqlScalarType::RegClass
5290 | SqlScalarType::RegProc
5291 | SqlScalarType::RegType => any::<u32>().prop_map(PropDatum::UInt32).boxed(),
5292 SqlScalarType::UInt64 => any::<u64>().prop_map(PropDatum::UInt64).boxed(),
5293 SqlScalarType::Float32 => any::<f32>().prop_map(PropDatum::Float32).boxed(),
5294 SqlScalarType::Float64 => any::<f64>().prop_map(PropDatum::Float64).boxed(),
5295 SqlScalarType::Numeric { .. } => arb_numeric().prop_map(PropDatum::Numeric).boxed(),
5296 SqlScalarType::String
5297 | SqlScalarType::PgLegacyName
5298 | SqlScalarType::Char { length: None }
5299 | SqlScalarType::VarChar { max_length: None } => ".*".prop_map(PropDatum::String).boxed(),
5300 SqlScalarType::Char {
5301 length: Some(length),
5302 } => {
5303 let max_len = usize::cast_from(length.into_u32()).max(1);
5304 prop::collection::vec(any::<char>(), 0..max_len)
5305 .prop_map(move |chars| {
5306 let num_blanks = max_len - chars.len();
5308 let s = chars
5309 .into_iter()
5310 .chain(std::iter::repeat(' ').take(num_blanks))
5311 .collect();
5312 PropDatum::String(s)
5313 })
5314 .boxed()
5315 }
5316 SqlScalarType::VarChar {
5317 max_length: Some(length),
5318 } => {
5319 let max_len = usize::cast_from(length.into_u32()).max(1);
5320 prop::collection::vec(any::<char>(), 0..max_len)
5321 .prop_map(|chars| PropDatum::String(chars.into_iter().collect()))
5322 .boxed()
5323 }
5324 SqlScalarType::Bytes => prop::collection::vec(any::<u8>(), 300)
5325 .prop_map(PropDatum::Bytes)
5326 .boxed(),
5327 SqlScalarType::Date => arb_date().prop_map(PropDatum::Date).boxed(),
5328 SqlScalarType::Time => add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
5329 .prop_map(PropDatum::Time)
5330 .boxed(),
5331 SqlScalarType::Timestamp { .. } => arb_naive_date_time()
5332 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
5333 .boxed(),
5334 SqlScalarType::TimestampTz { .. } => arb_utc_date_time()
5335 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
5336 .boxed(),
5337 SqlScalarType::MzTimestamp => any::<u64>().prop_map(PropDatum::MzTimestamp).boxed(),
5338 SqlScalarType::Interval => any::<Interval>().prop_map(PropDatum::Interval).boxed(),
5339 SqlScalarType::Uuid => any::<[u8; 16]>()
5340 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
5341 .boxed(),
5342 SqlScalarType::AclItem => any::<AclItem>().prop_map(PropDatum::AclItem).boxed(),
5343 SqlScalarType::MzAclItem => any::<MzAclItem>().prop_map(PropDatum::MzAclItem).boxed(),
5344 SqlScalarType::Range { element_type } => {
5345 let data_strat = (
5346 arb_datum_for_scalar(*element_type.clone()),
5347 arb_datum_for_scalar(*element_type),
5348 );
5349 arb_range(data_strat).prop_map(PropDatum::Range).boxed()
5350 }
5351 SqlScalarType::List { element_type, .. } => arb_list(arb_datum_for_scalar(*element_type))
5352 .prop_map(PropDatum::List)
5353 .boxed(),
5354 SqlScalarType::Array(element_type) => arb_array(arb_datum_for_scalar(*element_type))
5355 .prop_map(PropDatum::Array)
5356 .boxed(),
5357 SqlScalarType::Int2Vector => arb_array(any::<i16>().prop_map(PropDatum::Int16).boxed())
5358 .prop_map(PropDatum::Array)
5359 .boxed(),
5360 SqlScalarType::Map { value_type, .. } => arb_dict(arb_datum_for_scalar(*value_type))
5361 .prop_map(PropDatum::Map)
5362 .boxed(),
5363 SqlScalarType::Record { fields, .. } => {
5364 let field_strats = fields.iter().map(|(name, ty)| {
5365 (
5366 name.to_string(),
5367 arb_datum_for_scalar(ty.scalar_type.clone()),
5368 )
5369 });
5370 arb_record(field_strats).prop_map(PropDatum::Record).boxed()
5371 }
5372 SqlScalarType::Jsonb => {
5373 let int_value = any::<i128>()
5374 .prop_map(|v| Numeric::try_from(v).unwrap())
5375 .boxed();
5376 let float_value = (1e-39f64..1e39)
5378 .prop_map(|v| Numeric::try_from(v).unwrap())
5379 .boxed();
5380 let json_number = Union::new(vec![int_value, float_value]);
5383
5384 let json_leaf = Union::new(vec![
5385 any::<()>().prop_map(|_| PropDatum::JsonNull).boxed(),
5386 any::<bool>().prop_map(PropDatum::Bool).boxed(),
5387 json_number.prop_map(PropDatum::Numeric).boxed(),
5388 ".*".prop_map(PropDatum::String).boxed(),
5389 ]);
5390 json_leaf
5391 .prop_recursive(4, 32, 8, |element| {
5392 Union::new(vec![
5393 prop::collection::vec(element.clone(), 0..16)
5394 .prop_map(|elements| {
5395 let datums: Vec<_> = elements.iter().map(|pd| pd.into()).collect();
5396 let mut row = Row::default();
5397 row.packer().push_list(datums.iter());
5398 PropDatum::List(PropList(row, elements))
5399 })
5400 .boxed(),
5401 prop::collection::hash_map(".*", element, 0..16)
5402 .prop_map(|elements| {
5403 let mut elements: Vec<_> = elements.into_iter().collect();
5404 elements.sort_by_key(|(k, _)| k.clone());
5405 elements.dedup_by_key(|(k, _)| k.clone());
5406 let mut row = Row::default();
5407 let entry_iter =
5408 elements.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
5409 row.packer().push_dict(entry_iter);
5410 PropDatum::Map(PropDict(row, elements))
5411 })
5412 .boxed(),
5413 ])
5414 })
5415 .boxed()
5416 }
5417 }
5418}
5419
5420pub fn arb_naive_date_time() -> impl Strategy<Value = NaiveDateTime> {
5422 add_arb_duration(chrono::DateTime::from_timestamp(0, 0).unwrap().naive_utc())
5423}
5424
5425pub fn arb_utc_date_time() -> impl Strategy<Value = DateTime<Utc>> {
5427 add_arb_duration(chrono::Utc.timestamp_opt(0, 0).unwrap())
5428}
5429
5430fn arb_array_dimension() -> BoxedStrategy<ArrayDimension> {
5431 (1..4_usize)
5432 .prop_map(|length| ArrayDimension {
5433 lower_bound: 1,
5434 length,
5435 })
5436 .boxed()
5437}
5438
5439#[derive(Debug, PartialEq, Clone)]
5440pub struct PropArray(Row, Vec<PropDatum>);
5441
5442fn arb_array(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropArray> {
5443 let element_strategy = Union::new_weighted(vec![
5445 (20, element_strategy),
5446 (1, Just(PropDatum::Null).boxed()),
5447 ]);
5448
5449 prop::collection::vec(
5450 arb_array_dimension(),
5451 1..usize::from(crate::adt::array::MAX_ARRAY_DIMENSIONS),
5452 )
5453 .prop_flat_map(move |dimensions| {
5454 let n_elts: usize = dimensions.iter().map(|d| d.length).product();
5455 (
5456 Just(dimensions),
5457 prop::collection::vec(element_strategy.clone(), n_elts),
5458 )
5459 })
5460 .prop_map(|(dimensions, elements)| {
5461 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
5462 let mut row = Row::default();
5463 row.packer()
5464 .try_push_array(&dimensions, element_datums)
5465 .unwrap();
5466 PropArray(row, elements)
5467 })
5468 .boxed()
5469}
5470
5471#[derive(Debug, PartialEq, Clone)]
5472pub struct PropList(Row, Vec<PropDatum>);
5473
5474fn arb_list(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropList> {
5475 let element_strategy = Union::new_weighted(vec![
5477 (20, element_strategy),
5478 (1, Just(PropDatum::Null).boxed()),
5479 ]);
5480
5481 prop::collection::vec(element_strategy, 1..50)
5482 .prop_map(|elements| {
5483 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
5484 let mut row = Row::default();
5485 row.packer().push_list(element_datums.iter());
5486 PropList(row, elements)
5487 })
5488 .boxed()
5489}
5490
5491#[derive(Debug, PartialEq, Clone)]
5492pub struct PropRange(
5493 Row,
5494 Option<(
5495 (Option<Box<PropDatum>>, bool),
5496 (Option<Box<PropDatum>>, bool),
5497 )>,
5498);
5499
5500pub fn arb_range_type() -> Union<BoxedStrategy<SqlScalarType>> {
5501 Union::new(vec![
5502 Just(SqlScalarType::Int32).boxed(),
5503 Just(SqlScalarType::Int64).boxed(),
5504 Just(SqlScalarType::Date).boxed(),
5505 ])
5506}
5507
5508fn arb_range_data() -> Union<BoxedStrategy<(PropDatum, PropDatum)>> {
5509 Union::new(vec![
5510 (
5511 any::<i32>().prop_map(PropDatum::Int32),
5512 any::<i32>().prop_map(PropDatum::Int32),
5513 )
5514 .boxed(),
5515 (
5516 any::<i64>().prop_map(PropDatum::Int64),
5517 any::<i64>().prop_map(PropDatum::Int64),
5518 )
5519 .boxed(),
5520 (
5521 arb_date().prop_map(PropDatum::Date),
5522 arb_date().prop_map(PropDatum::Date),
5523 )
5524 .boxed(),
5525 ])
5526}
5527
5528fn arb_range(
5529 data: impl Strategy<Value = (PropDatum, PropDatum)> + 'static,
5530) -> BoxedStrategy<PropRange> {
5531 (
5532 any::<u16>(),
5533 any::<bool>(),
5534 any::<bool>(),
5535 any::<bool>(),
5536 any::<bool>(),
5537 data,
5538 )
5539 .prop_map(
5540 |(split, lower_inf, lower_inc, upper_inf, upper_inc, (a, b))| {
5541 let mut row = Row::default();
5542 let mut packer = row.packer();
5543 let r = if split % 32 == 0 {
5544 packer
5545 .push_range(Range::new(None))
5546 .expect("pushing empty ranges never fails");
5547 None
5548 } else {
5549 let b_is_lower = Datum::from(&b) < Datum::from(&a);
5550
5551 let (lower, upper) = if b_is_lower { (b, a) } else { (a, b) };
5552 let mut range = Range::new(Some((
5553 RangeLowerBound {
5554 inclusive: lower_inc,
5555 bound: if lower_inf {
5556 None
5557 } else {
5558 Some(Datum::from(&lower))
5559 },
5560 },
5561 RangeUpperBound {
5562 inclusive: upper_inc,
5563 bound: if upper_inf {
5564 None
5565 } else {
5566 Some(Datum::from(&upper))
5567 },
5568 },
5569 )));
5570
5571 range.canonicalize().unwrap();
5572
5573 let (empty, lower_inf, lower_inc, upper_inf, upper_inc) = match range.inner {
5576 None => (true, false, false, false, false),
5577 Some(inner) => (
5578 false
5579 || match inner.lower.bound {
5580 Some(b) => b != Datum::from(&lower),
5581 None => !lower_inf,
5582 }
5583 || match inner.upper.bound {
5584 Some(b) => b != Datum::from(&upper),
5585 None => !upper_inf,
5586 },
5587 inner.lower.bound.is_none(),
5588 inner.lower.inclusive,
5589 inner.upper.bound.is_none(),
5590 inner.upper.inclusive,
5591 ),
5592 };
5593
5594 if empty {
5595 packer.push_range(Range { inner: None }).unwrap();
5596 None
5597 } else {
5598 packer.push_range(range).unwrap();
5599 Some((
5600 (
5601 if lower_inf {
5602 None
5603 } else {
5604 Some(Box::new(lower))
5605 },
5606 lower_inc,
5607 ),
5608 (
5609 if upper_inf {
5610 None
5611 } else {
5612 Some(Box::new(upper))
5613 },
5614 upper_inc,
5615 ),
5616 ))
5617 }
5618 };
5619
5620 PropRange(row, r)
5621 },
5622 )
5623 .boxed()
5624}
5625
5626#[derive(Debug, PartialEq, Clone)]
5627pub struct PropDict(Row, Vec<(String, PropDatum)>);
5628
5629fn arb_dict(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropDict> {
5630 let element_strategy = Union::new_weighted(vec![
5632 (20, element_strategy),
5633 (1, Just(PropDatum::Null).boxed()),
5634 ]);
5635
5636 prop::collection::vec((".*", element_strategy), 1..50)
5637 .prop_map(|mut entries| {
5638 entries.sort_by_key(|(k, _)| k.clone());
5639 entries.dedup_by_key(|(k, _)| k.clone());
5640 let mut row = Row::default();
5641 let entry_iter = entries.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
5642 row.packer().push_dict(entry_iter);
5643 PropDict(row, entries)
5644 })
5645 .boxed()
5646}
5647
5648fn arb_record(
5649 fields: impl Iterator<Item = (String, BoxedStrategy<PropDatum>)>,
5650) -> BoxedStrategy<PropDict> {
5651 let (names, strategies): (Vec<_>, Vec<_>) = fields.unzip();
5652
5653 strategies
5654 .prop_map(move |x| {
5655 let mut row = Row::default();
5656 row.packer().push_list(x.iter().map(Datum::from));
5657 let entries: Vec<_> = names.clone().into_iter().zip_eq(x).collect();
5658 PropDict(row, entries)
5659 })
5660 .boxed()
5661}
5662
5663fn arb_date() -> BoxedStrategy<Date> {
5664 (Date::LOW_DAYS..Date::HIGH_DAYS)
5665 .prop_map(move |days| Date::from_pg_epoch(days).unwrap())
5666 .boxed()
5667}
5668
5669pub fn add_arb_duration<T: 'static + Copy + Add<chrono::Duration> + std::fmt::Debug>(
5670 to: T,
5671) -> BoxedStrategy<T::Output>
5672where
5673 T::Output: std::fmt::Debug,
5674{
5675 let lower = LOW_DATE
5676 .and_hms_opt(0, 0, 0)
5677 .unwrap()
5678 .and_utc()
5679 .timestamp_micros();
5680 let upper = HIGH_DATE
5681 .and_hms_opt(0, 0, 0)
5682 .unwrap()
5683 .and_utc()
5684 .timestamp_micros();
5685 (lower..upper)
5686 .prop_map(move |v| to + chrono::Duration::microseconds(v))
5687 .boxed()
5688}
5689
5690pub(crate) fn arb_numeric() -> BoxedStrategy<Numeric> {
5691 let int_value = any::<i128>()
5692 .prop_map(|v| Numeric::try_from(v).unwrap())
5693 .boxed();
5694 let float_value = (-1e39f64..1e39)
5695 .prop_map(|v| Numeric::try_from(v).unwrap())
5696 .boxed();
5697
5698 let tiny_floats = ((-10.0..10.0), (1u32..10))
5701 .prop_map(|(v, num_digits)| {
5702 let num_digits: f64 = 10u32.pow(num_digits).try_into().unwrap();
5704 let trunc = f64::trunc(v * num_digits) / num_digits;
5705 Numeric::try_from(trunc).unwrap()
5706 })
5707 .boxed();
5708 let small_ints = (-1_000_000..1_000_000)
5709 .prop_map(|v| Numeric::try_from(v).unwrap())
5710 .boxed();
5711 let small_floats = (-1_000_000.0..1_000_000.0)
5712 .prop_map(|v| Numeric::try_from(v).unwrap())
5713 .boxed();
5714
5715 Union::new_weighted(vec![
5716 (20, tiny_floats),
5717 (20, small_ints),
5718 (20, small_floats),
5719 (10, int_value),
5720 (10, float_value),
5721 (1, Just(Numeric::infinity()).boxed()),
5722 (1, Just(-Numeric::infinity()).boxed()),
5723 (1, Just(Numeric::nan()).boxed()),
5724 (1, Just(Numeric::zero()).boxed()),
5725 ])
5726 .boxed()
5727}
5728
5729impl<'a> From<&'a PropDatum> for Datum<'a> {
5730 #[inline]
5731 fn from(pd: &'a PropDatum) -> Self {
5732 use PropDatum::*;
5733 match pd {
5734 Null => Datum::Null,
5735 Bool(b) => Datum::from(*b),
5736 Int16(i) => Datum::from(*i),
5737 Int32(i) => Datum::from(*i),
5738 Int64(i) => Datum::from(*i),
5739 UInt8(u) => Datum::from(*u),
5740 UInt16(u) => Datum::from(*u),
5741 UInt32(u) => Datum::from(*u),
5742 UInt64(u) => Datum::from(*u),
5743 Float32(f) => Datum::from(*f),
5744 Float64(f) => Datum::from(*f),
5745 Date(d) => Datum::from(*d),
5746 Time(t) => Datum::from(*t),
5747 Timestamp(t) => Datum::from(*t),
5748 TimestampTz(t) => Datum::from(*t),
5749 MzTimestamp(t) => Datum::MzTimestamp((*t).into()),
5750 Interval(i) => Datum::from(*i),
5751 Numeric(s) => Datum::from(*s),
5752 Bytes(b) => Datum::from(&b[..]),
5753 String(s) => Datum::from(s.as_str()),
5754 Array(PropArray(row, _)) => {
5755 let array = row.unpack_first().unwrap_array();
5756 Datum::Array(array)
5757 }
5758 List(PropList(row, _)) => {
5759 let list = row.unpack_first().unwrap_list();
5760 Datum::List(list)
5761 }
5762 Map(PropDict(row, _)) => {
5763 let map = row.unpack_first().unwrap_map();
5764 Datum::Map(map)
5765 }
5766 Record(PropDict(row, _)) => {
5767 let list = row.unpack_first().unwrap_list();
5768 Datum::List(list)
5769 }
5770 Range(PropRange(row, _)) => {
5771 let d = row.unpack_first();
5772 assert!(matches!(d, Datum::Range(_)));
5773 d
5774 }
5775 AclItem(i) => Datum::AclItem(*i),
5776 MzAclItem(i) => Datum::MzAclItem(*i),
5777 JsonNull => Datum::JsonNull,
5778 Uuid(u) => Datum::from(*u),
5779 Dummy => Datum::Dummy,
5780 }
5781 }
5782}
5783
5784#[mz_ore::test]
5785fn verify_base_eq_record_nullability() {
5786 let s1 = SqlScalarType::Record {
5787 fields: [(
5788 "c".into(),
5789 SqlColumnType {
5790 scalar_type: SqlScalarType::Bool,
5791 nullable: true,
5792 },
5793 )]
5794 .into(),
5795 custom_id: None,
5796 };
5797 let s2 = SqlScalarType::Record {
5798 fields: [(
5799 "c".into(),
5800 SqlColumnType {
5801 scalar_type: SqlScalarType::Bool,
5802 nullable: false,
5803 },
5804 )]
5805 .into(),
5806 custom_id: None,
5807 };
5808 let s3 = SqlScalarType::Record {
5809 fields: [].into(),
5810 custom_id: None,
5811 };
5812 assert!(s1.base_eq(&s2));
5813 assert!(!s1.base_eq(&s3));
5814}
5815
5816#[cfg(test)]
5817mod tests {
5818 use mz_ore::assert_ok;
5819 use mz_proto::protobuf_roundtrip;
5820
5821 use super::*;
5822
5823 proptest! {
5824 #[mz_ore::test]
5825 #[cfg_attr(miri, ignore)] fn scalar_type_protobuf_roundtrip(expect in any::<SqlScalarType>() ) {
5827 let actual = protobuf_roundtrip::<_, ProtoScalarType>(&expect);
5828 assert_ok!(actual);
5829 assert_eq!(actual.unwrap(), expect);
5830 }
5831 }
5832
5833 proptest! {
5834 #[mz_ore::test]
5835 #[cfg_attr(miri, ignore)]
5836 fn sql_repr_types_agree_on_valid_data(
5837 (src, datum) in any::<SqlColumnType>()
5838 .prop_flat_map(|src| {
5839 let datum = arb_datum_for_column(src.clone());
5840 (Just(src), datum)
5841 }),
5842 ) {
5843 let tgt = ReprColumnType::from(&src);
5844 let datum = Datum::from(&datum);
5845 assert_eq!(
5846 datum.is_instance_of_sql(&src),
5847 datum.is_instance_of(&tgt),
5848 "translated to repr type {tgt:#?}",
5849 );
5850 }
5851 }
5852
5853 proptest! {
5854 #![proptest_config(ProptestConfig::with_cases(10000))]
5857 #[mz_ore::test]
5858 #[cfg_attr(miri, ignore)]
5859 fn sql_repr_types_agree_on_random_data(
5860 src in any::<SqlColumnType>(),
5861 datum in arb_datum(true),
5862 ) {
5863 let tgt = ReprColumnType::from(&src);
5864 let datum = Datum::from(&datum);
5865
5866 assert_eq!(
5867 datum.is_instance_of_sql(&src),
5868 datum.is_instance_of(&tgt),
5869 "translated to repr type {tgt:#?}",
5870 );
5871 }
5872 }
5873
5874 proptest! {
5875 #![proptest_config(ProptestConfig::with_cases(10000))]
5876 #[mz_ore::test]
5877 #[cfg_attr(miri, ignore)]
5878 fn repr_type_to_sql_type_roundtrip(repr_type in any::<ReprScalarType>()) {
5879 let sql_type = SqlScalarType::from_repr(&repr_type);
5884 assert_eq!(repr_type, ReprScalarType::from(&sql_type));
5885 }
5886 }
5887
5888 proptest! {
5889 #![proptest_config(ProptestConfig::with_cases(10000))]
5890 #[mz_ore::test]
5891 #[cfg_attr(miri, ignore)]
5892 fn sql_type_base_eq_implies_repr_type_eq(
5893 sql_type1 in any::<SqlScalarType>(),
5894 sql_type2 in any::<SqlScalarType>(),
5895 ) {
5896 let repr_type1 = ReprScalarType::from(&sql_type1);
5897 let repr_type2 = ReprScalarType::from(&sql_type2);
5898 if sql_type1.base_eq(&sql_type2) {
5899 assert_eq!(repr_type1, repr_type2);
5900 }
5901 }
5902 }
5903
5904 proptest! {
5905 #![proptest_config(ProptestConfig::with_cases(10000))]
5906 #[mz_ore::test]
5907 #[cfg_attr(miri, ignore)]
5908 fn repr_type_self_union(repr_type in any::<ReprScalarType>()) {
5909 let union = repr_type.union(&repr_type);
5910 assert_ok!(
5911 union,
5912 "every type should self-union \
5913 (update ReprScalarType::union to handle this)",
5914 );
5915 assert_eq!(
5916 union.unwrap(), repr_type,
5917 "every type should self-union to itself",
5918 );
5919 }
5920 }
5921
5922 proptest! {
5923 #[mz_ore::test]
5924 #[cfg_attr(miri, ignore)] fn array_packing_unpacks_correctly(array in arb_array(arb_datum(true))) {
5926 let PropArray(row, elts) = array;
5927 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
5928 let unpacked_datums: Vec<Datum<'_>> = row
5929 .unpack_first().unwrap_array().elements().iter().collect();
5930 assert_eq!(unpacked_datums, datums);
5931 }
5932
5933 #[mz_ore::test]
5934 #[cfg_attr(miri, ignore)] fn list_packing_unpacks_correctly(array in arb_list(arb_datum(true))) {
5936 let PropList(row, elts) = array;
5937 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
5938 let unpacked_datums: Vec<Datum<'_>> = row
5939 .unpack_first().unwrap_list().iter().collect();
5940 assert_eq!(unpacked_datums, datums);
5941 }
5942
5943 #[mz_ore::test]
5944 #[cfg_attr(miri, ignore)] fn dict_packing_unpacks_correctly(array in arb_dict(arb_datum(true))) {
5946 let PropDict(row, elts) = array;
5947 let datums: Vec<(&str, Datum<'_>)> = elts.iter()
5948 .map(|(k, e)| (k.as_str(), e.into())).collect();
5949 let unpacked_datums: Vec<(&str, Datum<'_>)> = row
5950 .unpack_first().unwrap_map().iter().collect();
5951 assert_eq!(unpacked_datums, datums);
5952 }
5953
5954 #[mz_ore::test]
5955 #[cfg_attr(miri, ignore)] fn row_packing_roundtrips_single_valued(
5957 prop_datums in prop::collection::vec(arb_datum(true), 1..100),
5958 ) {
5959 let datums: Vec<Datum<'_>> = prop_datums.iter().map(|pd| pd.into()).collect();
5960 let row = Row::pack(&datums);
5961 let unpacked = row.unpack();
5962 assert_eq!(datums, unpacked);
5963 }
5964
5965 #[mz_ore::test]
5966 #[cfg_attr(miri, ignore)] fn range_packing_unpacks_correctly(range in arb_range(arb_range_data())) {
5968 let PropRange(row, prop_range) = range;
5969 let row = row.unpack_first();
5970 let d = row.unwrap_range();
5971
5972 let (
5973 ((prop_lower, prop_lower_inc), (prop_upper, prop_upper_inc)),
5974 crate::adt::range::RangeInner { lower, upper },
5975 ) = match (prop_range, d.inner) {
5976 (Some(prop_values), Some(inner_range)) => (prop_values, inner_range),
5977 (None, None) => return Ok(()),
5978 _ => panic!("inequivalent row packing"),
5979 };
5980
5981 for (prop_bound, prop_bound_inc, inner_bound, inner_bound_inc) in [
5982 (prop_lower, prop_lower_inc, lower.bound, lower.inclusive),
5983 (prop_upper, prop_upper_inc, upper.bound, upper.inclusive),
5984 ] {
5985 assert_eq!(prop_bound_inc, inner_bound_inc);
5986 match (prop_bound, inner_bound) {
5987 (None, None) => continue,
5988 (Some(p), Some(b)) => {
5989 assert_eq!(Datum::from(&*p), b);
5990 }
5991 _ => panic!("inequivalent row packing"),
5992 }
5993 }
5994 }
5995 }
5996}