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