1use std::collections::BTreeMap;
11use std::fmt::{self, Debug};
12use std::hash::Hash;
13use std::iter;
14use std::ops::Add;
15use std::sync::LazyLock;
16
17use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
18use dec::OrderedDecimal;
19use enum_kinds::EnumKind;
20use itertools::Itertools;
21use mz_lowertest::MzReflect;
22use mz_ore::Overflowing;
23use mz_ore::cast::CastFrom;
24use mz_ore::str::StrExt;
25use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
26use ordered_float::OrderedFloat;
27use proptest::prelude::*;
28use proptest::strategy::Union;
29use serde::{Deserialize, Serialize};
30use uuid::Uuid;
31
32use crate::adt::array::{Array, ArrayDimension};
33use crate::adt::char::{Char, CharLength};
34use crate::adt::date::Date;
35use crate::adt::interval::Interval;
36use crate::adt::jsonb::{Jsonb, JsonbRef};
37use crate::adt::mz_acl_item::{AclItem, AclMode, MzAclItem};
38use crate::adt::numeric::{Numeric, NumericMaxScale};
39use crate::adt::pg_legacy_name::PgLegacyName;
40use crate::adt::range::{Range, RangeLowerBound, RangeUpperBound};
41use crate::adt::system::{Oid, PgLegacyChar, RegClass, RegProc, RegType};
42use crate::adt::timestamp::{
43 CheckedTimestamp, HIGH_DATE, LOW_DATE, TimestampError, TimestampPrecision,
44};
45use crate::adt::varchar::{VarChar, VarCharMaxLength};
46pub use crate::relation_and_scalar::ProtoScalarType;
47pub use crate::relation_and_scalar::proto_scalar_type::ProtoRecordField;
48use crate::role_id::RoleId;
49use crate::row::DatumNested;
50use crate::{CatalogItemId, ColumnName, ColumnType, DatumList, DatumMap, Row, RowArena};
51
52#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, EnumKind)]
72#[enum_kind(DatumKind)]
73pub enum Datum<'a> {
74 False,
76 True,
78 Int16(i16),
80 Int32(i32),
82 Int64(i64),
84 UInt8(u8),
86 UInt16(u16),
88 UInt32(u32),
90 UInt64(u64),
92 Float32(OrderedFloat<f32>),
94 Float64(OrderedFloat<f64>),
96 Date(Date),
98 Time(NaiveTime),
100 Timestamp(CheckedTimestamp<NaiveDateTime>),
103 TimestampTz(CheckedTimestamp<DateTime<Utc>>),
105 Interval(Interval),
107 Bytes(&'a [u8]),
109 String(&'a str),
111 Array(Array<'a>),
114 List(DatumList<'a>),
118 Map(DatumMap<'a>),
120 Numeric(OrderedDecimal<Numeric>),
123 JsonNull,
128 Uuid(Uuid),
130 MzTimestamp(crate::Timestamp),
131 Range(Range<DatumNested<'a>>),
133 MzAclItem(MzAclItem),
136 AclItem(AclItem),
139 Dummy,
156 Null,
164 }
170
171impl TryFrom<Datum<'_>> for bool {
172 type Error = ();
173
174 #[inline]
175 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
176 match from {
177 Datum::False => Ok(false),
178 Datum::True => Ok(true),
179 _ => Err(()),
180 }
181 }
182}
183
184impl TryFrom<Datum<'_>> for Option<bool> {
185 type Error = ();
186
187 #[inline]
188 fn try_from(datum: Datum<'_>) -> Result<Self, Self::Error> {
189 match datum {
190 Datum::Null => Ok(None),
191 Datum::False => Ok(Some(false)),
192 Datum::True => Ok(Some(true)),
193 _ => Err(()),
194 }
195 }
196}
197
198impl TryFrom<Datum<'_>> for f32 {
199 type Error = ();
200
201 #[inline]
202 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
203 match from {
204 Datum::Float32(f) => Ok(*f),
205 _ => Err(()),
206 }
207 }
208}
209
210impl TryFrom<Datum<'_>> for Option<f32> {
211 type Error = ();
212
213 #[inline]
214 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
215 match from {
216 Datum::Null => Ok(None),
217 Datum::Float32(f) => Ok(Some(*f)),
218 _ => Err(()),
219 }
220 }
221}
222
223impl TryFrom<Datum<'_>> for OrderedFloat<f32> {
224 type Error = ();
225
226 #[inline]
227 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
228 match from {
229 Datum::Float32(f) => Ok(f),
230 _ => Err(()),
231 }
232 }
233}
234
235impl TryFrom<Datum<'_>> for Option<OrderedFloat<f32>> {
236 type Error = ();
237
238 #[inline]
239 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
240 match from {
241 Datum::Null => Ok(None),
242 Datum::Float32(f) => Ok(Some(f)),
243 _ => Err(()),
244 }
245 }
246}
247
248impl TryFrom<Datum<'_>> for f64 {
249 type Error = ();
250
251 #[inline]
252 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
253 match from {
254 Datum::Float64(f) => Ok(*f),
255 _ => Err(()),
256 }
257 }
258}
259
260impl TryFrom<Datum<'_>> for Option<f64> {
261 type Error = ();
262
263 #[inline]
264 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
265 match from {
266 Datum::Null => Ok(None),
267 Datum::Float64(f) => Ok(Some(*f)),
268 _ => Err(()),
269 }
270 }
271}
272
273impl TryFrom<Datum<'_>> for OrderedFloat<f64> {
274 type Error = ();
275
276 #[inline]
277 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
278 match from {
279 Datum::Float64(f) => Ok(f),
280 _ => Err(()),
281 }
282 }
283}
284
285impl TryFrom<Datum<'_>> for Option<OrderedFloat<f64>> {
286 type Error = ();
287
288 #[inline]
289 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
290 match from {
291 Datum::Null => Ok(None),
292 Datum::Float64(f) => Ok(Some(f)),
293 _ => Err(()),
294 }
295 }
296}
297
298impl TryFrom<Datum<'_>> for i16 {
299 type Error = ();
300
301 #[inline]
302 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
303 match from {
304 Datum::Int16(i) => Ok(i),
305 _ => Err(()),
306 }
307 }
308}
309
310impl TryFrom<Datum<'_>> for Option<i16> {
311 type Error = ();
312
313 #[inline]
314 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
315 match from {
316 Datum::Null => Ok(None),
317 Datum::Int16(i) => Ok(Some(i)),
318 _ => Err(()),
319 }
320 }
321}
322
323impl TryFrom<Datum<'_>> for i32 {
324 type Error = ();
325
326 #[inline]
327 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
328 match from {
329 Datum::Int32(i) => Ok(i),
330 _ => Err(()),
331 }
332 }
333}
334
335impl TryFrom<Datum<'_>> for Option<i32> {
336 type Error = ();
337
338 #[inline]
339 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
340 match from {
341 Datum::Null => Ok(None),
342 Datum::Int32(i) => Ok(Some(i)),
343 _ => Err(()),
344 }
345 }
346}
347
348impl TryFrom<Datum<'_>> for i64 {
349 type Error = ();
350
351 #[inline]
352 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
353 match from {
354 Datum::Int64(i) => Ok(i),
355 _ => Err(()),
356 }
357 }
358}
359
360impl TryFrom<Datum<'_>> for Option<i64> {
361 type Error = ();
362
363 #[inline]
364 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
365 match from {
366 Datum::Null => Ok(None),
367 Datum::Int64(i) => Ok(Some(i)),
368 _ => Err(()),
369 }
370 }
371}
372
373impl TryFrom<Datum<'_>> for u16 {
374 type Error = ();
375
376 #[inline]
377 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
378 match from {
379 Datum::UInt16(u) => Ok(u),
380 _ => Err(()),
381 }
382 }
383}
384
385impl TryFrom<Datum<'_>> for Option<u16> {
386 type Error = ();
387
388 #[inline]
389 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
390 match from {
391 Datum::Null => Ok(None),
392 Datum::UInt16(u) => Ok(Some(u)),
393 _ => Err(()),
394 }
395 }
396}
397
398impl TryFrom<Datum<'_>> for u32 {
399 type Error = ();
400
401 #[inline]
402 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
403 match from {
404 Datum::UInt32(u) => Ok(u),
405 _ => Err(()),
406 }
407 }
408}
409
410impl TryFrom<Datum<'_>> for Option<u32> {
411 type Error = ();
412
413 #[inline]
414 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
415 match from {
416 Datum::Null => Ok(None),
417 Datum::UInt32(u) => Ok(Some(u)),
418 _ => Err(()),
419 }
420 }
421}
422
423impl TryFrom<Datum<'_>> for u64 {
424 type Error = ();
425
426 #[inline]
427 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
428 match from {
429 Datum::UInt64(u) => Ok(u),
430 _ => Err(()),
431 }
432 }
433}
434
435impl TryFrom<Datum<'_>> for Option<u64> {
436 type Error = ();
437
438 #[inline]
439 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
440 match from {
441 Datum::Null => Ok(None),
442 Datum::UInt64(u) => Ok(Some(u)),
443 _ => Err(()),
444 }
445 }
446}
447
448impl TryFrom<Datum<'_>> for CheckedTimestamp<NaiveDateTime> {
449 type Error = ();
450
451 #[inline]
452 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
453 match from {
454 Datum::Timestamp(dt) => Ok(dt),
455 _ => Err(()),
456 }
457 }
458}
459
460impl TryFrom<Datum<'_>> for CheckedTimestamp<DateTime<Utc>> {
461 type Error = ();
462
463 #[inline]
464 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
465 match from {
466 Datum::TimestampTz(dt_tz) => Ok(dt_tz),
467 _ => Err(()),
468 }
469 }
470}
471
472impl TryFrom<Datum<'_>> for Date {
473 type Error = ();
474
475 #[inline]
476 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
477 match from {
478 Datum::Date(d) => Ok(d),
479 _ => Err(()),
480 }
481 }
482}
483
484impl TryFrom<Datum<'_>> for OrderedDecimal<Numeric> {
485 type Error = ();
486
487 #[inline]
488 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
489 match from {
490 Datum::Numeric(n) => Ok(n),
491 _ => Err(()),
492 }
493 }
494}
495
496impl TryFrom<Datum<'_>> for Option<OrderedDecimal<Numeric>> {
497 type Error = ();
498
499 #[inline]
500 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
501 match from {
502 Datum::Null => Ok(None),
503 Datum::Numeric(n) => Ok(Some(n)),
504 _ => Err(()),
505 }
506 }
507}
508
509impl TryFrom<Datum<'_>> for crate::Timestamp {
510 type Error = ();
511
512 #[inline]
513 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
514 match from {
515 Datum::MzTimestamp(n) => Ok(n),
516 _ => Err(()),
517 }
518 }
519}
520
521impl TryFrom<Datum<'_>> for Option<crate::Timestamp> {
522 type Error = ();
523
524 #[inline]
525 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
526 match from {
527 Datum::Null => Ok(None),
528 Datum::MzTimestamp(n) => Ok(Some(n)),
529 _ => Err(()),
530 }
531 }
532}
533
534impl TryFrom<Datum<'_>> for Interval {
535 type Error = ();
536
537 #[inline]
538 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
539 match from {
540 Datum::Interval(i) => Ok(i),
541 _ => Err(()),
542 }
543 }
544}
545
546impl TryFrom<Datum<'_>> for Option<Interval> {
547 type Error = ();
548
549 #[inline]
550 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
551 match from {
552 Datum::Null => Ok(None),
553 Datum::Interval(i) => Ok(Some(i)),
554 _ => Err(()),
555 }
556 }
557}
558
559impl TryFrom<Datum<'_>> for NaiveTime {
560 type Error = ();
561
562 #[inline]
563 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
564 match from {
565 Datum::Time(t) => Ok(t),
566 _ => Err(()),
567 }
568 }
569}
570
571impl TryFrom<Datum<'_>> for Option<NaiveTime> {
572 type Error = ();
573
574 #[inline]
575 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
576 match from {
577 Datum::Null => Ok(None),
578 Datum::Time(t) => Ok(Some(t)),
579 _ => Err(()),
580 }
581 }
582}
583
584impl<'a> Datum<'a> {
585 pub fn is_null(&self) -> bool {
587 matches!(self, Datum::Null)
588 }
589
590 #[track_caller]
596 pub fn unwrap_bool(&self) -> bool {
597 match self {
598 Datum::False => false,
599 Datum::True => true,
600 _ => panic!("Datum::unwrap_bool called on {:?}", self),
601 }
602 }
603
604 #[track_caller]
610 pub fn unwrap_int16(&self) -> i16 {
611 match self {
612 Datum::Int16(i) => *i,
613 _ => panic!("Datum::unwrap_int16 called on {:?}", self),
614 }
615 }
616
617 #[track_caller]
623 pub fn unwrap_int32(&self) -> i32 {
624 match self {
625 Datum::Int32(i) => *i,
626 _ => panic!("Datum::unwrap_int32 called on {:?}", self),
627 }
628 }
629
630 #[track_caller]
636 pub fn unwrap_int64(&self) -> i64 {
637 match self {
638 Datum::Int64(i) => *i,
639 _ => panic!("Datum::unwrap_int64 called on {:?}", self),
640 }
641 }
642
643 #[track_caller]
649 pub fn unwrap_uint8(&self) -> u8 {
650 match self {
651 Datum::UInt8(u) => *u,
652 _ => panic!("Datum::unwrap_uint8 called on {:?}", self),
653 }
654 }
655
656 #[track_caller]
662 pub fn unwrap_uint16(&self) -> u16 {
663 match self {
664 Datum::UInt16(u) => *u,
665 _ => panic!("Datum::unwrap_uint16 called on {:?}", self),
666 }
667 }
668
669 #[track_caller]
675 pub fn unwrap_uint32(&self) -> u32 {
676 match self {
677 Datum::UInt32(u) => *u,
678 _ => panic!("Datum::unwrap_uint32 called on {:?}", self),
679 }
680 }
681
682 #[track_caller]
688 pub fn unwrap_uint64(&self) -> u64 {
689 match self {
690 Datum::UInt64(u) => *u,
691 _ => panic!("Datum::unwrap_uint64 called on {:?}", self),
692 }
693 }
694
695 #[track_caller]
696 pub fn unwrap_ordered_float32(&self) -> OrderedFloat<f32> {
697 match self {
698 Datum::Float32(f) => *f,
699 _ => panic!("Datum::unwrap_ordered_float32 called on {:?}", self),
700 }
701 }
702
703 #[track_caller]
704 pub fn unwrap_ordered_float64(&self) -> OrderedFloat<f64> {
705 match self {
706 Datum::Float64(f) => *f,
707 _ => panic!("Datum::unwrap_ordered_float64 called on {:?}", self),
708 }
709 }
710
711 #[track_caller]
717 pub fn unwrap_float32(&self) -> f32 {
718 match self {
719 Datum::Float32(f) => f.into_inner(),
720 _ => panic!("Datum::unwrap_float32 called on {:?}", self),
721 }
722 }
723
724 #[track_caller]
730 pub fn unwrap_float64(&self) -> f64 {
731 match self {
732 Datum::Float64(f) => f.into_inner(),
733 _ => panic!("Datum::unwrap_float64 called on {:?}", self),
734 }
735 }
736
737 #[track_caller]
743 pub fn unwrap_date(&self) -> Date {
744 match self {
745 Datum::Date(d) => *d,
746 _ => panic!("Datum::unwrap_date called on {:?}", self),
747 }
748 }
749
750 #[track_caller]
756 pub fn unwrap_time(&self) -> chrono::NaiveTime {
757 match self {
758 Datum::Time(t) => *t,
759 _ => panic!("Datum::unwrap_time called on {:?}", self),
760 }
761 }
762
763 #[track_caller]
769 pub fn unwrap_timestamp(&self) -> CheckedTimestamp<chrono::NaiveDateTime> {
770 match self {
771 Datum::Timestamp(ts) => *ts,
772 _ => panic!("Datum::unwrap_timestamp called on {:?}", self),
773 }
774 }
775
776 #[track_caller]
782 pub fn unwrap_timestamptz(&self) -> CheckedTimestamp<chrono::DateTime<Utc>> {
783 match self {
784 Datum::TimestampTz(ts) => *ts,
785 _ => panic!("Datum::unwrap_timestamptz called on {:?}", self),
786 }
787 }
788
789 #[track_caller]
795 pub fn unwrap_interval(&self) -> Interval {
796 match self {
797 Datum::Interval(iv) => *iv,
798 _ => panic!("Datum::unwrap_interval called on {:?}", self),
799 }
800 }
801
802 #[track_caller]
808 pub fn unwrap_str(&self) -> &'a str {
809 match self {
810 Datum::String(s) => s,
811 _ => panic!("Datum::unwrap_string called on {:?}", self),
812 }
813 }
814
815 #[track_caller]
821 pub fn unwrap_bytes(&self) -> &'a [u8] {
822 match self {
823 Datum::Bytes(b) => b,
824 _ => panic!("Datum::unwrap_bytes called on {:?}", self),
825 }
826 }
827
828 #[track_caller]
834 pub fn unwrap_uuid(&self) -> Uuid {
835 match self {
836 Datum::Uuid(u) => *u,
837 _ => panic!("Datum::unwrap_uuid called on {:?}", self),
838 }
839 }
840
841 #[track_caller]
847 pub fn unwrap_array(&self) -> Array<'a> {
848 match self {
849 Datum::Array(array) => *array,
850 _ => panic!("Datum::unwrap_array called on {:?}", self),
851 }
852 }
853
854 #[track_caller]
860 pub fn unwrap_list(&self) -> DatumList<'a> {
861 match self {
862 Datum::List(list) => *list,
863 _ => panic!("Datum::unwrap_list called on {:?}", self),
864 }
865 }
866
867 #[track_caller]
873 pub fn unwrap_map(&self) -> DatumMap<'a> {
874 match self {
875 Datum::Map(dict) => *dict,
876 _ => panic!("Datum::unwrap_dict called on {:?}", self),
877 }
878 }
879
880 #[track_caller]
886 pub fn unwrap_numeric(&self) -> OrderedDecimal<Numeric> {
887 match self {
888 Datum::Numeric(n) => *n,
889 _ => panic!("Datum::unwrap_numeric called on {:?}", self),
890 }
891 }
892
893 #[track_caller]
899 pub fn unwrap_mz_timestamp(&self) -> crate::Timestamp {
900 match self {
901 Datum::MzTimestamp(t) => *t,
902 _ => panic!("Datum::unwrap_mz_timestamp called on {:?}", self),
903 }
904 }
905
906 #[track_caller]
917 pub fn unwrap_range(&self) -> Range<Datum<'a>> {
918 match self {
919 Datum::Range(range) => range.into_bounds(|b| b.datum()),
920 _ => panic!("Datum::unwrap_range called on {:?}", self),
921 }
922 }
923
924 #[track_caller]
930 pub fn unwrap_mz_acl_item(&self) -> MzAclItem {
931 match self {
932 Datum::MzAclItem(mz_acl_item) => *mz_acl_item,
933 _ => panic!("Datum::unwrap_mz_acl_item called on {:?}", self),
934 }
935 }
936
937 #[track_caller]
943 pub fn unwrap_acl_item(&self) -> AclItem {
944 match self {
945 Datum::AclItem(acl_item) => *acl_item,
946 _ => panic!("Datum::unwrap_acl_item called on {:?}", self),
947 }
948 }
949
950 pub fn is_instance_of(self, column_type: &ColumnType) -> bool {
952 fn is_instance_of_scalar(datum: Datum, scalar_type: &ScalarType) -> bool {
953 if let ScalarType::Jsonb = scalar_type {
954 match datum {
956 Datum::JsonNull
957 | Datum::False
958 | Datum::True
959 | Datum::Numeric(_)
960 | Datum::String(_) => true,
961 Datum::List(list) => list
962 .iter()
963 .all(|elem| is_instance_of_scalar(elem, scalar_type)),
964 Datum::Map(dict) => dict
965 .iter()
966 .all(|(_key, val)| is_instance_of_scalar(val, scalar_type)),
967 _ => false,
968 }
969 } else {
970 match (datum, scalar_type) {
972 (Datum::Dummy, _) => panic!("Datum::Dummy observed"),
973 (Datum::Null, _) => false,
974 (Datum::False, ScalarType::Bool) => true,
975 (Datum::False, _) => false,
976 (Datum::True, ScalarType::Bool) => true,
977 (Datum::True, _) => false,
978 (Datum::Int16(_), ScalarType::Int16) => true,
979 (Datum::Int16(_), _) => false,
980 (Datum::Int32(_), ScalarType::Int32) => true,
981 (Datum::Int32(_), _) => false,
982 (Datum::Int64(_), ScalarType::Int64) => true,
983 (Datum::Int64(_), _) => false,
984 (Datum::UInt8(_), ScalarType::PgLegacyChar) => true,
985 (Datum::UInt8(_), _) => false,
986 (Datum::UInt16(_), ScalarType::UInt16) => true,
987 (Datum::UInt16(_), _) => false,
988 (Datum::UInt32(_), ScalarType::Oid) => true,
989 (Datum::UInt32(_), ScalarType::RegClass) => true,
990 (Datum::UInt32(_), ScalarType::RegProc) => true,
991 (Datum::UInt32(_), ScalarType::RegType) => true,
992 (Datum::UInt32(_), ScalarType::UInt32) => true,
993 (Datum::UInt32(_), _) => false,
994 (Datum::UInt64(_), ScalarType::UInt64) => true,
995 (Datum::UInt64(_), _) => false,
996 (Datum::Float32(_), ScalarType::Float32) => true,
997 (Datum::Float32(_), _) => false,
998 (Datum::Float64(_), ScalarType::Float64) => true,
999 (Datum::Float64(_), _) => false,
1000 (Datum::Date(_), ScalarType::Date) => true,
1001 (Datum::Date(_), _) => false,
1002 (Datum::Time(_), ScalarType::Time) => true,
1003 (Datum::Time(_), _) => false,
1004 (Datum::Timestamp(_), ScalarType::Timestamp { .. }) => true,
1005 (Datum::Timestamp(_), _) => false,
1006 (Datum::TimestampTz(_), ScalarType::TimestampTz { .. }) => true,
1007 (Datum::TimestampTz(_), _) => false,
1008 (Datum::Interval(_), ScalarType::Interval) => true,
1009 (Datum::Interval(_), _) => false,
1010 (Datum::Bytes(_), ScalarType::Bytes) => true,
1011 (Datum::Bytes(_), _) => false,
1012 (Datum::String(_), ScalarType::String)
1013 | (Datum::String(_), ScalarType::VarChar { .. })
1014 | (Datum::String(_), ScalarType::Char { .. })
1015 | (Datum::String(_), ScalarType::PgLegacyName) => true,
1016 (Datum::String(_), _) => false,
1017 (Datum::Uuid(_), ScalarType::Uuid) => true,
1018 (Datum::Uuid(_), _) => false,
1019 (Datum::Array(array), ScalarType::Array(t)) => {
1020 array.elements.iter().all(|e| match e {
1021 Datum::Null => true,
1022 _ => is_instance_of_scalar(e, t),
1023 })
1024 }
1025 (Datum::Array(array), ScalarType::Int2Vector) => {
1026 array.dims().len() == 1
1027 && array
1028 .elements
1029 .iter()
1030 .all(|e| is_instance_of_scalar(e, &ScalarType::Int16))
1031 }
1032 (Datum::Array(_), _) => false,
1033 (Datum::List(list), ScalarType::List { element_type, .. }) => list
1034 .iter()
1035 .all(|e| e.is_null() || is_instance_of_scalar(e, element_type)),
1036 (Datum::List(list), ScalarType::Record { fields, .. }) => {
1037 list.iter().zip_eq(fields).all(|(e, (_, t))| {
1038 (e.is_null() && t.nullable) || is_instance_of_scalar(e, &t.scalar_type)
1039 })
1040 }
1041 (Datum::List(_), _) => false,
1042 (Datum::Map(map), ScalarType::Map { value_type, .. }) => map
1043 .iter()
1044 .all(|(_k, v)| v.is_null() || is_instance_of_scalar(v, value_type)),
1045 (Datum::Map(_), _) => false,
1046 (Datum::JsonNull, _) => false,
1047 (Datum::Numeric(_), ScalarType::Numeric { .. }) => true,
1048 (Datum::Numeric(_), _) => false,
1049 (Datum::MzTimestamp(_), ScalarType::MzTimestamp) => true,
1050 (Datum::MzTimestamp(_), _) => false,
1051 (Datum::Range(Range { inner }), ScalarType::Range { element_type }) => {
1052 match inner {
1053 None => true,
1054 Some(inner) => {
1055 true && match inner.lower.bound {
1056 None => true,
1057 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1058 } && match inner.upper.bound {
1059 None => true,
1060 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1061 }
1062 }
1063 }
1064 }
1065 (Datum::Range(_), _) => false,
1066 (Datum::MzAclItem(_), ScalarType::MzAclItem) => true,
1067 (Datum::MzAclItem(_), _) => false,
1068 (Datum::AclItem(_), ScalarType::AclItem) => true,
1069 (Datum::AclItem(_), _) => false,
1070 }
1071 }
1072 }
1073 if column_type.nullable {
1074 if let Datum::Null = self {
1075 return true;
1076 }
1077 }
1078 is_instance_of_scalar(self, &column_type.scalar_type)
1079 }
1080}
1081
1082impl<'a> From<bool> for Datum<'a> {
1083 #[inline]
1084 fn from(b: bool) -> Datum<'a> {
1085 if b { Datum::True } else { Datum::False }
1086 }
1087}
1088
1089impl<'a, T> From<Overflowing<T>> for Datum<'a>
1092where
1093 Datum<'a>: From<T>,
1094{
1095 #[inline]
1096 fn from(i: Overflowing<T>) -> Datum<'a> {
1097 Datum::from(i.into_inner())
1098 }
1099}
1100
1101impl<'a> From<i16> for Datum<'a> {
1102 #[inline]
1103 fn from(i: i16) -> Datum<'a> {
1104 Datum::Int16(i)
1105 }
1106}
1107
1108impl<'a> From<i32> for Datum<'a> {
1109 #[inline]
1110 fn from(i: i32) -> Datum<'a> {
1111 Datum::Int32(i)
1112 }
1113}
1114
1115impl<'a> From<i64> for Datum<'a> {
1116 #[inline]
1117 fn from(i: i64) -> Datum<'a> {
1118 Datum::Int64(i)
1119 }
1120}
1121
1122impl<'a> From<u8> for Datum<'a> {
1123 #[inline]
1124 fn from(u: u8) -> Datum<'a> {
1125 Datum::UInt8(u)
1126 }
1127}
1128
1129impl<'a> From<u16> for Datum<'a> {
1130 #[inline]
1131 fn from(u: u16) -> Datum<'a> {
1132 Datum::UInt16(u)
1133 }
1134}
1135
1136impl<'a> From<u32> for Datum<'a> {
1137 #[inline]
1138 fn from(u: u32) -> Datum<'a> {
1139 Datum::UInt32(u)
1140 }
1141}
1142
1143impl<'a> From<u64> for Datum<'a> {
1144 #[inline]
1145 fn from(u: u64) -> Datum<'a> {
1146 Datum::UInt64(u)
1147 }
1148}
1149
1150impl<'a> From<OrderedFloat<f32>> for Datum<'a> {
1151 #[inline]
1152 fn from(f: OrderedFloat<f32>) -> Datum<'a> {
1153 Datum::Float32(f)
1154 }
1155}
1156
1157impl<'a> From<OrderedFloat<f64>> for Datum<'a> {
1158 #[inline]
1159 fn from(f: OrderedFloat<f64>) -> Datum<'a> {
1160 Datum::Float64(f)
1161 }
1162}
1163
1164impl<'a> From<f32> for Datum<'a> {
1165 #[inline]
1166 fn from(f: f32) -> Datum<'a> {
1167 Datum::Float32(OrderedFloat(f))
1168 }
1169}
1170
1171impl<'a> From<f64> for Datum<'a> {
1172 #[inline]
1173 fn from(f: f64) -> Datum<'a> {
1174 Datum::Float64(OrderedFloat(f))
1175 }
1176}
1177
1178impl<'a> From<i128> for Datum<'a> {
1179 #[inline]
1180 fn from(d: i128) -> Datum<'a> {
1181 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1182 }
1183}
1184
1185impl<'a> From<u128> for Datum<'a> {
1186 #[inline]
1187 fn from(d: u128) -> Datum<'a> {
1188 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1189 }
1190}
1191
1192impl<'a> From<Numeric> for Datum<'a> {
1193 #[inline]
1194 fn from(n: Numeric) -> Datum<'a> {
1195 Datum::Numeric(OrderedDecimal(n))
1196 }
1197}
1198
1199impl<'a> From<OrderedDecimal<Numeric>> for Datum<'a> {
1200 #[inline]
1201 fn from(n: OrderedDecimal<Numeric>) -> Datum<'a> {
1202 Datum::Numeric(n)
1203 }
1204}
1205
1206impl<'a> From<chrono::Duration> for Datum<'a> {
1207 #[inline]
1208 fn from(duration: chrono::Duration) -> Datum<'a> {
1209 let micros = duration.num_microseconds().unwrap_or(0);
1210 Datum::Interval(Interval::new(0, 0, micros))
1211 }
1212}
1213
1214impl<'a> From<Interval> for Datum<'a> {
1215 #[inline]
1216 fn from(other: Interval) -> Datum<'a> {
1217 Datum::Interval(other)
1218 }
1219}
1220
1221impl<'a> From<&'a str> for Datum<'a> {
1222 #[inline]
1223 fn from(s: &'a str) -> Datum<'a> {
1224 Datum::String(s)
1225 }
1226}
1227
1228impl<'a> From<&'a [u8]> for Datum<'a> {
1229 #[inline]
1230 fn from(b: &'a [u8]) -> Datum<'a> {
1231 Datum::Bytes(b)
1232 }
1233}
1234
1235impl<'a> From<Date> for Datum<'a> {
1236 #[inline]
1237 fn from(d: Date) -> Datum<'a> {
1238 Datum::Date(d)
1239 }
1240}
1241
1242impl<'a> From<NaiveTime> for Datum<'a> {
1243 #[inline]
1244 fn from(t: NaiveTime) -> Datum<'a> {
1245 Datum::Time(t)
1246 }
1247}
1248
1249impl<'a> From<CheckedTimestamp<NaiveDateTime>> for Datum<'a> {
1250 #[inline]
1251 fn from(dt: CheckedTimestamp<NaiveDateTime>) -> Datum<'a> {
1252 Datum::Timestamp(dt)
1253 }
1254}
1255
1256impl<'a> From<CheckedTimestamp<DateTime<Utc>>> for Datum<'a> {
1257 #[inline]
1258 fn from(dt: CheckedTimestamp<DateTime<Utc>>) -> Datum<'a> {
1259 Datum::TimestampTz(dt)
1260 }
1261}
1262
1263impl<'a> TryInto<Datum<'a>> for NaiveDateTime {
1264 type Error = TimestampError;
1265
1266 #[inline]
1267 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1268 let t = CheckedTimestamp::from_timestamplike(self)?;
1269 Ok(t.into())
1270 }
1271}
1272
1273impl<'a> TryInto<Datum<'a>> for DateTime<Utc> {
1274 type Error = TimestampError;
1275
1276 #[inline]
1277 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1278 let t = CheckedTimestamp::from_timestamplike(self)?;
1279 Ok(t.into())
1280 }
1281}
1282
1283impl<'a> From<Uuid> for Datum<'a> {
1284 #[inline]
1285 fn from(uuid: Uuid) -> Datum<'a> {
1286 Datum::Uuid(uuid)
1287 }
1288}
1289impl<'a> From<crate::Timestamp> for Datum<'a> {
1290 #[inline]
1291 fn from(ts: crate::Timestamp) -> Datum<'a> {
1292 Datum::MzTimestamp(ts)
1293 }
1294}
1295
1296impl<'a> From<MzAclItem> for Datum<'a> {
1297 #[inline]
1298 fn from(mz_acl_item: MzAclItem) -> Self {
1299 Datum::MzAclItem(mz_acl_item)
1300 }
1301}
1302
1303impl<'a, T> From<Option<T>> for Datum<'a>
1304where
1305 Datum<'a>: From<T>,
1306{
1307 fn from(o: Option<T>) -> Datum<'a> {
1308 match o {
1309 Some(d) => d.into(),
1310 None => Datum::Null,
1311 }
1312 }
1313}
1314
1315fn write_delimited<T, TS, F>(
1316 f: &mut fmt::Formatter,
1317 delimiter: &str,
1318 things: TS,
1319 write: F,
1320) -> fmt::Result
1321where
1322 TS: IntoIterator<Item = T>,
1323 F: Fn(&mut fmt::Formatter, T) -> fmt::Result,
1324{
1325 let mut iter = things.into_iter().peekable();
1326 while let Some(thing) = iter.next() {
1327 write(f, thing)?;
1328 if iter.peek().is_some() {
1329 f.write_str(delimiter)?;
1330 }
1331 }
1332 Ok(())
1333}
1334
1335impl fmt::Display for Datum<'_> {
1336 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1337 match self {
1338 Datum::Null => f.write_str("null"),
1339 Datum::True => f.write_str("true"),
1340 Datum::False => f.write_str("false"),
1341 Datum::Int16(num) => write!(f, "{}", num),
1342 Datum::Int32(num) => write!(f, "{}", num),
1343 Datum::Int64(num) => write!(f, "{}", num),
1344 Datum::UInt8(num) => write!(f, "{}", num),
1345 Datum::UInt16(num) => write!(f, "{}", num),
1346 Datum::UInt32(num) => write!(f, "{}", num),
1347 Datum::UInt64(num) => write!(f, "{}", num),
1348 Datum::Float32(num) => write!(f, "{}", num),
1349 Datum::Float64(num) => write!(f, "{}", num),
1350 Datum::Date(d) => write!(f, "{}", d),
1351 Datum::Time(t) => write!(f, "{}", t),
1352 Datum::Timestamp(t) => write!(f, "{}", t),
1353 Datum::TimestampTz(t) => write!(f, "{}", t),
1354 Datum::Interval(iv) => write!(f, "{}", iv),
1355 Datum::Bytes(dat) => {
1356 f.write_str("0x")?;
1357 for b in dat.iter() {
1358 write!(f, "{:02x}", b)?;
1359 }
1360 Ok(())
1361 }
1362 Datum::String(s) => {
1363 write!(f, "{}", s.escaped())
1364 }
1365 Datum::Uuid(u) => write!(f, "{}", u),
1366 Datum::Array(array) => {
1367 if array.dims().into_iter().any(|dim| dim.lower_bound != 1) {
1368 write_delimited(f, "", array.dims().into_iter(), |f, e| {
1369 let (lower, upper) = e.dimension_bounds();
1370 write!(f, "[{}:{}]", lower, upper)
1371 })?;
1372 f.write_str("=")?;
1373 }
1374 f.write_str("{")?;
1375 write_delimited(f, ", ", &array.elements, |f, e| write!(f, "{}", e))?;
1376 f.write_str("}")
1377 }
1378 Datum::List(list) => {
1379 f.write_str("[")?;
1380 write_delimited(f, ", ", list, |f, e| write!(f, "{}", e))?;
1381 f.write_str("]")
1382 }
1383 Datum::Map(dict) => {
1384 f.write_str("{")?;
1385 write_delimited(f, ", ", dict, |f, (k, v)| write!(f, "{}: {}", k, v))?;
1386 f.write_str("}")
1387 }
1388 Datum::Numeric(n) => write!(f, "{}", n.0.to_standard_notation_string()),
1389 Datum::MzTimestamp(t) => write!(f, "{}", t),
1390 Datum::JsonNull => f.write_str("json_null"),
1391 Datum::Dummy => f.write_str("dummy"),
1392 Datum::Range(i) => write!(f, "{}", i),
1393 Datum::MzAclItem(mz_acl_item) => write!(f, "{mz_acl_item}"),
1394 Datum::AclItem(acl_item) => write!(f, "{acl_item}"),
1395 }
1396 }
1397}
1398
1399#[derive(
1404 Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash, EnumKind, MzReflect,
1405)]
1406#[enum_kind(ScalarBaseType, derive(PartialOrd, Ord, Hash))]
1407pub enum ScalarType {
1408 Bool,
1410 Int16,
1412 Int32,
1414 Int64,
1416 UInt16,
1418 UInt32,
1420 UInt64,
1422 Float32,
1424 Float64,
1426 Numeric {
1436 max_scale: Option<NumericMaxScale>,
1437 },
1438 Date,
1440 Time,
1442 Timestamp {
1444 precision: Option<TimestampPrecision>,
1445 },
1446 TimestampTz {
1448 precision: Option<TimestampPrecision>,
1449 },
1450 Interval,
1452 PgLegacyChar,
1457 PgLegacyName,
1463 Bytes,
1465 String,
1467 Char {
1473 length: Option<CharLength>,
1474 },
1475 VarChar {
1478 max_length: Option<VarCharMaxLength>,
1479 },
1480 Jsonb,
1492 Uuid,
1494 Array(Box<ScalarType>),
1500 List {
1505 element_type: Box<ScalarType>,
1506 custom_id: Option<CatalogItemId>,
1507 },
1508 Record {
1510 fields: Box<[(ColumnName, ColumnType)]>,
1515 custom_id: Option<CatalogItemId>,
1516 },
1517 Oid,
1519 Map {
1525 value_type: Box<ScalarType>,
1526 custom_id: Option<CatalogItemId>,
1527 },
1528 RegProc,
1530 RegType,
1532 RegClass,
1534 Int2Vector,
1537 MzTimestamp,
1539 Range {
1540 element_type: Box<ScalarType>,
1541 },
1542 MzAclItem,
1544 AclItem,
1546}
1547
1548impl RustType<ProtoRecordField> for (ColumnName, ColumnType) {
1549 fn into_proto(&self) -> ProtoRecordField {
1550 ProtoRecordField {
1551 column_name: Some(self.0.into_proto()),
1552 column_type: Some(self.1.into_proto()),
1553 }
1554 }
1555
1556 fn from_proto(proto: ProtoRecordField) -> Result<Self, TryFromProtoError> {
1557 Ok((
1558 proto
1559 .column_name
1560 .into_rust_if_some("ProtoRecordField::column_name")?,
1561 proto
1562 .column_type
1563 .into_rust_if_some("ProtoRecordField::column_type")?,
1564 ))
1565 }
1566}
1567
1568impl RustType<ProtoScalarType> for ScalarType {
1569 fn into_proto(&self) -> ProtoScalarType {
1570 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1571 use crate::relation_and_scalar::proto_scalar_type::*;
1572
1573 ProtoScalarType {
1574 kind: Some(match self {
1575 ScalarType::Bool => Bool(()),
1576 ScalarType::Int16 => Int16(()),
1577 ScalarType::Int32 => Int32(()),
1578 ScalarType::Int64 => Int64(()),
1579 ScalarType::UInt16 => UInt16(()),
1580 ScalarType::UInt32 => UInt32(()),
1581 ScalarType::UInt64 => UInt64(()),
1582 ScalarType::Float32 => Float32(()),
1583 ScalarType::Float64 => Float64(()),
1584 ScalarType::Date => Date(()),
1585 ScalarType::Time => Time(()),
1586 ScalarType::Timestamp { precision } => Timestamp(ProtoTimestamp {
1587 precision: precision.into_proto(),
1588 }),
1589 ScalarType::TimestampTz { precision } => TimestampTz(ProtoTimestampTz {
1590 precision: precision.into_proto(),
1591 }),
1592 ScalarType::Interval => Interval(()),
1593 ScalarType::PgLegacyChar => PgLegacyChar(()),
1594 ScalarType::PgLegacyName => PgLegacyName(()),
1595 ScalarType::Bytes => Bytes(()),
1596 ScalarType::String => String(()),
1597 ScalarType::Jsonb => Jsonb(()),
1598 ScalarType::Uuid => Uuid(()),
1599 ScalarType::Oid => Oid(()),
1600 ScalarType::RegProc => RegProc(()),
1601 ScalarType::RegType => RegType(()),
1602 ScalarType::RegClass => RegClass(()),
1603 ScalarType::Int2Vector => Int2Vector(()),
1604
1605 ScalarType::Numeric { max_scale } => Numeric(max_scale.into_proto()),
1606 ScalarType::Char { length } => Char(ProtoChar {
1607 length: length.into_proto(),
1608 }),
1609 ScalarType::VarChar { max_length } => VarChar(ProtoVarChar {
1610 max_length: max_length.into_proto(),
1611 }),
1612
1613 ScalarType::List {
1614 element_type,
1615 custom_id,
1616 } => List(Box::new(ProtoList {
1617 element_type: Some(element_type.into_proto()),
1618 custom_id: custom_id.map(|id| id.into_proto()),
1619 })),
1620 ScalarType::Record { custom_id, fields } => Record(ProtoRecord {
1621 custom_id: custom_id.map(|id| id.into_proto()),
1622 fields: fields.into_proto(),
1623 }),
1624 ScalarType::Array(typ) => Array(typ.into_proto()),
1625 ScalarType::Map {
1626 value_type,
1627 custom_id,
1628 } => Map(Box::new(ProtoMap {
1629 value_type: Some(value_type.into_proto()),
1630 custom_id: custom_id.map(|id| id.into_proto()),
1631 })),
1632 ScalarType::MzTimestamp => MzTimestamp(()),
1633 ScalarType::Range { element_type } => Range(Box::new(ProtoRange {
1634 element_type: Some(element_type.into_proto()),
1635 })),
1636 ScalarType::MzAclItem => MzAclItem(()),
1637 ScalarType::AclItem => AclItem(()),
1638 }),
1639 }
1640 }
1641
1642 fn from_proto(proto: ProtoScalarType) -> Result<Self, TryFromProtoError> {
1643 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1644
1645 let kind = proto
1646 .kind
1647 .ok_or_else(|| TryFromProtoError::missing_field("ProtoScalarType::Kind"))?;
1648
1649 match kind {
1650 Bool(()) => Ok(ScalarType::Bool),
1651 Int16(()) => Ok(ScalarType::Int16),
1652 Int32(()) => Ok(ScalarType::Int32),
1653 Int64(()) => Ok(ScalarType::Int64),
1654 UInt16(()) => Ok(ScalarType::UInt16),
1655 UInt32(()) => Ok(ScalarType::UInt32),
1656 UInt64(()) => Ok(ScalarType::UInt64),
1657 Float32(()) => Ok(ScalarType::Float32),
1658 Float64(()) => Ok(ScalarType::Float64),
1659 Date(()) => Ok(ScalarType::Date),
1660 Time(()) => Ok(ScalarType::Time),
1661 Timestamp(x) => Ok(ScalarType::Timestamp {
1662 precision: x.precision.into_rust()?,
1663 }),
1664 TimestampTz(x) => Ok(ScalarType::TimestampTz {
1665 precision: x.precision.into_rust()?,
1666 }),
1667 Interval(()) => Ok(ScalarType::Interval),
1668 PgLegacyChar(()) => Ok(ScalarType::PgLegacyChar),
1669 PgLegacyName(()) => Ok(ScalarType::PgLegacyName),
1670 Bytes(()) => Ok(ScalarType::Bytes),
1671 String(()) => Ok(ScalarType::String),
1672 Jsonb(()) => Ok(ScalarType::Jsonb),
1673 Uuid(()) => Ok(ScalarType::Uuid),
1674 Oid(()) => Ok(ScalarType::Oid),
1675 RegProc(()) => Ok(ScalarType::RegProc),
1676 RegType(()) => Ok(ScalarType::RegType),
1677 RegClass(()) => Ok(ScalarType::RegClass),
1678 Int2Vector(()) => Ok(ScalarType::Int2Vector),
1679
1680 Numeric(x) => Ok(ScalarType::Numeric {
1681 max_scale: x.into_rust()?,
1682 }),
1683 Char(x) => Ok(ScalarType::Char {
1684 length: x.length.into_rust()?,
1685 }),
1686
1687 VarChar(x) => Ok(ScalarType::VarChar {
1688 max_length: x.max_length.into_rust()?,
1689 }),
1690 Array(x) => Ok(ScalarType::Array({
1691 let st: ScalarType = (*x).into_rust()?;
1692 st.into()
1693 })),
1694 List(x) => Ok(ScalarType::List {
1695 element_type: Box::new(
1696 x.element_type
1697 .map(|x| *x)
1698 .into_rust_if_some("ProtoList::element_type")?,
1699 ),
1700 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1701 }),
1702 Record(x) => Ok(ScalarType::Record {
1703 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1704 fields: x.fields.into_rust()?,
1705 }),
1706 Map(x) => Ok(ScalarType::Map {
1707 value_type: Box::new(
1708 x.value_type
1709 .map(|x| *x)
1710 .into_rust_if_some("ProtoMap::value_type")?,
1711 ),
1712 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1713 }),
1714 MzTimestamp(()) => Ok(ScalarType::MzTimestamp),
1715 Range(x) => Ok(ScalarType::Range {
1716 element_type: Box::new(
1717 x.element_type
1718 .map(|x| *x)
1719 .into_rust_if_some("ProtoRange::element_type")?,
1720 ),
1721 }),
1722 MzAclItem(()) => Ok(ScalarType::MzAclItem),
1723 AclItem(()) => Ok(ScalarType::AclItem),
1724 }
1725 }
1726}
1727
1728pub trait AsColumnType {
1730 fn as_column_type() -> ColumnType;
1732}
1733
1734pub trait DatumType<'a, E>: Sized {
1736 fn nullable() -> bool;
1738
1739 fn fallible() -> bool;
1741
1742 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>>;
1745
1746 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E>;
1748}
1749
1750#[derive(Debug)]
1753pub struct ArrayRustType<T>(pub Vec<T>);
1754
1755impl<B: AsColumnType> AsColumnType for Option<B> {
1756 fn as_column_type() -> ColumnType {
1757 B::as_column_type().nullable(true)
1758 }
1759}
1760
1761impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for Option<B> {
1762 fn nullable() -> bool {
1763 true
1764 }
1765 fn fallible() -> bool {
1766 false
1767 }
1768 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1769 match res {
1770 Ok(Datum::Null) => Ok(None),
1771 Ok(datum) => B::try_from_result(Ok(datum)).map(Some),
1772 _ => Err(res),
1773 }
1774 }
1775 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1776 match self {
1777 Some(inner) => inner.into_result(temp_storage),
1778 None => Ok(Datum::Null),
1779 }
1780 }
1781}
1782
1783impl<E, B: AsColumnType> AsColumnType for Result<B, E> {
1784 fn as_column_type() -> ColumnType {
1785 B::as_column_type()
1786 }
1787}
1788
1789impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for Result<B, E> {
1790 fn nullable() -> bool {
1791 B::nullable()
1792 }
1793 fn fallible() -> bool {
1794 true
1795 }
1796 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1797 B::try_from_result(res).map(Ok)
1798 }
1799 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1800 self.and_then(|inner| inner.into_result(temp_storage))
1801 }
1802}
1803
1804macro_rules! impl_datum_type_copy {
1806 ($lt:lifetime, $native:ty, $variant:ident) => {
1807 impl<$lt> AsColumnType for $native {
1808 fn as_column_type() -> ColumnType {
1809 ScalarType::$variant.nullable(false)
1810 }
1811 }
1812
1813 impl<$lt, E> DatumType<$lt, E> for $native {
1814 fn nullable() -> bool {
1815 false
1816 }
1817
1818 fn fallible() -> bool {
1819 false
1820 }
1821
1822 fn try_from_result(res: Result<Datum<$lt>, E>) -> Result<Self, Result<Datum<$lt>, E>> {
1823 match res {
1824 Ok(Datum::$variant(f)) => Ok(f.into()),
1825 _ => Err(res),
1826 }
1827 }
1828
1829 fn into_result(self, _temp_storage: &$lt RowArena) -> Result<Datum<$lt>, E> {
1830 Ok(Datum::$variant(self.into()))
1831 }
1832 }
1833 };
1834 ($native:ty, $variant:ident) => {
1835 impl_datum_type_copy!('a, $native, $variant);
1836 };
1837}
1838
1839impl_datum_type_copy!(f32, Float32);
1840impl_datum_type_copy!(f64, Float64);
1841impl_datum_type_copy!(i16, Int16);
1842impl_datum_type_copy!(i32, Int32);
1843impl_datum_type_copy!(i64, Int64);
1844impl_datum_type_copy!(u16, UInt16);
1845impl_datum_type_copy!(u32, UInt32);
1846impl_datum_type_copy!(u64, UInt64);
1847impl_datum_type_copy!(Interval, Interval);
1848impl_datum_type_copy!(Date, Date);
1849impl_datum_type_copy!(NaiveTime, Time);
1850impl_datum_type_copy!(Uuid, Uuid);
1851impl_datum_type_copy!('a, &'a str, String);
1852impl_datum_type_copy!('a, &'a [u8], Bytes);
1853impl_datum_type_copy!(crate::Timestamp, MzTimestamp);
1854
1855impl<'a, E> DatumType<'a, E> for Datum<'a> {
1856 fn nullable() -> bool {
1857 true
1858 }
1859
1860 fn fallible() -> bool {
1861 false
1862 }
1863
1864 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1865 match res {
1866 Ok(datum) => Ok(datum),
1867 _ => Err(res),
1868 }
1869 }
1870
1871 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1872 Ok(self)
1873 }
1874}
1875
1876impl<'a, E> DatumType<'a, E> for DatumList<'a> {
1877 fn nullable() -> bool {
1878 false
1879 }
1880
1881 fn fallible() -> bool {
1882 false
1883 }
1884
1885 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1886 match res {
1887 Ok(Datum::List(list)) => Ok(list),
1888 _ => Err(res),
1889 }
1890 }
1891
1892 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1893 Ok(Datum::List(self))
1894 }
1895}
1896
1897impl<'a, E> DatumType<'a, E> for DatumMap<'a> {
1898 fn nullable() -> bool {
1899 false
1900 }
1901
1902 fn fallible() -> bool {
1903 false
1904 }
1905
1906 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1907 match res {
1908 Ok(Datum::Map(map)) => Ok(map),
1909 _ => Err(res),
1910 }
1911 }
1912
1913 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1914 Ok(Datum::Map(self))
1915 }
1916}
1917
1918impl<'a, E> DatumType<'a, E> for Range<DatumNested<'a>> {
1919 fn nullable() -> bool {
1920 false
1921 }
1922
1923 fn fallible() -> bool {
1924 false
1925 }
1926
1927 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1928 match res {
1929 Ok(Datum::Range(range)) => Ok(range),
1930 _ => Err(res),
1931 }
1932 }
1933
1934 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1935 Ok(Datum::Range(self))
1936 }
1937}
1938
1939impl<'a, E> DatumType<'a, E> for Range<Datum<'a>> {
1940 fn nullable() -> bool {
1941 false
1942 }
1943
1944 fn fallible() -> bool {
1945 false
1946 }
1947
1948 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1949 match res {
1950 Ok(r @ Datum::Range(..)) => Ok(r.unwrap_range()),
1951 _ => Err(res),
1952 }
1953 }
1954
1955 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1956 let d =
1957 self.into_bounds(|bound| temp_storage.make_datum_nested(|packer| packer.push(bound)));
1958 Ok(Datum::Range(d))
1959 }
1960}
1961
1962impl AsColumnType for bool {
1963 fn as_column_type() -> ColumnType {
1964 ScalarType::Bool.nullable(false)
1965 }
1966}
1967
1968impl<'a, E> DatumType<'a, E> for bool {
1969 fn nullable() -> bool {
1970 false
1971 }
1972
1973 fn fallible() -> bool {
1974 false
1975 }
1976
1977 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1978 match res {
1979 Ok(Datum::True) => Ok(true),
1980 Ok(Datum::False) => Ok(false),
1981 _ => Err(res),
1982 }
1983 }
1984
1985 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1986 if self {
1987 Ok(Datum::True)
1988 } else {
1989 Ok(Datum::False)
1990 }
1991 }
1992}
1993
1994impl AsColumnType for String {
1995 fn as_column_type() -> ColumnType {
1996 ScalarType::String.nullable(false)
1997 }
1998}
1999
2000impl<'a, E> DatumType<'a, E> for String {
2001 fn nullable() -> bool {
2002 false
2003 }
2004
2005 fn fallible() -> bool {
2006 false
2007 }
2008
2009 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2010 match res {
2011 Ok(Datum::String(s)) => Ok(s.to_owned()),
2012 _ => Err(res),
2013 }
2014 }
2015
2016 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2017 Ok(Datum::String(temp_storage.push_string(self)))
2018 }
2019}
2020
2021impl AsColumnType for ArrayRustType<String> {
2022 fn as_column_type() -> ColumnType {
2023 ScalarType::Array(Box::new(ScalarType::String)).nullable(false)
2024 }
2025}
2026
2027impl<'a, E> DatumType<'a, E> for ArrayRustType<String> {
2028 fn nullable() -> bool {
2029 false
2030 }
2031
2032 fn fallible() -> bool {
2033 false
2034 }
2035
2036 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2037 match res {
2038 Ok(Datum::Array(arr)) => Ok(ArrayRustType(
2039 arr.elements()
2040 .into_iter()
2041 .map(|d| d.unwrap_str().to_string())
2042 .collect(),
2043 )),
2044 _ => Err(res),
2045 }
2046 }
2047
2048 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2049 Ok(temp_storage.make_datum(|packer| {
2050 packer
2051 .try_push_array(
2052 &[ArrayDimension {
2053 lower_bound: 1,
2054 length: self.0.len(),
2055 }],
2056 self.0.iter().map(|elem| Datum::String(elem.as_str())),
2057 )
2058 .expect("self is 1 dimensional, and its length is used for the array length");
2059 }))
2060 }
2061}
2062
2063impl AsColumnType for Vec<u8> {
2064 fn as_column_type() -> ColumnType {
2065 ScalarType::Bytes.nullable(false)
2066 }
2067}
2068
2069impl<'a, E> DatumType<'a, E> for Vec<u8> {
2070 fn nullable() -> bool {
2071 false
2072 }
2073
2074 fn fallible() -> bool {
2075 false
2076 }
2077
2078 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2079 match res {
2080 Ok(Datum::Bytes(b)) => Ok(b.to_owned()),
2081 _ => Err(res),
2082 }
2083 }
2084
2085 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2086 Ok(Datum::Bytes(temp_storage.push_bytes(self)))
2087 }
2088}
2089
2090impl AsColumnType for Numeric {
2091 fn as_column_type() -> ColumnType {
2092 ScalarType::Numeric { max_scale: None }.nullable(false)
2093 }
2094}
2095
2096impl<'a, E> DatumType<'a, E> for Numeric {
2097 fn nullable() -> bool {
2098 false
2099 }
2100
2101 fn fallible() -> bool {
2102 false
2103 }
2104
2105 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2106 match res {
2107 Ok(Datum::Numeric(n)) => Ok(n.into_inner()),
2108 _ => Err(res),
2109 }
2110 }
2111
2112 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2113 Ok(Datum::from(self))
2114 }
2115}
2116
2117impl<'a, E> DatumType<'a, E> for OrderedDecimal<Numeric> {
2118 fn nullable() -> bool {
2119 false
2120 }
2121
2122 fn fallible() -> bool {
2123 false
2124 }
2125
2126 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2127 match res {
2128 Ok(Datum::Numeric(n)) => Ok(n),
2129 _ => Err(res),
2130 }
2131 }
2132
2133 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2134 Ok(Datum::from(self))
2135 }
2136}
2137
2138impl AsColumnType for PgLegacyChar {
2139 fn as_column_type() -> ColumnType {
2140 ScalarType::PgLegacyChar.nullable(false)
2141 }
2142}
2143
2144impl<'a, E> DatumType<'a, E> for PgLegacyChar {
2145 fn nullable() -> bool {
2146 false
2147 }
2148
2149 fn fallible() -> bool {
2150 false
2151 }
2152
2153 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2154 match res {
2155 Ok(Datum::UInt8(a)) => Ok(PgLegacyChar(a)),
2156 _ => Err(res),
2157 }
2158 }
2159
2160 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2161 Ok(Datum::UInt8(self.0))
2162 }
2163}
2164
2165impl<S> AsColumnType for PgLegacyName<S>
2166where
2167 S: AsRef<str>,
2168{
2169 fn as_column_type() -> ColumnType {
2170 ScalarType::PgLegacyName.nullable(false)
2171 }
2172}
2173
2174impl<'a, E> DatumType<'a, E> for PgLegacyName<&'a str> {
2175 fn nullable() -> bool {
2176 false
2177 }
2178
2179 fn fallible() -> bool {
2180 false
2181 }
2182
2183 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2184 match res {
2185 Ok(Datum::String(a)) => Ok(PgLegacyName(a)),
2186 _ => Err(res),
2187 }
2188 }
2189
2190 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2191 Ok(Datum::String(self.0))
2192 }
2193}
2194
2195impl<'a, E> DatumType<'a, E> for PgLegacyName<String> {
2196 fn nullable() -> bool {
2197 false
2198 }
2199
2200 fn fallible() -> bool {
2201 false
2202 }
2203
2204 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2205 match res {
2206 Ok(Datum::String(a)) => Ok(PgLegacyName(a.to_owned())),
2207 _ => Err(res),
2208 }
2209 }
2210
2211 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2212 Ok(Datum::String(temp_storage.push_string(self.0)))
2213 }
2214}
2215
2216impl AsColumnType for Oid {
2217 fn as_column_type() -> ColumnType {
2218 ScalarType::Oid.nullable(false)
2219 }
2220}
2221
2222impl<'a, E> DatumType<'a, E> for Oid {
2223 fn nullable() -> bool {
2224 false
2225 }
2226
2227 fn fallible() -> bool {
2228 false
2229 }
2230
2231 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2232 match res {
2233 Ok(Datum::UInt32(a)) => Ok(Oid(a)),
2234 _ => Err(res),
2235 }
2236 }
2237
2238 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2239 Ok(Datum::UInt32(self.0))
2240 }
2241}
2242
2243impl AsColumnType for RegClass {
2244 fn as_column_type() -> ColumnType {
2245 ScalarType::RegClass.nullable(false)
2246 }
2247}
2248
2249impl<'a, E> DatumType<'a, E> for RegClass {
2250 fn nullable() -> bool {
2251 false
2252 }
2253
2254 fn fallible() -> bool {
2255 false
2256 }
2257
2258 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2259 match res {
2260 Ok(Datum::UInt32(a)) => Ok(RegClass(a)),
2261 _ => Err(res),
2262 }
2263 }
2264
2265 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2266 Ok(Datum::UInt32(self.0))
2267 }
2268}
2269
2270impl AsColumnType for RegProc {
2271 fn as_column_type() -> ColumnType {
2272 ScalarType::RegProc.nullable(false)
2273 }
2274}
2275
2276impl<'a, E> DatumType<'a, E> for RegProc {
2277 fn nullable() -> bool {
2278 false
2279 }
2280
2281 fn fallible() -> bool {
2282 false
2283 }
2284
2285 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2286 match res {
2287 Ok(Datum::UInt32(a)) => Ok(RegProc(a)),
2288 _ => Err(res),
2289 }
2290 }
2291
2292 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2293 Ok(Datum::UInt32(self.0))
2294 }
2295}
2296
2297impl AsColumnType for RegType {
2298 fn as_column_type() -> ColumnType {
2299 ScalarType::RegType.nullable(false)
2300 }
2301}
2302
2303impl<'a, E> DatumType<'a, E> for RegType {
2304 fn nullable() -> bool {
2305 false
2306 }
2307
2308 fn fallible() -> bool {
2309 false
2310 }
2311
2312 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2313 match res {
2314 Ok(Datum::UInt32(a)) => Ok(RegType(a)),
2315 _ => Err(res),
2316 }
2317 }
2318
2319 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2320 Ok(Datum::UInt32(self.0))
2321 }
2322}
2323
2324impl<S> AsColumnType for Char<S>
2325where
2326 S: AsRef<str>,
2327{
2328 fn as_column_type() -> ColumnType {
2329 ScalarType::Char { length: None }.nullable(false)
2330 }
2331}
2332
2333impl<'a, E> DatumType<'a, E> for Char<&'a str> {
2334 fn nullable() -> bool {
2335 false
2336 }
2337
2338 fn fallible() -> bool {
2339 false
2340 }
2341
2342 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2343 match res {
2344 Ok(Datum::String(a)) => Ok(Char(a)),
2345 _ => Err(res),
2346 }
2347 }
2348
2349 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2350 Ok(Datum::String(self.0))
2351 }
2352}
2353
2354impl<'a, E> DatumType<'a, E> for Char<String> {
2355 fn nullable() -> bool {
2356 false
2357 }
2358
2359 fn fallible() -> bool {
2360 false
2361 }
2362
2363 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2364 match res {
2365 Ok(Datum::String(a)) => Ok(Char(a.to_owned())),
2366 _ => Err(res),
2367 }
2368 }
2369
2370 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2371 Ok(Datum::String(temp_storage.push_string(self.0)))
2372 }
2373}
2374
2375impl<S> AsColumnType for VarChar<S>
2376where
2377 S: AsRef<str>,
2378{
2379 fn as_column_type() -> ColumnType {
2380 ScalarType::Char { length: None }.nullable(false)
2381 }
2382}
2383
2384impl<'a, E> DatumType<'a, E> for VarChar<&'a str> {
2385 fn nullable() -> bool {
2386 false
2387 }
2388
2389 fn fallible() -> bool {
2390 false
2391 }
2392
2393 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2394 match res {
2395 Ok(Datum::String(a)) => Ok(VarChar(a)),
2396 _ => Err(res),
2397 }
2398 }
2399
2400 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2401 Ok(Datum::String(self.0))
2402 }
2403}
2404
2405impl<'a, E> DatumType<'a, E> for VarChar<String> {
2406 fn nullable() -> bool {
2407 false
2408 }
2409
2410 fn fallible() -> bool {
2411 false
2412 }
2413
2414 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2415 match res {
2416 Ok(Datum::String(a)) => Ok(VarChar(a.to_owned())),
2417 _ => Err(res),
2418 }
2419 }
2420
2421 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2422 Ok(Datum::String(temp_storage.push_string(self.0)))
2423 }
2424}
2425
2426impl<'a, E> DatumType<'a, E> for Jsonb {
2427 fn nullable() -> bool {
2428 false
2429 }
2430
2431 fn fallible() -> bool {
2432 false
2433 }
2434
2435 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2436 Ok(JsonbRef::try_from_result(res)?.to_owned())
2437 }
2438
2439 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2440 Ok(temp_storage.push_unary_row(self.into_row()))
2441 }
2442}
2443
2444impl AsColumnType for Jsonb {
2445 fn as_column_type() -> ColumnType {
2446 ScalarType::Jsonb.nullable(false)
2447 }
2448}
2449
2450impl<'a, E> DatumType<'a, E> for JsonbRef<'a> {
2451 fn nullable() -> bool {
2452 false
2453 }
2454
2455 fn fallible() -> bool {
2456 false
2457 }
2458
2459 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2460 match res {
2461 Ok(
2462 d @ (Datum::JsonNull
2463 | Datum::True
2464 | Datum::False
2465 | Datum::Numeric(_)
2466 | Datum::String(_)
2467 | Datum::List(_)
2468 | Datum::Map(_)),
2469 ) => Ok(JsonbRef::from_datum(d)),
2470 _ => Err(res),
2471 }
2472 }
2473
2474 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2475 Ok(self.into_datum())
2476 }
2477}
2478
2479impl<'a> AsColumnType for JsonbRef<'a> {
2480 fn as_column_type() -> ColumnType {
2481 ScalarType::Jsonb.nullable(false)
2482 }
2483}
2484
2485impl AsColumnType for MzAclItem {
2486 fn as_column_type() -> ColumnType {
2487 ScalarType::MzAclItem.nullable(false)
2488 }
2489}
2490
2491impl<'a, E> DatumType<'a, E> for MzAclItem {
2492 fn nullable() -> bool {
2493 false
2494 }
2495
2496 fn fallible() -> bool {
2497 false
2498 }
2499
2500 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2501 match res {
2502 Ok(Datum::MzAclItem(mz_acl_item)) => Ok(mz_acl_item),
2503 _ => Err(res),
2504 }
2505 }
2506
2507 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2508 Ok(Datum::MzAclItem(self))
2509 }
2510}
2511
2512impl AsColumnType for AclItem {
2513 fn as_column_type() -> ColumnType {
2514 ScalarType::AclItem.nullable(false)
2515 }
2516}
2517
2518impl<'a, E> DatumType<'a, E> for AclItem {
2519 fn nullable() -> bool {
2520 false
2521 }
2522
2523 fn fallible() -> bool {
2524 false
2525 }
2526
2527 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2528 match res {
2529 Ok(Datum::AclItem(acl_item)) => Ok(acl_item),
2530 _ => Err(res),
2531 }
2532 }
2533
2534 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2535 Ok(Datum::AclItem(self))
2536 }
2537}
2538
2539impl AsColumnType for CheckedTimestamp<NaiveDateTime> {
2540 fn as_column_type() -> ColumnType {
2541 ScalarType::Timestamp { precision: None }.nullable(false)
2542 }
2543}
2544
2545impl<'a, E> DatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
2546 fn nullable() -> bool {
2547 false
2548 }
2549
2550 fn fallible() -> bool {
2551 false
2552 }
2553
2554 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2555 match res {
2556 Ok(Datum::Timestamp(a)) => Ok(a),
2557 _ => Err(res),
2558 }
2559 }
2560
2561 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2562 Ok(Datum::Timestamp(self))
2563 }
2564}
2565
2566impl AsColumnType for CheckedTimestamp<DateTime<Utc>> {
2567 fn as_column_type() -> ColumnType {
2568 ScalarType::TimestampTz { precision: None }.nullable(false)
2569 }
2570}
2571
2572impl<'a, E> DatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
2573 fn nullable() -> bool {
2574 false
2575 }
2576
2577 fn fallible() -> bool {
2578 false
2579 }
2580
2581 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2582 match res {
2583 Ok(Datum::TimestampTz(a)) => Ok(a),
2584 _ => Err(res),
2585 }
2586 }
2587
2588 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2589 Ok(Datum::TimestampTz(self))
2590 }
2591}
2592
2593impl ScalarType {
2594 pub fn unwrap_numeric_max_scale(&self) -> Option<NumericMaxScale> {
2600 match self {
2601 ScalarType::Numeric { max_scale } => *max_scale,
2602 _ => panic!("ScalarType::unwrap_numeric_scale called on {:?}", self),
2603 }
2604 }
2605
2606 pub fn unwrap_timestamp_precision(&self) -> Option<TimestampPrecision> {
2613 match self {
2614 ScalarType::Timestamp { precision } | ScalarType::TimestampTz { precision } => {
2615 *precision
2616 }
2617 _ => panic!(
2618 "ScalarType::unwrap_timestamp_precision called on {:?}",
2619 self
2620 ),
2621 }
2622 }
2623
2624 pub fn unwrap_list_element_type(&self) -> &ScalarType {
2630 match self {
2631 ScalarType::List { element_type, .. } => element_type,
2632 _ => panic!("ScalarType::unwrap_list_element_type called on {:?}", self),
2633 }
2634 }
2635
2636 pub fn unwrap_list_nth_layer_type(&self, layer: usize) -> &ScalarType {
2649 if layer == 0 {
2650 return self;
2651 }
2652 match self {
2653 ScalarType::List { element_type, .. } => {
2654 element_type.unwrap_list_nth_layer_type(layer - 1)
2655 }
2656 _ => panic!(
2657 "ScalarType::unwrap_list_nth_layer_type called on {:?}",
2658 self
2659 ),
2660 }
2661 }
2662
2663 pub fn unwrap_record_element_type(&self) -> Vec<&ScalarType> {
2669 match self {
2670 ScalarType::Record { fields, .. } => {
2671 fields.iter().map(|(_, t)| &t.scalar_type).collect_vec()
2672 }
2673 _ => panic!(
2674 "ScalarType::unwrap_record_element_type called on {:?}",
2675 self
2676 ),
2677 }
2678 }
2679
2680 pub fn unwrap_record_element_column_type(&self) -> Vec<&ColumnType> {
2686 match self {
2687 ScalarType::Record { fields, .. } => fields.iter().map(|(_, t)| t).collect_vec(),
2688 _ => panic!(
2689 "ScalarType::unwrap_record_element_column_type called on {:?}",
2690 self
2691 ),
2692 }
2693 }
2694
2695 pub fn unwrap_list_n_layers(&self) -> usize {
2702 let mut descender = self.unwrap_list_element_type();
2703 let mut layers = 1;
2704
2705 while let ScalarType::List { element_type, .. } = descender {
2706 layers += 1;
2707 descender = element_type;
2708 }
2709
2710 layers
2711 }
2712
2713 pub fn without_modifiers(&self) -> ScalarType {
2717 use ScalarType::*;
2718 match self {
2719 List {
2720 element_type,
2721 custom_id: None,
2722 } => List {
2723 element_type: Box::new(element_type.without_modifiers()),
2724 custom_id: None,
2725 },
2726 Map {
2727 value_type,
2728 custom_id: None,
2729 } => Map {
2730 value_type: Box::new(value_type.without_modifiers()),
2731 custom_id: None,
2732 },
2733 Record {
2734 fields,
2735 custom_id: None,
2736 } => {
2737 let fields = fields
2738 .iter()
2739 .map(|(column_name, column_type)| {
2740 (
2741 column_name.clone(),
2742 ColumnType {
2743 scalar_type: column_type.scalar_type.without_modifiers(),
2744 nullable: column_type.nullable,
2745 },
2746 )
2747 })
2748 .collect();
2749 Record {
2750 fields,
2751 custom_id: None,
2752 }
2753 }
2754 Array(a) => Array(Box::new(a.without_modifiers())),
2755 Numeric { .. } => Numeric { max_scale: None },
2756 Char { .. } => Char { length: None },
2759 VarChar { .. } => VarChar { max_length: None },
2760 Range { element_type } => Range {
2761 element_type: Box::new(element_type.without_modifiers()),
2762 },
2763 v => v.clone(),
2764 }
2765 }
2766
2767 pub fn unwrap_array_element_type(&self) -> &ScalarType {
2776 match self {
2777 ScalarType::Array(s) => &**s,
2778 ScalarType::Int2Vector => &ScalarType::Int16,
2779 _ => panic!("ScalarType::unwrap_array_element_type called on {:?}", self),
2780 }
2781 }
2782
2783 pub fn unwrap_collection_element_type(&self) -> &ScalarType {
2791 match self {
2792 ScalarType::Array(element_type) => element_type,
2793 ScalarType::Int2Vector => &ScalarType::Int16,
2794 ScalarType::List { element_type, .. } => element_type,
2795 _ => panic!(
2796 "ScalarType::unwrap_collection_element_type called on {:?}",
2797 self
2798 ),
2799 }
2800 }
2801
2802 pub fn unwrap_map_value_type(&self) -> &ScalarType {
2808 match self {
2809 ScalarType::Map { value_type, .. } => &**value_type,
2810 _ => panic!("ScalarType::unwrap_map_value_type called on {:?}", self),
2811 }
2812 }
2813
2814 pub fn unwrap_char_length(&self) -> Option<CharLength> {
2820 match self {
2821 ScalarType::Char { length, .. } => *length,
2822 _ => panic!("ScalarType::unwrap_char_length called on {:?}", self),
2823 }
2824 }
2825
2826 pub fn unwrap_varchar_max_length(&self) -> Option<VarCharMaxLength> {
2832 match self {
2833 ScalarType::VarChar { max_length, .. } => *max_length,
2834 _ => panic!("ScalarType::unwrap_varchar_max_length called on {:?}", self),
2835 }
2836 }
2837
2838 pub fn unwrap_range_element_type(&self) -> &ScalarType {
2844 match self {
2845 ScalarType::Range { element_type } => &**element_type,
2846 _ => panic!("ScalarType::unwrap_range_element_type called on {:?}", self),
2847 }
2848 }
2849
2850 pub fn near_match(&self) -> Option<&'static ScalarType> {
2874 match self {
2875 ScalarType::UInt16 => Some(&ScalarType::Int32),
2876 ScalarType::UInt32 => Some(&ScalarType::Int64),
2877 ScalarType::UInt64 => Some(&ScalarType::Numeric { max_scale: None }),
2878 _ => None,
2879 }
2880 }
2881
2882 pub const fn nullable(self, nullable: bool) -> ColumnType {
2885 ColumnType {
2886 nullable,
2887 scalar_type: self,
2888 }
2889 }
2890
2891 pub fn is_vec(&self) -> bool {
2895 matches!(
2896 self,
2897 ScalarType::Array(_) | ScalarType::Int2Vector | ScalarType::List { .. }
2898 )
2899 }
2900
2901 pub fn is_custom_type(&self) -> bool {
2902 use ScalarType::*;
2903 match self {
2904 List {
2905 element_type: t,
2906 custom_id,
2907 }
2908 | Map {
2909 value_type: t,
2910 custom_id,
2911 } => custom_id.is_some() || t.is_custom_type(),
2912 Record {
2913 fields, custom_id, ..
2914 } => {
2915 custom_id.is_some()
2916 || fields
2917 .iter()
2918 .map(|(_, t)| t)
2919 .any(|t| t.scalar_type.is_custom_type())
2920 }
2921 _ => false,
2922 }
2923 }
2924
2925 pub fn base_eq(&self, other: &ScalarType) -> bool {
2938 self.eq_inner(other, false)
2939 }
2940
2941 pub fn structural_eq(&self, other: &ScalarType) -> bool {
2944 self.eq_inner(other, true)
2945 }
2946
2947 pub fn eq_inner(&self, other: &ScalarType, structure_only: bool) -> bool {
2948 use ScalarType::*;
2949 match (self, other) {
2950 (
2951 List {
2952 element_type: l,
2953 custom_id: oid_l,
2954 },
2955 List {
2956 element_type: r,
2957 custom_id: oid_r,
2958 },
2959 )
2960 | (
2961 Map {
2962 value_type: l,
2963 custom_id: oid_l,
2964 },
2965 Map {
2966 value_type: r,
2967 custom_id: oid_r,
2968 },
2969 ) => l.eq_inner(r, structure_only) && (oid_l == oid_r || structure_only),
2970 (Array(a), Array(b)) | (Range { element_type: a }, Range { element_type: b }) => {
2971 a.eq_inner(b, structure_only)
2972 }
2973 (
2974 Record {
2975 fields: fields_a,
2976 custom_id: oid_a,
2977 },
2978 Record {
2979 fields: fields_b,
2980 custom_id: oid_b,
2981 },
2982 ) => {
2983 (oid_a == oid_b || structure_only)
2984 && fields_a.len() == fields_b.len()
2985 && fields_a
2986 .iter()
2987 .zip(fields_b)
2988 .all(|(a, b)| {
2990 (a.0 == b.0 || structure_only)
2991 && a.1.scalar_type.eq_inner(&b.1.scalar_type, structure_only)
2992 })
2993 }
2994 (s, o) => ScalarBaseType::from(s) == ScalarBaseType::from(o),
2995 }
2996 }
2997
2998 pub fn interesting_datums(&self) -> impl Iterator<Item = Datum<'static>> {
3000 static BOOL: LazyLock<Row> =
3006 LazyLock::new(|| Row::pack_slice(&[Datum::True, Datum::False]));
3007 static INT16: LazyLock<Row> = LazyLock::new(|| {
3008 Row::pack_slice(&[
3009 Datum::Int16(0),
3010 Datum::Int16(1),
3011 Datum::Int16(-1),
3012 Datum::Int16(i16::MIN),
3013 Datum::Int16(i16::MIN + 1),
3014 Datum::Int16(i16::MAX),
3015 Datum::Int16(127),
3023 Datum::Int16(128),
3024 ])
3025 });
3026 static INT32: LazyLock<Row> = LazyLock::new(|| {
3027 Row::pack_slice(&[
3028 Datum::Int32(0),
3029 Datum::Int32(1),
3030 Datum::Int32(-1),
3031 Datum::Int32(i32::MIN),
3032 Datum::Int32(i32::MIN + 1),
3033 Datum::Int32(i32::MAX),
3034 Datum::Int32(32767),
3038 Datum::Int32(32768),
3039 ])
3040 });
3041 static INT64: LazyLock<Row> = LazyLock::new(|| {
3042 Row::pack_slice(&[
3043 Datum::Int64(0),
3044 Datum::Int64(1),
3045 Datum::Int64(-1),
3046 Datum::Int64(i64::MIN),
3047 Datum::Int64(i64::MIN + 1),
3048 Datum::Int64(i64::MAX),
3049 Datum::Int64(2147483647),
3053 Datum::Int64(2147483648),
3054 ])
3055 });
3056 static UINT16: LazyLock<Row> = LazyLock::new(|| {
3057 Row::pack_slice(&[
3058 Datum::UInt16(0),
3059 Datum::UInt16(1),
3060 Datum::UInt16(u16::MAX),
3061 Datum::UInt16(255),
3065 Datum::UInt16(256),
3066 ])
3067 });
3068 static UINT32: LazyLock<Row> = LazyLock::new(|| {
3069 Row::pack_slice(&[
3070 Datum::UInt32(0),
3071 Datum::UInt32(1),
3072 Datum::UInt32(u32::MAX),
3073 Datum::UInt32(32767),
3077 Datum::UInt32(32768),
3078 ])
3079 });
3080 static UINT64: LazyLock<Row> = LazyLock::new(|| {
3081 Row::pack_slice(&[
3082 Datum::UInt64(0),
3083 Datum::UInt64(1),
3084 Datum::UInt64(u64::MAX),
3085 Datum::UInt64(2147483647),
3089 Datum::UInt64(2147483648),
3090 ])
3091 });
3092 static FLOAT32: LazyLock<Row> = LazyLock::new(|| {
3093 Row::pack_slice(&[
3094 Datum::Float32(OrderedFloat(0.0)),
3095 Datum::Float32(OrderedFloat(1.0)),
3096 Datum::Float32(OrderedFloat(-1.0)),
3097 Datum::Float32(OrderedFloat(f32::MIN)),
3098 Datum::Float32(OrderedFloat(f32::MIN_POSITIVE)),
3099 Datum::Float32(OrderedFloat(f32::MAX)),
3100 Datum::Float32(OrderedFloat(f32::EPSILON)),
3101 Datum::Float32(OrderedFloat(f32::NAN)),
3102 Datum::Float32(OrderedFloat(f32::INFINITY)),
3103 Datum::Float32(OrderedFloat(f32::NEG_INFINITY)),
3104 ])
3105 });
3106 static FLOAT64: LazyLock<Row> = LazyLock::new(|| {
3107 Row::pack_slice(&[
3108 Datum::Float64(OrderedFloat(0.0)),
3109 Datum::Float64(OrderedFloat(1.0)),
3110 Datum::Float64(OrderedFloat(-1.0)),
3111 Datum::Float64(OrderedFloat(f64::MIN)),
3112 Datum::Float64(OrderedFloat(f64::MIN_POSITIVE)),
3113 Datum::Float64(OrderedFloat(f64::MAX)),
3114 Datum::Float64(OrderedFloat(f64::EPSILON)),
3115 Datum::Float64(OrderedFloat(f64::NAN)),
3116 Datum::Float64(OrderedFloat(f64::INFINITY)),
3117 Datum::Float64(OrderedFloat(f64::NEG_INFINITY)),
3118 ])
3119 });
3120 static NUMERIC: LazyLock<Row> = LazyLock::new(|| {
3121 cfg_if::cfg_if! {
3122 if #[cfg(miri)] {
3124 Row::pack_slice(&[])
3125 } else {
3126 Row::pack_slice(&[
3127 Datum::Numeric(OrderedDecimal(Numeric::from(0.0))),
3128 Datum::Numeric(OrderedDecimal(Numeric::from(1.0))),
3129 Datum::Numeric(OrderedDecimal(Numeric::from(-1.0))),
3130 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN))),
3131 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN_POSITIVE))),
3132 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MAX))),
3133 Datum::Numeric(OrderedDecimal(Numeric::from(f64::EPSILON))),
3134 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NAN))),
3135 Datum::Numeric(OrderedDecimal(Numeric::from(f64::INFINITY))),
3136 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NEG_INFINITY))),
3137 ])
3138 }
3139 }
3140 });
3141 static DATE: LazyLock<Row> = LazyLock::new(|| {
3142 Row::pack_slice(&[
3143 Datum::Date(Date::from_pg_epoch(0).unwrap()),
3144 Datum::Date(Date::from_pg_epoch(Date::LOW_DAYS).unwrap()),
3145 Datum::Date(Date::from_pg_epoch(Date::HIGH_DAYS).unwrap()),
3146 ])
3147 });
3148 static TIME: LazyLock<Row> = LazyLock::new(|| {
3149 Row::pack_slice(&[
3150 Datum::Time(NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap()),
3151 Datum::Time(NaiveTime::from_hms_micro_opt(23, 59, 59, 999_999).unwrap()),
3152 ])
3153 });
3154 static TIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3155 Row::pack_slice(&[
3156 Datum::Timestamp(
3157 DateTime::from_timestamp(0, 0)
3158 .unwrap()
3159 .naive_utc()
3160 .try_into()
3161 .unwrap(),
3162 ),
3163 Datum::Timestamp(
3164 crate::adt::timestamp::LOW_DATE
3165 .and_hms_opt(0, 0, 0)
3166 .unwrap()
3167 .try_into()
3168 .unwrap(),
3169 ),
3170 Datum::Timestamp(
3171 crate::adt::timestamp::HIGH_DATE
3172 .and_hms_opt(23, 59, 59)
3173 .unwrap()
3174 .try_into()
3175 .unwrap(),
3176 ),
3177 Datum::Timestamp(
3179 DateTime::from_timestamp(0, 123456789)
3180 .unwrap()
3181 .naive_utc()
3182 .try_into()
3183 .unwrap(),
3184 ),
3185 Datum::Timestamp(
3187 CheckedTimestamp::from_timestamplike(
3188 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
3189 .unwrap()
3190 .and_hms_milli_opt(23, 59, 59, 1234)
3191 .unwrap(),
3192 )
3193 .unwrap(),
3194 ),
3195 ])
3196 });
3197 static TIMESTAMPTZ: LazyLock<Row> = LazyLock::new(|| {
3198 Row::pack_slice(&[
3199 Datum::TimestampTz(DateTime::from_timestamp(0, 0).unwrap().try_into().unwrap()),
3200 Datum::TimestampTz(
3201 DateTime::from_naive_utc_and_offset(
3202 crate::adt::timestamp::LOW_DATE
3203 .and_hms_opt(0, 0, 0)
3204 .unwrap(),
3205 Utc,
3206 )
3207 .try_into()
3208 .unwrap(),
3209 ),
3210 Datum::TimestampTz(
3211 DateTime::from_naive_utc_and_offset(
3212 crate::adt::timestamp::HIGH_DATE
3213 .and_hms_opt(23, 59, 59)
3214 .unwrap(),
3215 Utc,
3216 )
3217 .try_into()
3218 .unwrap(),
3219 ),
3220 Datum::TimestampTz(
3222 DateTime::from_timestamp(0, 123456789)
3223 .unwrap()
3224 .try_into()
3225 .unwrap(),
3226 ),
3227 ])
3228 });
3229 static INTERVAL: LazyLock<Row> = LazyLock::new(|| {
3230 Row::pack_slice(&[
3231 Datum::Interval(Interval::new(0, 0, 0)),
3232 Datum::Interval(Interval::new(1, 1, 1)),
3233 Datum::Interval(Interval::new(-1, -1, -1)),
3234 Datum::Interval(Interval::new(1, 0, 0)),
3235 Datum::Interval(Interval::new(0, 1, 0)),
3236 Datum::Interval(Interval::new(0, 0, 1)),
3237 Datum::Interval(Interval::new(-1, 0, 0)),
3238 Datum::Interval(Interval::new(0, -1, 0)),
3239 Datum::Interval(Interval::new(0, 0, -1)),
3240 Datum::Interval(Interval::new(i32::MIN, i32::MIN, i64::MIN)),
3241 Datum::Interval(Interval::new(i32::MAX, i32::MAX, i64::MAX)),
3242 Datum::Interval(Interval::new(i32::MIN, 0, 0)),
3243 Datum::Interval(Interval::new(i32::MAX, 0, 0)),
3244 Datum::Interval(Interval::new(0, i32::MIN, 0)),
3245 Datum::Interval(Interval::new(0, i32::MAX, 0)),
3246 Datum::Interval(Interval::new(0, 0, i64::MIN)),
3247 Datum::Interval(Interval::new(0, 0, i64::MAX)),
3248 ])
3249 });
3250 static PGLEGACYCHAR: LazyLock<Row> =
3251 LazyLock::new(|| Row::pack_slice(&[Datum::UInt8(u8::MIN), Datum::UInt8(u8::MAX)]));
3252 static PGLEGACYNAME: LazyLock<Row> = LazyLock::new(|| {
3253 Row::pack_slice(&[
3254 Datum::String(""),
3255 Datum::String(" "),
3256 Datum::String("'"),
3257 Datum::String("\""),
3258 Datum::String("."),
3259 Datum::String(&"x".repeat(64)),
3260 ])
3261 });
3262 static BYTES: LazyLock<Row> = LazyLock::new(|| {
3263 Row::pack_slice(&[Datum::Bytes(&[]), Datum::Bytes(&[0]), Datum::Bytes(&[255])])
3264 });
3265 static STRING: LazyLock<Row> = LazyLock::new(|| {
3266 Row::pack_slice(&[
3267 Datum::String(""),
3268 Datum::String(" "),
3269 Datum::String("'"),
3270 Datum::String("\""),
3271 Datum::String("."),
3272 Datum::String("2015-09-18T23:56:04.123Z"),
3273 Datum::String(&"x".repeat(100)),
3274 Datum::String("JAPAN"),
3276 Datum::String("1,2,3"),
3277 Datum::String("\r\n"),
3278 Datum::String("\"\""),
3279 ])
3280 });
3281 static CHAR: LazyLock<Row> = LazyLock::new(|| {
3282 Row::pack_slice(&[
3283 Datum::String(" "),
3284 Datum::String("'"),
3285 Datum::String("\""),
3286 Datum::String("."),
3287 Datum::String(","),
3288 Datum::String("\t"),
3289 Datum::String("\n"),
3290 Datum::String("\r"),
3291 Datum::String("\\"),
3292 Datum::String(std::str::from_utf8(b"\x00").unwrap()),
3294 Datum::String(std::str::from_utf8(b"\x02").unwrap()),
3296 Datum::String(std::str::from_utf8(b"\x03").unwrap()),
3298 Datum::String(std::str::from_utf8(b"\x08").unwrap()),
3300 Datum::String(std::str::from_utf8(b"\x1B").unwrap()),
3302 Datum::String(std::str::from_utf8(b"\x7F").unwrap()),
3304 ])
3305 });
3306 static JSONB: LazyLock<Row> = LazyLock::new(|| {
3307 let mut datums = vec![Datum::True, Datum::False, Datum::JsonNull];
3308 datums.extend(STRING.iter());
3309 datums.extend(NUMERIC.iter().filter(|n| {
3310 let Datum::Numeric(n) = n else {
3311 panic!("expected Numeric, found {n:?}");
3312 };
3313 !(n.0.is_nan() || n.0.is_infinite())
3315 }));
3316 Row::pack_slice(&datums)
3318 });
3319 static UUID: LazyLock<Row> = LazyLock::new(|| {
3320 Row::pack_slice(&[
3321 Datum::Uuid(Uuid::from_u128(u128::MIN)),
3322 Datum::Uuid(Uuid::from_u128(u128::MAX)),
3323 ])
3324 });
3325 static ARRAY: LazyLock<BTreeMap<&'static ScalarType, Row>> = LazyLock::new(|| {
3326 let generate_row = |inner_type: &ScalarType| {
3327 let datums: Vec<_> = inner_type.interesting_datums().collect();
3328
3329 let mut row = Row::default();
3330 row.packer()
3331 .try_push_array::<_, Datum<'static>>(
3332 &[ArrayDimension {
3333 lower_bound: 1,
3334 length: 0,
3335 }],
3336 [],
3337 )
3338 .expect("failed to push empty array");
3339 row.packer()
3340 .try_push_array(
3341 &[ArrayDimension {
3342 lower_bound: 1,
3343 length: datums.len(),
3344 }],
3345 datums,
3346 )
3347 .expect("failed to push array");
3348
3349 row
3350 };
3351
3352 ScalarType::enumerate()
3353 .into_iter()
3354 .filter(|ty| !matches!(ty, ScalarType::Array(_)))
3355 .map(|ty| (ty, generate_row(ty)))
3356 .collect()
3357 });
3358 static EMPTY_ARRAY: LazyLock<Row> = LazyLock::new(|| {
3359 let mut row = Row::default();
3360 row.packer()
3361 .try_push_array::<_, Datum<'static>>(
3362 &[ArrayDimension {
3363 lower_bound: 1,
3364 length: 0,
3365 }],
3366 [],
3367 )
3368 .expect("failed to push empty array");
3369 row
3370 });
3371 static LIST: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3372 static RECORD: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3373 static OID: LazyLock<Row> =
3374 LazyLock::new(|| Row::pack_slice(&[Datum::UInt32(u32::MIN), Datum::UInt32(u32::MAX)]));
3375 static MAP: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3376 static INT2VECTOR: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3377 static MZTIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3378 Row::pack_slice(&[
3379 Datum::MzTimestamp(crate::Timestamp::MIN),
3380 Datum::MzTimestamp(crate::Timestamp::MAX),
3381 ])
3382 });
3383 static RANGE: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3384 static MZACLITEM: LazyLock<Row> = LazyLock::new(|| {
3385 Row::pack_slice(&[
3386 Datum::MzAclItem(MzAclItem {
3387 grantee: RoleId::Public,
3388 grantor: RoleId::Public,
3389 acl_mode: AclMode::empty(),
3390 }),
3391 Datum::MzAclItem(MzAclItem {
3392 grantee: RoleId::Public,
3393 grantor: RoleId::Public,
3394 acl_mode: AclMode::all(),
3395 }),
3396 Datum::MzAclItem(MzAclItem {
3397 grantee: RoleId::User(42),
3398 grantor: RoleId::Public,
3399 acl_mode: AclMode::empty(),
3400 }),
3401 Datum::MzAclItem(MzAclItem {
3402 grantee: RoleId::User(42),
3403 grantor: RoleId::Public,
3404 acl_mode: AclMode::all(),
3405 }),
3406 Datum::MzAclItem(MzAclItem {
3407 grantee: RoleId::Public,
3408 grantor: RoleId::User(42),
3409 acl_mode: AclMode::empty(),
3410 }),
3411 Datum::MzAclItem(MzAclItem {
3412 grantee: RoleId::Public,
3413 grantor: RoleId::User(42),
3414 acl_mode: AclMode::all(),
3415 }),
3416 ])
3417 });
3418 static ACLITEM: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3420
3421 let iter: Box<dyn Iterator<Item = Datum<'static>>> = match self {
3422 ScalarType::Bool => Box::new((*BOOL).iter()),
3423 ScalarType::Int16 => Box::new((*INT16).iter()),
3424 ScalarType::Int32 => Box::new((*INT32).iter()),
3425 ScalarType::Int64 => Box::new((*INT64).iter()),
3426 ScalarType::UInt16 => Box::new((*UINT16).iter()),
3427 ScalarType::UInt32 => Box::new((*UINT32).iter()),
3428 ScalarType::UInt64 => Box::new((*UINT64).iter()),
3429 ScalarType::Float32 => Box::new((*FLOAT32).iter()),
3430 ScalarType::Float64 => Box::new((*FLOAT64).iter()),
3431 ScalarType::Numeric { .. } => Box::new((*NUMERIC).iter()),
3432 ScalarType::Date => Box::new((*DATE).iter()),
3433 ScalarType::Time => Box::new((*TIME).iter()),
3434 ScalarType::Timestamp { .. } => Box::new((*TIMESTAMP).iter()),
3435 ScalarType::TimestampTz { .. } => Box::new((*TIMESTAMPTZ).iter()),
3436 ScalarType::Interval => Box::new((*INTERVAL).iter()),
3437 ScalarType::PgLegacyChar => Box::new((*PGLEGACYCHAR).iter()),
3438 ScalarType::PgLegacyName => Box::new((*PGLEGACYNAME).iter()),
3439 ScalarType::Bytes => Box::new((*BYTES).iter()),
3440 ScalarType::String => Box::new((*STRING).iter().chain((*CHAR).iter())),
3441 ScalarType::Char { .. } => Box::new((*CHAR).iter()),
3442 ScalarType::VarChar { .. } => Box::new((*STRING).iter().chain((*CHAR).iter())),
3443 ScalarType::Jsonb => Box::new((*JSONB).iter()),
3444 ScalarType::Uuid => Box::new((*UUID).iter()),
3445 ScalarType::Array(inner_type) => {
3446 if matches!(inner_type.as_ref(), ScalarType::Array(_)) {
3447 panic!("ScalarType::Array cannot have a nested Array");
3448 }
3449
3450 Box::new(
3451 (*ARRAY)
3452 .get(inner_type.as_ref())
3453 .unwrap_or(&*EMPTY_ARRAY)
3454 .iter(),
3455 )
3456 }
3457 ScalarType::List { .. } => Box::new((*LIST).iter()),
3458 ScalarType::Record { .. } => Box::new((*RECORD).iter()),
3459 ScalarType::Oid => Box::new((*OID).iter()),
3460 ScalarType::Map { .. } => Box::new((*MAP).iter()),
3461 ScalarType::RegProc => Box::new((*OID).iter()),
3462 ScalarType::RegType => Box::new((*OID).iter()),
3463 ScalarType::RegClass => Box::new((*OID).iter()),
3464 ScalarType::Int2Vector => Box::new((*INT2VECTOR).iter()),
3465 ScalarType::MzTimestamp => Box::new((*MZTIMESTAMP).iter()),
3466 ScalarType::Range { .. } => Box::new((*RANGE).iter()),
3467 ScalarType::MzAclItem { .. } => Box::new((*MZACLITEM).iter()),
3468 ScalarType::AclItem { .. } => Box::new((*ACLITEM).iter()),
3469 };
3470
3471 iter
3472 }
3473
3474 pub fn enumerate() -> &'static [Self] {
3477 &[
3480 ScalarType::Bool,
3481 ScalarType::Int16,
3482 ScalarType::Int32,
3483 ScalarType::Int64,
3484 ScalarType::UInt16,
3485 ScalarType::UInt32,
3486 ScalarType::UInt64,
3487 ScalarType::Float32,
3488 ScalarType::Float64,
3489 ScalarType::Numeric {
3490 max_scale: Some(NumericMaxScale(
3491 crate::adt::numeric::NUMERIC_DATUM_MAX_PRECISION,
3492 )),
3493 },
3494 ScalarType::Date,
3495 ScalarType::Time,
3496 ScalarType::Timestamp {
3497 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3498 },
3499 ScalarType::Timestamp {
3500 precision: Some(TimestampPrecision(0)),
3501 },
3502 ScalarType::Timestamp { precision: None },
3503 ScalarType::TimestampTz {
3504 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3505 },
3506 ScalarType::TimestampTz {
3507 precision: Some(TimestampPrecision(0)),
3508 },
3509 ScalarType::TimestampTz { precision: None },
3510 ScalarType::Interval,
3511 ScalarType::PgLegacyChar,
3512 ScalarType::Bytes,
3513 ScalarType::String,
3514 ScalarType::Char {
3515 length: Some(CharLength(1)),
3516 },
3517 ScalarType::VarChar { max_length: None },
3518 ScalarType::Jsonb,
3519 ScalarType::Uuid,
3520 ScalarType::Oid,
3521 ScalarType::RegProc,
3522 ScalarType::RegType,
3523 ScalarType::RegClass,
3524 ScalarType::Int2Vector,
3525 ScalarType::MzTimestamp,
3526 ScalarType::MzAclItem,
3527 ]
3548 }
3549
3550 pub fn array_of_self_elem_type(self) -> Result<ScalarType, ScalarType> {
3555 match self {
3556 t @ (ScalarType::AclItem
3557 | ScalarType::Bool
3558 | ScalarType::Int16
3559 | ScalarType::Int32
3560 | ScalarType::Int64
3561 | ScalarType::UInt16
3562 | ScalarType::UInt32
3563 | ScalarType::UInt64
3564 | ScalarType::Float32
3565 | ScalarType::Float64
3566 | ScalarType::Numeric { .. }
3567 | ScalarType::Date
3568 | ScalarType::Time
3569 | ScalarType::Timestamp { .. }
3570 | ScalarType::TimestampTz { .. }
3571 | ScalarType::Interval
3572 | ScalarType::PgLegacyChar
3573 | ScalarType::PgLegacyName
3574 | ScalarType::Bytes
3575 | ScalarType::String
3576 | ScalarType::VarChar { .. }
3577 | ScalarType::Jsonb
3578 | ScalarType::Uuid
3579 | ScalarType::Record { .. }
3580 | ScalarType::Oid
3581 | ScalarType::RegProc
3582 | ScalarType::RegType
3583 | ScalarType::RegClass
3584 | ScalarType::Int2Vector
3585 | ScalarType::MzTimestamp
3586 | ScalarType::Range { .. }
3587 | ScalarType::MzAclItem { .. }) => Ok(t),
3588
3589 ScalarType::Array(elem) => Ok(elem.array_of_self_elem_type()?),
3590
3591 t @ (ScalarType::Char { .. }
3593 | ScalarType::Map { .. }
3595 | ScalarType::List { .. }) => Err(t),
3596 }
3597 }
3598}
3599
3600impl Arbitrary for ScalarType {
3603 type Parameters = ();
3604 type Strategy = BoxedStrategy<ScalarType>;
3605
3606 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
3607 let leaf = Union::new(vec![
3609 Just(ScalarType::Bool).boxed(),
3610 Just(ScalarType::UInt16).boxed(),
3611 Just(ScalarType::UInt32).boxed(),
3612 Just(ScalarType::UInt64).boxed(),
3613 Just(ScalarType::Int16).boxed(),
3614 Just(ScalarType::Int32).boxed(),
3615 Just(ScalarType::Int64).boxed(),
3616 Just(ScalarType::Float32).boxed(),
3617 Just(ScalarType::Float64).boxed(),
3618 any::<Option<NumericMaxScale>>()
3619 .prop_map(|max_scale| ScalarType::Numeric { max_scale })
3620 .boxed(),
3621 Just(ScalarType::Date).boxed(),
3622 Just(ScalarType::Time).boxed(),
3623 any::<Option<TimestampPrecision>>()
3624 .prop_map(|precision| ScalarType::Timestamp { precision })
3625 .boxed(),
3626 any::<Option<TimestampPrecision>>()
3627 .prop_map(|precision| ScalarType::TimestampTz { precision })
3628 .boxed(),
3629 Just(ScalarType::MzTimestamp).boxed(),
3630 Just(ScalarType::Interval).boxed(),
3631 Just(ScalarType::PgLegacyChar).boxed(),
3632 Just(ScalarType::Bytes).boxed(),
3633 Just(ScalarType::String).boxed(),
3634 any::<Option<CharLength>>()
3635 .prop_map(|length| ScalarType::Char { length })
3636 .boxed(),
3637 any::<Option<VarCharMaxLength>>()
3638 .prop_map(|max_length| ScalarType::VarChar { max_length })
3639 .boxed(),
3640 Just(ScalarType::PgLegacyName).boxed(),
3641 Just(ScalarType::Jsonb).boxed(),
3642 Just(ScalarType::Uuid).boxed(),
3643 Just(ScalarType::AclItem).boxed(),
3644 Just(ScalarType::MzAclItem).boxed(),
3645 Just(ScalarType::Oid).boxed(),
3646 Just(ScalarType::RegProc).boxed(),
3647 Just(ScalarType::RegType).boxed(),
3648 Just(ScalarType::RegClass).boxed(),
3649 Just(ScalarType::Int2Vector).boxed(),
3650 ])
3651 .no_shrink()
3654 .boxed();
3655
3656 let range_leaf = Union::new(vec![
3658 Just(ScalarType::Int32).boxed(),
3659 Just(ScalarType::Int64).boxed(),
3660 Just(ScalarType::Date).boxed(),
3661 any::<Option<NumericMaxScale>>()
3662 .prop_map(|max_scale| ScalarType::Numeric { max_scale })
3663 .boxed(),
3664 any::<Option<TimestampPrecision>>()
3665 .prop_map(|precision| ScalarType::Timestamp { precision })
3666 .boxed(),
3667 any::<Option<TimestampPrecision>>()
3668 .prop_map(|precision| ScalarType::TimestampTz { precision })
3669 .boxed(),
3670 ]);
3671 let range = range_leaf
3672 .prop_map(|inner_type| ScalarType::Range {
3673 element_type: Box::new(inner_type),
3674 })
3675 .boxed();
3676
3677 let array = leaf
3679 .clone()
3680 .prop_map(|inner_type| ScalarType::Array(Box::new(inner_type)))
3681 .boxed();
3682
3683 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
3684
3685 leaf.prop_recursive(2, 3, 5, |inner| {
3686 Union::new(vec![
3687 (inner.clone(), any::<Option<CatalogItemId>>())
3689 .prop_map(|(x, id)| ScalarType::List {
3690 element_type: Box::new(x),
3691 custom_id: id,
3692 })
3693 .boxed(),
3694 (inner.clone(), any::<Option<CatalogItemId>>())
3696 .prop_map(|(x, id)| ScalarType::Map {
3697 value_type: Box::new(x),
3698 custom_id: id,
3699 })
3700 .boxed(),
3701 {
3703 let column_type_strat =
3706 (inner, any::<bool>()).prop_map(|(scalar_type, nullable)| ColumnType {
3707 scalar_type,
3708 nullable,
3709 });
3710
3711 let fields_strat =
3714 prop::collection::vec((any::<ColumnName>(), column_type_strat), 0..10);
3715
3716 (fields_strat, any::<Option<CatalogItemId>>())
3718 .prop_map(|(fields, custom_id)| ScalarType::Record {
3719 fields: fields.into(),
3720 custom_id,
3721 })
3722 .boxed()
3723 },
3724 ])
3725 })
3726 .boxed()
3727 }
3728}
3729
3730static EMPTY_ARRAY_ROW: LazyLock<Row> = LazyLock::new(|| {
3731 let mut row = Row::default();
3732 row.packer()
3733 .try_push_array(&[], iter::empty::<Datum>())
3734 .expect("array known to be valid");
3735 row
3736});
3737
3738static EMPTY_LIST_ROW: LazyLock<Row> = LazyLock::new(|| {
3739 let mut row = Row::default();
3740 row.packer().push_list(iter::empty::<Datum>());
3741 row
3742});
3743
3744static EMPTY_MAP_ROW: LazyLock<Row> = LazyLock::new(|| {
3745 let mut row = Row::default();
3746 row.packer().push_dict(iter::empty::<(_, Datum)>());
3747 row
3748});
3749
3750impl Datum<'_> {
3751 pub fn empty_array() -> Datum<'static> {
3752 EMPTY_ARRAY_ROW.unpack_first()
3753 }
3754
3755 pub fn empty_list() -> Datum<'static> {
3756 EMPTY_LIST_ROW.unpack_first()
3757 }
3758
3759 pub fn empty_map() -> Datum<'static> {
3760 EMPTY_MAP_ROW.unpack_first()
3761 }
3762}
3763
3764#[derive(Debug, PartialEq, Clone)]
3766pub enum PropDatum {
3767 Null,
3768 Bool(bool),
3769 Int16(i16),
3770 Int32(i32),
3771 Int64(i64),
3772 UInt8(u8),
3773 UInt16(u16),
3774 UInt32(u32),
3775 UInt64(u64),
3776 Float32(f32),
3777 Float64(f64),
3778
3779 Date(Date),
3780 Time(chrono::NaiveTime),
3781 Timestamp(CheckedTimestamp<chrono::NaiveDateTime>),
3782 TimestampTz(CheckedTimestamp<chrono::DateTime<chrono::Utc>>),
3783 MzTimestamp(u64),
3784
3785 Interval(Interval),
3786 Numeric(Numeric),
3787
3788 Bytes(Vec<u8>),
3789 String(String),
3790
3791 Array(PropArray),
3792 List(PropList),
3793 Map(PropDict),
3794 Record(PropDict),
3795 Range(PropRange),
3796
3797 AclItem(AclItem),
3798 MzAclItem(MzAclItem),
3799
3800 JsonNull,
3801 Uuid(Uuid),
3802 Dummy,
3803}
3804
3805impl std::cmp::Eq for PropDatum {}
3806
3807impl PartialOrd for PropDatum {
3808 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
3809 Some(self.cmp(other))
3810 }
3811}
3812
3813impl Ord for PropDatum {
3814 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
3815 Datum::from(self).cmp(&Datum::from(other))
3816 }
3817}
3818
3819pub fn arb_datum() -> BoxedStrategy<PropDatum> {
3821 let leaf = Union::new(vec![
3822 Just(PropDatum::Null).boxed(),
3823 any::<bool>().prop_map(PropDatum::Bool).boxed(),
3824 any::<i16>().prop_map(PropDatum::Int16).boxed(),
3825 any::<i32>().prop_map(PropDatum::Int32).boxed(),
3826 any::<i64>().prop_map(PropDatum::Int64).boxed(),
3827 any::<u16>().prop_map(PropDatum::UInt16).boxed(),
3828 any::<u32>().prop_map(PropDatum::UInt32).boxed(),
3829 any::<u64>().prop_map(PropDatum::UInt64).boxed(),
3830 any::<f32>().prop_map(PropDatum::Float32).boxed(),
3831 any::<f64>().prop_map(PropDatum::Float64).boxed(),
3832 arb_date().prop_map(PropDatum::Date).boxed(),
3833 add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
3834 .prop_map(PropDatum::Time)
3835 .boxed(),
3836 arb_naive_date_time()
3837 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
3838 .boxed(),
3839 arb_utc_date_time()
3840 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
3841 .boxed(),
3842 any::<Interval>().prop_map(PropDatum::Interval).boxed(),
3843 arb_numeric().prop_map(PropDatum::Numeric).boxed(),
3844 prop::collection::vec(any::<u8>(), 1024)
3845 .prop_map(PropDatum::Bytes)
3846 .boxed(),
3847 ".*".prop_map(PropDatum::String).boxed(),
3848 Just(PropDatum::JsonNull).boxed(),
3849 any::<[u8; 16]>()
3850 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
3851 .boxed(),
3852 arb_range(arb_range_data())
3853 .prop_map(PropDatum::Range)
3854 .boxed(),
3855 Just(PropDatum::Dummy).boxed(),
3856 ]);
3857 leaf.prop_recursive(3, 8, 16, |inner| {
3858 Union::new(vec![
3859 arb_array(inner.clone()).prop_map(PropDatum::Array).boxed(),
3860 arb_list(inner.clone()).prop_map(PropDatum::List).boxed(),
3861 arb_dict(inner).prop_map(PropDatum::Map).boxed(),
3862 ])
3863 })
3864 .boxed()
3865}
3866
3867pub fn arb_datum_for_column(column_type: ColumnType) -> impl Strategy<Value = PropDatum> {
3869 let strat = arb_datum_for_scalar(column_type.scalar_type);
3870
3871 if column_type.nullable {
3872 Union::new_weighted(vec![(1, Just(PropDatum::Null).boxed()), (5, strat.boxed())]).boxed()
3873 } else {
3874 strat.boxed()
3875 }
3876}
3877
3878pub fn arb_datum_for_scalar(scalar_type: ScalarType) -> impl Strategy<Value = PropDatum> {
3880 match scalar_type {
3881 ScalarType::Bool => any::<bool>().prop_map(PropDatum::Bool).boxed(),
3882 ScalarType::Int16 => any::<i16>().prop_map(PropDatum::Int16).boxed(),
3883 ScalarType::Int32 => any::<i32>().prop_map(PropDatum::Int32).boxed(),
3884 ScalarType::Int64 => any::<i64>().prop_map(PropDatum::Int64).boxed(),
3885 ScalarType::PgLegacyChar => any::<u8>().prop_map(PropDatum::UInt8).boxed(),
3886 ScalarType::UInt16 => any::<u16>().prop_map(PropDatum::UInt16).boxed(),
3887 ScalarType::UInt32
3888 | ScalarType::Oid
3889 | ScalarType::RegClass
3890 | ScalarType::RegProc
3891 | ScalarType::RegType => any::<u32>().prop_map(PropDatum::UInt32).boxed(),
3892 ScalarType::UInt64 => any::<u64>().prop_map(PropDatum::UInt64).boxed(),
3893 ScalarType::Float32 => any::<f32>().prop_map(PropDatum::Float32).boxed(),
3894 ScalarType::Float64 => any::<f64>().prop_map(PropDatum::Float64).boxed(),
3895 ScalarType::Numeric { .. } => arb_numeric().prop_map(PropDatum::Numeric).boxed(),
3896 ScalarType::String
3897 | ScalarType::PgLegacyName
3898 | ScalarType::Char { length: None }
3899 | ScalarType::VarChar { max_length: None } => ".*".prop_map(PropDatum::String).boxed(),
3900 ScalarType::Char {
3901 length: Some(length),
3902 } => {
3903 let max_len = usize::cast_from(length.into_u32()).max(1);
3904 prop::collection::vec(any::<char>(), 0..max_len)
3905 .prop_map(move |chars| {
3906 let num_blanks = max_len - chars.len();
3908 let s = chars
3909 .into_iter()
3910 .chain(std::iter::repeat(' ').take(num_blanks))
3911 .collect();
3912 PropDatum::String(s)
3913 })
3914 .boxed()
3915 }
3916 ScalarType::VarChar {
3917 max_length: Some(length),
3918 } => {
3919 let max_len = usize::cast_from(length.into_u32()).max(1);
3920 prop::collection::vec(any::<char>(), 0..max_len)
3921 .prop_map(|chars| PropDatum::String(chars.into_iter().collect()))
3922 .boxed()
3923 }
3924 ScalarType::Bytes => prop::collection::vec(any::<u8>(), 300)
3925 .prop_map(PropDatum::Bytes)
3926 .boxed(),
3927 ScalarType::Date => arb_date().prop_map(PropDatum::Date).boxed(),
3928 ScalarType::Time => add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
3929 .prop_map(PropDatum::Time)
3930 .boxed(),
3931 ScalarType::Timestamp { .. } => arb_naive_date_time()
3932 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
3933 .boxed(),
3934 ScalarType::TimestampTz { .. } => arb_utc_date_time()
3935 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
3936 .boxed(),
3937 ScalarType::MzTimestamp => any::<u64>().prop_map(PropDatum::MzTimestamp).boxed(),
3938 ScalarType::Interval => any::<Interval>().prop_map(PropDatum::Interval).boxed(),
3939 ScalarType::Uuid => any::<[u8; 16]>()
3940 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
3941 .boxed(),
3942 ScalarType::AclItem => any::<AclItem>().prop_map(PropDatum::AclItem).boxed(),
3943 ScalarType::MzAclItem => any::<MzAclItem>().prop_map(PropDatum::MzAclItem).boxed(),
3944 ScalarType::Range { element_type } => {
3945 let data_strat = (
3946 arb_datum_for_scalar(*element_type.clone()),
3947 arb_datum_for_scalar(*element_type),
3948 );
3949 arb_range(data_strat).prop_map(PropDatum::Range).boxed()
3950 }
3951 ScalarType::List { element_type, .. } => arb_list(arb_datum_for_scalar(*element_type))
3952 .prop_map(PropDatum::List)
3953 .boxed(),
3954 ScalarType::Array(element_type) => arb_array(arb_datum_for_scalar(*element_type))
3955 .prop_map(PropDatum::Array)
3956 .boxed(),
3957 ScalarType::Int2Vector => arb_array(any::<i16>().prop_map(PropDatum::Int16).boxed())
3958 .prop_map(PropDatum::Array)
3959 .boxed(),
3960 ScalarType::Map { value_type, .. } => arb_dict(arb_datum_for_scalar(*value_type))
3961 .prop_map(PropDatum::Map)
3962 .boxed(),
3963 ScalarType::Record { fields, .. } => {
3964 let field_strats = fields.iter().map(|(name, ty)| {
3965 (
3966 name.to_string(),
3967 arb_datum_for_scalar(ty.scalar_type.clone()),
3968 )
3969 });
3970 arb_record(field_strats).prop_map(PropDatum::Record).boxed()
3971 }
3972 ScalarType::Jsonb => {
3973 let int_value = any::<i128>()
3974 .prop_map(|v| Numeric::try_from(v).unwrap())
3975 .boxed();
3976 let float_value = (1e-39f64..1e39)
3978 .prop_map(|v| Numeric::try_from(v).unwrap())
3979 .boxed();
3980 let json_number = Union::new(vec![int_value, float_value]);
3983
3984 let json_leaf = Union::new(vec![
3985 any::<()>().prop_map(|_| PropDatum::JsonNull).boxed(),
3986 any::<bool>().prop_map(PropDatum::Bool).boxed(),
3987 json_number.prop_map(PropDatum::Numeric).boxed(),
3988 ".*".prop_map(PropDatum::String).boxed(),
3989 ]);
3990 json_leaf
3991 .prop_recursive(4, 32, 8, |element| {
3992 Union::new(vec![
3993 prop::collection::vec(element.clone(), 0..16)
3994 .prop_map(|elements| {
3995 let datums: Vec<_> = elements.iter().map(|pd| pd.into()).collect();
3996 let mut row = Row::default();
3997 row.packer().push_list(datums.iter());
3998 PropDatum::List(PropList(row, elements))
3999 })
4000 .boxed(),
4001 prop::collection::hash_map(".*", element, 0..16)
4002 .prop_map(|elements| {
4003 let mut elements: Vec<_> = elements.into_iter().collect();
4004 elements.sort_by_key(|(k, _)| k.clone());
4005 elements.dedup_by_key(|(k, _)| k.clone());
4006 let mut row = Row::default();
4007 let entry_iter =
4008 elements.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4009 row.packer().push_dict(entry_iter);
4010 PropDatum::Map(PropDict(row, elements))
4011 })
4012 .boxed(),
4013 ])
4014 })
4015 .boxed()
4016 }
4017 }
4018}
4019
4020pub fn arb_naive_date_time() -> impl Strategy<Value = NaiveDateTime> {
4022 add_arb_duration(chrono::DateTime::from_timestamp(0, 0).unwrap().naive_utc())
4023}
4024
4025pub fn arb_utc_date_time() -> impl Strategy<Value = DateTime<Utc>> {
4027 add_arb_duration(chrono::Utc.timestamp_opt(0, 0).unwrap())
4028}
4029
4030fn arb_array_dimension() -> BoxedStrategy<ArrayDimension> {
4031 (1..4_usize)
4032 .prop_map(|length| ArrayDimension {
4033 lower_bound: 1,
4034 length,
4035 })
4036 .boxed()
4037}
4038
4039#[derive(Debug, PartialEq, Clone)]
4040pub struct PropArray(Row, Vec<PropDatum>);
4041
4042fn arb_array(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropArray> {
4043 let element_strategy = Union::new_weighted(vec![
4045 (20, element_strategy),
4046 (1, Just(PropDatum::Null).boxed()),
4047 ]);
4048
4049 prop::collection::vec(
4050 arb_array_dimension(),
4051 1..usize::from(crate::adt::array::MAX_ARRAY_DIMENSIONS),
4052 )
4053 .prop_flat_map(move |dimensions| {
4054 let n_elts: usize = dimensions.iter().map(|d| d.length).product();
4055 (
4056 Just(dimensions),
4057 prop::collection::vec(element_strategy.clone(), n_elts),
4058 )
4059 })
4060 .prop_map(|(dimensions, elements)| {
4061 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4062 let mut row = Row::default();
4063 row.packer()
4064 .try_push_array(&dimensions, element_datums)
4065 .unwrap();
4066 PropArray(row, elements)
4067 })
4068 .boxed()
4069}
4070
4071#[derive(Debug, PartialEq, Clone)]
4072pub struct PropList(Row, Vec<PropDatum>);
4073
4074fn arb_list(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropList> {
4075 let element_strategy = Union::new_weighted(vec![
4077 (20, element_strategy),
4078 (1, Just(PropDatum::Null).boxed()),
4079 ]);
4080
4081 prop::collection::vec(element_strategy, 1..50)
4082 .prop_map(|elements| {
4083 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4084 let mut row = Row::default();
4085 row.packer().push_list(element_datums.iter());
4086 PropList(row, elements)
4087 })
4088 .boxed()
4089}
4090
4091#[derive(Debug, PartialEq, Clone)]
4092pub struct PropRange(
4093 Row,
4094 Option<(
4095 (Option<Box<PropDatum>>, bool),
4096 (Option<Box<PropDatum>>, bool),
4097 )>,
4098);
4099
4100pub fn arb_range_type() -> Union<BoxedStrategy<ScalarType>> {
4101 Union::new(vec![
4102 Just(ScalarType::Int32).boxed(),
4103 Just(ScalarType::Int64).boxed(),
4104 Just(ScalarType::Date).boxed(),
4105 ])
4106}
4107
4108fn arb_range_data() -> Union<BoxedStrategy<(PropDatum, PropDatum)>> {
4109 Union::new(vec![
4110 (
4111 any::<i32>().prop_map(PropDatum::Int32),
4112 any::<i32>().prop_map(PropDatum::Int32),
4113 )
4114 .boxed(),
4115 (
4116 any::<i64>().prop_map(PropDatum::Int64),
4117 any::<i64>().prop_map(PropDatum::Int64),
4118 )
4119 .boxed(),
4120 (
4121 arb_date().prop_map(PropDatum::Date),
4122 arb_date().prop_map(PropDatum::Date),
4123 )
4124 .boxed(),
4125 ])
4126}
4127
4128fn arb_range(
4129 data: impl Strategy<Value = (PropDatum, PropDatum)> + 'static,
4130) -> BoxedStrategy<PropRange> {
4131 (
4132 any::<u16>(),
4133 any::<bool>(),
4134 any::<bool>(),
4135 any::<bool>(),
4136 any::<bool>(),
4137 data,
4138 )
4139 .prop_map(
4140 |(split, lower_inf, lower_inc, upper_inf, upper_inc, (a, b))| {
4141 let mut row = Row::default();
4142 let mut packer = row.packer();
4143 let r = if split % 32 == 0 {
4144 packer
4145 .push_range(Range::new(None))
4146 .expect("pushing empty ranges never fails");
4147 None
4148 } else {
4149 let b_is_lower = Datum::from(&b) < Datum::from(&a);
4150
4151 let (lower, upper) = if b_is_lower { (b, a) } else { (a, b) };
4152 let mut range = Range::new(Some((
4153 RangeLowerBound {
4154 inclusive: lower_inc,
4155 bound: if lower_inf {
4156 None
4157 } else {
4158 Some(Datum::from(&lower))
4159 },
4160 },
4161 RangeUpperBound {
4162 inclusive: upper_inc,
4163 bound: if upper_inf {
4164 None
4165 } else {
4166 Some(Datum::from(&upper))
4167 },
4168 },
4169 )));
4170
4171 range.canonicalize().unwrap();
4172
4173 let (empty, lower_inf, lower_inc, upper_inf, upper_inc) = match range.inner {
4176 None => (true, false, false, false, false),
4177 Some(inner) => (
4178 false
4179 || match inner.lower.bound {
4180 Some(b) => b != Datum::from(&lower),
4181 None => !lower_inf,
4182 }
4183 || match inner.upper.bound {
4184 Some(b) => b != Datum::from(&upper),
4185 None => !upper_inf,
4186 },
4187 inner.lower.bound.is_none(),
4188 inner.lower.inclusive,
4189 inner.upper.bound.is_none(),
4190 inner.upper.inclusive,
4191 ),
4192 };
4193
4194 if empty {
4195 packer.push_range(Range { inner: None }).unwrap();
4196 None
4197 } else {
4198 packer.push_range(range).unwrap();
4199 Some((
4200 (
4201 if lower_inf {
4202 None
4203 } else {
4204 Some(Box::new(lower))
4205 },
4206 lower_inc,
4207 ),
4208 (
4209 if upper_inf {
4210 None
4211 } else {
4212 Some(Box::new(upper))
4213 },
4214 upper_inc,
4215 ),
4216 ))
4217 }
4218 };
4219
4220 PropRange(row, r)
4221 },
4222 )
4223 .boxed()
4224}
4225
4226#[derive(Debug, PartialEq, Clone)]
4227pub struct PropDict(Row, Vec<(String, PropDatum)>);
4228
4229fn arb_dict(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropDict> {
4230 let element_strategy = Union::new_weighted(vec![
4232 (20, element_strategy),
4233 (1, Just(PropDatum::Null).boxed()),
4234 ]);
4235
4236 prop::collection::vec((".*", element_strategy), 1..50)
4237 .prop_map(|mut entries| {
4238 entries.sort_by_key(|(k, _)| k.clone());
4239 entries.dedup_by_key(|(k, _)| k.clone());
4240 let mut row = Row::default();
4241 let entry_iter = entries.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4242 row.packer().push_dict(entry_iter);
4243 PropDict(row, entries)
4244 })
4245 .boxed()
4246}
4247
4248fn arb_record(
4249 fields: impl Iterator<Item = (String, BoxedStrategy<PropDatum>)>,
4250) -> BoxedStrategy<PropDict> {
4251 let (names, strategies): (Vec<_>, Vec<_>) = fields.unzip();
4252
4253 strategies
4254 .prop_map(move |x| {
4255 let mut row = Row::default();
4256 row.packer().push_list(x.iter().map(Datum::from));
4257 let entries: Vec<_> = names.clone().into_iter().zip(x).collect();
4258 PropDict(row, entries)
4259 })
4260 .boxed()
4261}
4262
4263fn arb_date() -> BoxedStrategy<Date> {
4264 (Date::LOW_DAYS..Date::HIGH_DAYS)
4265 .prop_map(move |days| Date::from_pg_epoch(days).unwrap())
4266 .boxed()
4267}
4268
4269pub fn add_arb_duration<T: 'static + Copy + Add<chrono::Duration> + std::fmt::Debug>(
4270 to: T,
4271) -> BoxedStrategy<T::Output>
4272where
4273 T::Output: std::fmt::Debug,
4274{
4275 let lower = LOW_DATE
4276 .and_hms_opt(0, 0, 0)
4277 .unwrap()
4278 .and_utc()
4279 .timestamp_micros();
4280 let upper = HIGH_DATE
4281 .and_hms_opt(0, 0, 0)
4282 .unwrap()
4283 .and_utc()
4284 .timestamp_micros();
4285 (lower..upper)
4286 .prop_map(move |v| to + chrono::Duration::microseconds(v))
4287 .boxed()
4288}
4289
4290pub(crate) fn arb_numeric() -> BoxedStrategy<Numeric> {
4291 let int_value = any::<i128>()
4292 .prop_map(|v| Numeric::try_from(v).unwrap())
4293 .boxed();
4294 let float_value = (-1e39f64..1e39)
4295 .prop_map(|v| Numeric::try_from(v).unwrap())
4296 .boxed();
4297
4298 let tiny_floats = ((-10.0..10.0), (1u32..10))
4301 .prop_map(|(v, num_digits)| {
4302 let num_digits: f64 = 10u32.pow(num_digits).try_into().unwrap();
4304 let trunc = f64::trunc(v * num_digits) / num_digits;
4305 Numeric::try_from(trunc).unwrap()
4306 })
4307 .boxed();
4308 let small_ints = (-1_000_000..1_000_000)
4309 .prop_map(|v| Numeric::try_from(v).unwrap())
4310 .boxed();
4311 let small_floats = (-1_000_000.0..1_000_000.0)
4312 .prop_map(|v| Numeric::try_from(v).unwrap())
4313 .boxed();
4314
4315 Union::new_weighted(vec![
4316 (20, tiny_floats),
4317 (20, small_ints),
4318 (20, small_floats),
4319 (10, int_value),
4320 (10, float_value),
4321 (1, Just(Numeric::infinity()).boxed()),
4322 (1, Just(-Numeric::infinity()).boxed()),
4323 (1, Just(Numeric::nan()).boxed()),
4324 (1, Just(Numeric::zero()).boxed()),
4325 ])
4326 .boxed()
4327}
4328
4329impl<'a> From<&'a PropDatum> for Datum<'a> {
4330 #[inline]
4331 fn from(pd: &'a PropDatum) -> Self {
4332 use PropDatum::*;
4333 match pd {
4334 Null => Datum::Null,
4335 Bool(b) => Datum::from(*b),
4336 Int16(i) => Datum::from(*i),
4337 Int32(i) => Datum::from(*i),
4338 Int64(i) => Datum::from(*i),
4339 UInt8(u) => Datum::from(*u),
4340 UInt16(u) => Datum::from(*u),
4341 UInt32(u) => Datum::from(*u),
4342 UInt64(u) => Datum::from(*u),
4343 Float32(f) => Datum::from(*f),
4344 Float64(f) => Datum::from(*f),
4345 Date(d) => Datum::from(*d),
4346 Time(t) => Datum::from(*t),
4347 Timestamp(t) => Datum::from(*t),
4348 TimestampTz(t) => Datum::from(*t),
4349 MzTimestamp(t) => Datum::MzTimestamp((*t).into()),
4350 Interval(i) => Datum::from(*i),
4351 Numeric(s) => Datum::from(*s),
4352 Bytes(b) => Datum::from(&b[..]),
4353 String(s) => Datum::from(s.as_str()),
4354 Array(PropArray(row, _)) => {
4355 let array = row.unpack_first().unwrap_array();
4356 Datum::Array(array)
4357 }
4358 List(PropList(row, _)) => {
4359 let list = row.unpack_first().unwrap_list();
4360 Datum::List(list)
4361 }
4362 Map(PropDict(row, _)) => {
4363 let map = row.unpack_first().unwrap_map();
4364 Datum::Map(map)
4365 }
4366 Record(PropDict(row, _)) => {
4367 let list = row.unpack_first().unwrap_list();
4368 Datum::List(list)
4369 }
4370 Range(PropRange(row, _)) => {
4371 let d = row.unpack_first();
4372 assert!(matches!(d, Datum::Range(_)));
4373 d
4374 }
4375 AclItem(i) => Datum::AclItem(*i),
4376 MzAclItem(i) => Datum::MzAclItem(*i),
4377 JsonNull => Datum::JsonNull,
4378 Uuid(u) => Datum::from(*u),
4379 Dummy => Datum::Dummy,
4380 }
4381 }
4382}
4383
4384#[mz_ore::test]
4385fn verify_base_eq_record_nullability() {
4386 let s1 = ScalarType::Record {
4387 fields: [(
4388 "c".into(),
4389 ColumnType {
4390 scalar_type: ScalarType::Bool,
4391 nullable: true,
4392 },
4393 )]
4394 .into(),
4395 custom_id: None,
4396 };
4397 let s2 = ScalarType::Record {
4398 fields: [(
4399 "c".into(),
4400 ColumnType {
4401 scalar_type: ScalarType::Bool,
4402 nullable: false,
4403 },
4404 )]
4405 .into(),
4406 custom_id: None,
4407 };
4408 let s3 = ScalarType::Record {
4409 fields: [].into(),
4410 custom_id: None,
4411 };
4412 assert!(s1.base_eq(&s2));
4413 assert!(!s1.base_eq(&s3));
4414}
4415
4416#[cfg(test)]
4417mod tests {
4418 use mz_ore::assert_ok;
4419 use mz_proto::protobuf_roundtrip;
4420
4421 use super::*;
4422
4423 proptest! {
4424 #[mz_ore::test]
4425 #[cfg_attr(miri, ignore)] fn scalar_type_protobuf_roundtrip(expect in any::<ScalarType>() ) {
4427 let actual = protobuf_roundtrip::<_, ProtoScalarType>(&expect);
4428 assert_ok!(actual);
4429 assert_eq!(actual.unwrap(), expect);
4430 }
4431 }
4432
4433 proptest! {
4434 #[mz_ore::test]
4435 #[cfg_attr(miri, ignore)] fn array_packing_unpacks_correctly(array in arb_array(arb_datum())) {
4437 let PropArray(row, elts) = array;
4438 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
4439 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_array().elements().iter().collect();
4440 assert_eq!(unpacked_datums, datums);
4441 }
4442
4443 #[mz_ore::test]
4444 #[cfg_attr(miri, ignore)] fn list_packing_unpacks_correctly(array in arb_list(arb_datum())) {
4446 let PropList(row, elts) = array;
4447 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
4448 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_list().iter().collect();
4449 assert_eq!(unpacked_datums, datums);
4450 }
4451
4452 #[mz_ore::test]
4453 #[cfg_attr(miri, ignore)] fn dict_packing_unpacks_correctly(array in arb_dict(arb_datum())) {
4455 let PropDict(row, elts) = array;
4456 let datums: Vec<(&str, Datum<'_>)> = elts.iter().map(|(k, e)| (k.as_str(), e.into())).collect();
4457 let unpacked_datums: Vec<(&str, Datum<'_>)> = row.unpack_first().unwrap_map().iter().collect();
4458 assert_eq!(unpacked_datums, datums);
4459 }
4460
4461 #[mz_ore::test]
4462 #[cfg_attr(miri, ignore)] fn row_packing_roundtrips_single_valued(prop_datums in prop::collection::vec(arb_datum(), 1..100)) {
4464 let datums: Vec<Datum<'_>> = prop_datums.iter().map(|pd| pd.into()).collect();
4465 let row = Row::pack(&datums);
4466 let unpacked = row.unpack();
4467 assert_eq!(datums, unpacked);
4468 }
4469
4470 #[mz_ore::test]
4471 #[cfg_attr(miri, ignore)] fn range_packing_unpacks_correctly(range in arb_range(arb_range_data())) {
4473 let PropRange(row, prop_range) = range;
4474 let row = row.unpack_first();
4475 let d = row.unwrap_range();
4476
4477 let (((prop_lower, prop_lower_inc), (prop_upper, prop_upper_inc)), crate::adt::range::RangeInner {lower, upper}) = match (prop_range, d.inner) {
4478 (Some(prop_values), Some(inner_range)) => (prop_values, inner_range),
4479 (None, None) => return Ok(()),
4480 _ => panic!("inequivalent row packing"),
4481 };
4482
4483 for (prop_bound, prop_bound_inc, inner_bound, inner_bound_inc) in [
4484 (prop_lower, prop_lower_inc, lower.bound, lower.inclusive),
4485 (prop_upper, prop_upper_inc, upper.bound, upper.inclusive),
4486 ] {
4487 assert_eq!(prop_bound_inc, inner_bound_inc);
4488 match (prop_bound, inner_bound) {
4489 (None, None) => continue,
4490 (Some(p), Some(b)) => {
4491 assert_eq!(Datum::from(&*p), b);
4492 }
4493 _ => panic!("inequivalent row packing"),
4494 }
4495 }
4496 }
4497 }
4498}