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::Dummy => panic!("Datum::Dummy observed"),
957 Datum::JsonNull
958 | Datum::False
959 | Datum::True
960 | Datum::Numeric(_)
961 | Datum::String(_) => true,
962 Datum::List(list) => list
963 .iter()
964 .all(|elem| is_instance_of_scalar(elem, scalar_type)),
965 Datum::Map(dict) => dict
966 .iter()
967 .all(|(_key, val)| is_instance_of_scalar(val, scalar_type)),
968 _ => false,
969 }
970 } else {
971 match (datum, scalar_type) {
973 (Datum::Dummy, _) => panic!("Datum::Dummy observed"),
974 (Datum::Null, _) => false,
975 (Datum::False, ScalarType::Bool) => true,
976 (Datum::False, _) => false,
977 (Datum::True, ScalarType::Bool) => true,
978 (Datum::True, _) => false,
979 (Datum::Int16(_), ScalarType::Int16) => true,
980 (Datum::Int16(_), _) => false,
981 (Datum::Int32(_), ScalarType::Int32) => true,
982 (Datum::Int32(_), _) => false,
983 (Datum::Int64(_), ScalarType::Int64) => true,
984 (Datum::Int64(_), _) => false,
985 (Datum::UInt8(_), ScalarType::PgLegacyChar) => true,
986 (Datum::UInt8(_), _) => false,
987 (Datum::UInt16(_), ScalarType::UInt16) => true,
988 (Datum::UInt16(_), _) => false,
989 (Datum::UInt32(_), ScalarType::Oid) => true,
990 (Datum::UInt32(_), ScalarType::RegClass) => true,
991 (Datum::UInt32(_), ScalarType::RegProc) => true,
992 (Datum::UInt32(_), ScalarType::RegType) => true,
993 (Datum::UInt32(_), ScalarType::UInt32) => true,
994 (Datum::UInt32(_), _) => false,
995 (Datum::UInt64(_), ScalarType::UInt64) => true,
996 (Datum::UInt64(_), _) => false,
997 (Datum::Float32(_), ScalarType::Float32) => true,
998 (Datum::Float32(_), _) => false,
999 (Datum::Float64(_), ScalarType::Float64) => true,
1000 (Datum::Float64(_), _) => false,
1001 (Datum::Date(_), ScalarType::Date) => true,
1002 (Datum::Date(_), _) => false,
1003 (Datum::Time(_), ScalarType::Time) => true,
1004 (Datum::Time(_), _) => false,
1005 (Datum::Timestamp(_), ScalarType::Timestamp { .. }) => true,
1006 (Datum::Timestamp(_), _) => false,
1007 (Datum::TimestampTz(_), ScalarType::TimestampTz { .. }) => true,
1008 (Datum::TimestampTz(_), _) => false,
1009 (Datum::Interval(_), ScalarType::Interval) => true,
1010 (Datum::Interval(_), _) => false,
1011 (Datum::Bytes(_), ScalarType::Bytes) => true,
1012 (Datum::Bytes(_), _) => false,
1013 (Datum::String(_), ScalarType::String)
1014 | (Datum::String(_), ScalarType::VarChar { .. })
1015 | (Datum::String(_), ScalarType::Char { .. })
1016 | (Datum::String(_), ScalarType::PgLegacyName) => true,
1017 (Datum::String(_), _) => false,
1018 (Datum::Uuid(_), ScalarType::Uuid) => true,
1019 (Datum::Uuid(_), _) => false,
1020 (Datum::Array(array), ScalarType::Array(t)) => {
1021 array.elements.iter().all(|e| match e {
1022 Datum::Null => true,
1023 _ => is_instance_of_scalar(e, t),
1024 })
1025 }
1026 (Datum::Array(array), ScalarType::Int2Vector) => {
1027 array.dims().len() == 1
1028 && array
1029 .elements
1030 .iter()
1031 .all(|e| is_instance_of_scalar(e, &ScalarType::Int16))
1032 }
1033 (Datum::Array(_), _) => false,
1034 (Datum::List(list), ScalarType::List { element_type, .. }) => list
1035 .iter()
1036 .all(|e| e.is_null() || is_instance_of_scalar(e, element_type)),
1037 (Datum::List(list), ScalarType::Record { fields, .. }) => {
1038 list.iter().zip_eq(fields).all(|(e, (_, t))| {
1039 (e.is_null() && t.nullable) || is_instance_of_scalar(e, &t.scalar_type)
1040 })
1041 }
1042 (Datum::List(_), _) => false,
1043 (Datum::Map(map), ScalarType::Map { value_type, .. }) => map
1044 .iter()
1045 .all(|(_k, v)| v.is_null() || is_instance_of_scalar(v, value_type)),
1046 (Datum::Map(_), _) => false,
1047 (Datum::JsonNull, _) => false,
1048 (Datum::Numeric(_), ScalarType::Numeric { .. }) => true,
1049 (Datum::Numeric(_), _) => false,
1050 (Datum::MzTimestamp(_), ScalarType::MzTimestamp) => true,
1051 (Datum::MzTimestamp(_), _) => false,
1052 (Datum::Range(Range { inner }), ScalarType::Range { element_type }) => {
1053 match inner {
1054 None => true,
1055 Some(inner) => {
1056 true && match inner.lower.bound {
1057 None => true,
1058 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1059 } && match inner.upper.bound {
1060 None => true,
1061 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1062 }
1063 }
1064 }
1065 }
1066 (Datum::Range(_), _) => false,
1067 (Datum::MzAclItem(_), ScalarType::MzAclItem) => true,
1068 (Datum::MzAclItem(_), _) => false,
1069 (Datum::AclItem(_), ScalarType::AclItem) => true,
1070 (Datum::AclItem(_), _) => false,
1071 }
1072 }
1073 }
1074 if column_type.nullable {
1075 if let Datum::Null = self {
1076 return true;
1077 }
1078 }
1079 is_instance_of_scalar(self, &column_type.scalar_type)
1080 }
1081}
1082
1083impl<'a> From<bool> for Datum<'a> {
1084 #[inline]
1085 fn from(b: bool) -> Datum<'a> {
1086 if b { Datum::True } else { Datum::False }
1087 }
1088}
1089
1090impl<'a, T> From<Overflowing<T>> for Datum<'a>
1093where
1094 Datum<'a>: From<T>,
1095{
1096 #[inline]
1097 fn from(i: Overflowing<T>) -> Datum<'a> {
1098 Datum::from(i.into_inner())
1099 }
1100}
1101
1102impl<'a> From<i16> for Datum<'a> {
1103 #[inline]
1104 fn from(i: i16) -> Datum<'a> {
1105 Datum::Int16(i)
1106 }
1107}
1108
1109impl<'a> From<i32> for Datum<'a> {
1110 #[inline]
1111 fn from(i: i32) -> Datum<'a> {
1112 Datum::Int32(i)
1113 }
1114}
1115
1116impl<'a> From<i64> for Datum<'a> {
1117 #[inline]
1118 fn from(i: i64) -> Datum<'a> {
1119 Datum::Int64(i)
1120 }
1121}
1122
1123impl<'a> From<u8> for Datum<'a> {
1124 #[inline]
1125 fn from(u: u8) -> Datum<'a> {
1126 Datum::UInt8(u)
1127 }
1128}
1129
1130impl<'a> From<u16> for Datum<'a> {
1131 #[inline]
1132 fn from(u: u16) -> Datum<'a> {
1133 Datum::UInt16(u)
1134 }
1135}
1136
1137impl<'a> From<u32> for Datum<'a> {
1138 #[inline]
1139 fn from(u: u32) -> Datum<'a> {
1140 Datum::UInt32(u)
1141 }
1142}
1143
1144impl<'a> From<u64> for Datum<'a> {
1145 #[inline]
1146 fn from(u: u64) -> Datum<'a> {
1147 Datum::UInt64(u)
1148 }
1149}
1150
1151impl<'a> From<OrderedFloat<f32>> for Datum<'a> {
1152 #[inline]
1153 fn from(f: OrderedFloat<f32>) -> Datum<'a> {
1154 Datum::Float32(f)
1155 }
1156}
1157
1158impl<'a> From<OrderedFloat<f64>> for Datum<'a> {
1159 #[inline]
1160 fn from(f: OrderedFloat<f64>) -> Datum<'a> {
1161 Datum::Float64(f)
1162 }
1163}
1164
1165impl<'a> From<f32> for Datum<'a> {
1166 #[inline]
1167 fn from(f: f32) -> Datum<'a> {
1168 Datum::Float32(OrderedFloat(f))
1169 }
1170}
1171
1172impl<'a> From<f64> for Datum<'a> {
1173 #[inline]
1174 fn from(f: f64) -> Datum<'a> {
1175 Datum::Float64(OrderedFloat(f))
1176 }
1177}
1178
1179impl<'a> From<i128> for Datum<'a> {
1180 #[inline]
1181 fn from(d: i128) -> Datum<'a> {
1182 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1183 }
1184}
1185
1186impl<'a> From<u128> for Datum<'a> {
1187 #[inline]
1188 fn from(d: u128) -> Datum<'a> {
1189 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1190 }
1191}
1192
1193impl<'a> From<Numeric> for Datum<'a> {
1194 #[inline]
1195 fn from(n: Numeric) -> Datum<'a> {
1196 Datum::Numeric(OrderedDecimal(n))
1197 }
1198}
1199
1200impl<'a> From<OrderedDecimal<Numeric>> for Datum<'a> {
1201 #[inline]
1202 fn from(n: OrderedDecimal<Numeric>) -> Datum<'a> {
1203 Datum::Numeric(n)
1204 }
1205}
1206
1207impl<'a> From<chrono::Duration> for Datum<'a> {
1208 #[inline]
1209 fn from(duration: chrono::Duration) -> Datum<'a> {
1210 let micros = duration.num_microseconds().unwrap_or(0);
1211 Datum::Interval(Interval::new(0, 0, micros))
1212 }
1213}
1214
1215impl<'a> From<Interval> for Datum<'a> {
1216 #[inline]
1217 fn from(other: Interval) -> Datum<'a> {
1218 Datum::Interval(other)
1219 }
1220}
1221
1222impl<'a> From<&'a str> for Datum<'a> {
1223 #[inline]
1224 fn from(s: &'a str) -> Datum<'a> {
1225 Datum::String(s)
1226 }
1227}
1228
1229impl<'a> From<&'a [u8]> for Datum<'a> {
1230 #[inline]
1231 fn from(b: &'a [u8]) -> Datum<'a> {
1232 Datum::Bytes(b)
1233 }
1234}
1235
1236impl<'a> From<Date> for Datum<'a> {
1237 #[inline]
1238 fn from(d: Date) -> Datum<'a> {
1239 Datum::Date(d)
1240 }
1241}
1242
1243impl<'a> From<NaiveTime> for Datum<'a> {
1244 #[inline]
1245 fn from(t: NaiveTime) -> Datum<'a> {
1246 Datum::Time(t)
1247 }
1248}
1249
1250impl<'a> From<CheckedTimestamp<NaiveDateTime>> for Datum<'a> {
1251 #[inline]
1252 fn from(dt: CheckedTimestamp<NaiveDateTime>) -> Datum<'a> {
1253 Datum::Timestamp(dt)
1254 }
1255}
1256
1257impl<'a> From<CheckedTimestamp<DateTime<Utc>>> for Datum<'a> {
1258 #[inline]
1259 fn from(dt: CheckedTimestamp<DateTime<Utc>>) -> Datum<'a> {
1260 Datum::TimestampTz(dt)
1261 }
1262}
1263
1264impl<'a> TryInto<Datum<'a>> for NaiveDateTime {
1265 type Error = TimestampError;
1266
1267 #[inline]
1268 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1269 let t = CheckedTimestamp::from_timestamplike(self)?;
1270 Ok(t.into())
1271 }
1272}
1273
1274impl<'a> TryInto<Datum<'a>> for DateTime<Utc> {
1275 type Error = TimestampError;
1276
1277 #[inline]
1278 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1279 let t = CheckedTimestamp::from_timestamplike(self)?;
1280 Ok(t.into())
1281 }
1282}
1283
1284impl<'a> From<Uuid> for Datum<'a> {
1285 #[inline]
1286 fn from(uuid: Uuid) -> Datum<'a> {
1287 Datum::Uuid(uuid)
1288 }
1289}
1290impl<'a> From<crate::Timestamp> for Datum<'a> {
1291 #[inline]
1292 fn from(ts: crate::Timestamp) -> Datum<'a> {
1293 Datum::MzTimestamp(ts)
1294 }
1295}
1296
1297impl<'a> From<MzAclItem> for Datum<'a> {
1298 #[inline]
1299 fn from(mz_acl_item: MzAclItem) -> Self {
1300 Datum::MzAclItem(mz_acl_item)
1301 }
1302}
1303
1304impl<'a, T> From<Option<T>> for Datum<'a>
1305where
1306 Datum<'a>: From<T>,
1307{
1308 fn from(o: Option<T>) -> Datum<'a> {
1309 match o {
1310 Some(d) => d.into(),
1311 None => Datum::Null,
1312 }
1313 }
1314}
1315
1316fn write_delimited<T, TS, F>(
1317 f: &mut fmt::Formatter,
1318 delimiter: &str,
1319 things: TS,
1320 write: F,
1321) -> fmt::Result
1322where
1323 TS: IntoIterator<Item = T>,
1324 F: Fn(&mut fmt::Formatter, T) -> fmt::Result,
1325{
1326 let mut iter = things.into_iter().peekable();
1327 while let Some(thing) = iter.next() {
1328 write(f, thing)?;
1329 if iter.peek().is_some() {
1330 f.write_str(delimiter)?;
1331 }
1332 }
1333 Ok(())
1334}
1335
1336impl fmt::Display for Datum<'_> {
1337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1338 match self {
1339 Datum::Null => f.write_str("null"),
1340 Datum::True => f.write_str("true"),
1341 Datum::False => f.write_str("false"),
1342 Datum::Int16(num) => write!(f, "{}", num),
1343 Datum::Int32(num) => write!(f, "{}", num),
1344 Datum::Int64(num) => write!(f, "{}", num),
1345 Datum::UInt8(num) => write!(f, "{}", num),
1346 Datum::UInt16(num) => write!(f, "{}", num),
1347 Datum::UInt32(num) => write!(f, "{}", num),
1348 Datum::UInt64(num) => write!(f, "{}", num),
1349 Datum::Float32(num) => write!(f, "{}", num),
1350 Datum::Float64(num) => write!(f, "{}", num),
1351 Datum::Date(d) => write!(f, "{}", d),
1352 Datum::Time(t) => write!(f, "{}", t),
1353 Datum::Timestamp(t) => write!(f, "{}", t),
1354 Datum::TimestampTz(t) => write!(f, "{}", t),
1355 Datum::Interval(iv) => write!(f, "{}", iv),
1356 Datum::Bytes(dat) => {
1357 f.write_str("0x")?;
1358 for b in dat.iter() {
1359 write!(f, "{:02x}", b)?;
1360 }
1361 Ok(())
1362 }
1363 Datum::String(s) => {
1364 write!(f, "{}", s.escaped())
1365 }
1366 Datum::Uuid(u) => write!(f, "{}", u),
1367 Datum::Array(array) => {
1368 if array.dims().into_iter().any(|dim| dim.lower_bound != 1) {
1369 write_delimited(f, "", array.dims().into_iter(), |f, e| {
1370 let (lower, upper) = e.dimension_bounds();
1371 write!(f, "[{}:{}]", lower, upper)
1372 })?;
1373 f.write_str("=")?;
1374 }
1375 f.write_str("{")?;
1376 write_delimited(f, ", ", &array.elements, |f, e| write!(f, "{}", e))?;
1377 f.write_str("}")
1378 }
1379 Datum::List(list) => {
1380 f.write_str("[")?;
1381 write_delimited(f, ", ", list, |f, e| write!(f, "{}", e))?;
1382 f.write_str("]")
1383 }
1384 Datum::Map(dict) => {
1385 f.write_str("{")?;
1386 write_delimited(f, ", ", dict, |f, (k, v)| write!(f, "{}: {}", k, v))?;
1387 f.write_str("}")
1388 }
1389 Datum::Numeric(n) => write!(f, "{}", n.0.to_standard_notation_string()),
1390 Datum::MzTimestamp(t) => write!(f, "{}", t),
1391 Datum::JsonNull => f.write_str("json_null"),
1392 Datum::Dummy => f.write_str("dummy"),
1393 Datum::Range(i) => write!(f, "{}", i),
1394 Datum::MzAclItem(mz_acl_item) => write!(f, "{mz_acl_item}"),
1395 Datum::AclItem(acl_item) => write!(f, "{acl_item}"),
1396 }
1397 }
1398}
1399
1400#[derive(
1405 Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash, EnumKind, MzReflect,
1406)]
1407#[enum_kind(ScalarBaseType, derive(PartialOrd, Ord, Hash))]
1408pub enum ScalarType {
1409 Bool,
1411 Int16,
1413 Int32,
1415 Int64,
1417 UInt16,
1419 UInt32,
1421 UInt64,
1423 Float32,
1425 Float64,
1427 Numeric {
1437 max_scale: Option<NumericMaxScale>,
1438 },
1439 Date,
1441 Time,
1443 Timestamp {
1445 precision: Option<TimestampPrecision>,
1446 },
1447 TimestampTz {
1449 precision: Option<TimestampPrecision>,
1450 },
1451 Interval,
1453 PgLegacyChar,
1458 PgLegacyName,
1464 Bytes,
1466 String,
1468 Char {
1474 length: Option<CharLength>,
1475 },
1476 VarChar {
1479 max_length: Option<VarCharMaxLength>,
1480 },
1481 Jsonb,
1493 Uuid,
1495 Array(Box<ScalarType>),
1501 List {
1506 element_type: Box<ScalarType>,
1507 custom_id: Option<CatalogItemId>,
1508 },
1509 Record {
1511 fields: Box<[(ColumnName, ColumnType)]>,
1516 custom_id: Option<CatalogItemId>,
1517 },
1518 Oid,
1520 Map {
1526 value_type: Box<ScalarType>,
1527 custom_id: Option<CatalogItemId>,
1528 },
1529 RegProc,
1531 RegType,
1533 RegClass,
1535 Int2Vector,
1538 MzTimestamp,
1540 Range {
1541 element_type: Box<ScalarType>,
1542 },
1543 MzAclItem,
1545 AclItem,
1547}
1548
1549impl RustType<ProtoRecordField> for (ColumnName, ColumnType) {
1550 fn into_proto(&self) -> ProtoRecordField {
1551 ProtoRecordField {
1552 column_name: Some(self.0.into_proto()),
1553 column_type: Some(self.1.into_proto()),
1554 }
1555 }
1556
1557 fn from_proto(proto: ProtoRecordField) -> Result<Self, TryFromProtoError> {
1558 Ok((
1559 proto
1560 .column_name
1561 .into_rust_if_some("ProtoRecordField::column_name")?,
1562 proto
1563 .column_type
1564 .into_rust_if_some("ProtoRecordField::column_type")?,
1565 ))
1566 }
1567}
1568
1569impl RustType<ProtoScalarType> for ScalarType {
1570 fn into_proto(&self) -> ProtoScalarType {
1571 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1572 use crate::relation_and_scalar::proto_scalar_type::*;
1573
1574 ProtoScalarType {
1575 kind: Some(match self {
1576 ScalarType::Bool => Bool(()),
1577 ScalarType::Int16 => Int16(()),
1578 ScalarType::Int32 => Int32(()),
1579 ScalarType::Int64 => Int64(()),
1580 ScalarType::UInt16 => UInt16(()),
1581 ScalarType::UInt32 => UInt32(()),
1582 ScalarType::UInt64 => UInt64(()),
1583 ScalarType::Float32 => Float32(()),
1584 ScalarType::Float64 => Float64(()),
1585 ScalarType::Date => Date(()),
1586 ScalarType::Time => Time(()),
1587 ScalarType::Timestamp { precision } => Timestamp(ProtoTimestamp {
1588 precision: precision.into_proto(),
1589 }),
1590 ScalarType::TimestampTz { precision } => TimestampTz(ProtoTimestampTz {
1591 precision: precision.into_proto(),
1592 }),
1593 ScalarType::Interval => Interval(()),
1594 ScalarType::PgLegacyChar => PgLegacyChar(()),
1595 ScalarType::PgLegacyName => PgLegacyName(()),
1596 ScalarType::Bytes => Bytes(()),
1597 ScalarType::String => String(()),
1598 ScalarType::Jsonb => Jsonb(()),
1599 ScalarType::Uuid => Uuid(()),
1600 ScalarType::Oid => Oid(()),
1601 ScalarType::RegProc => RegProc(()),
1602 ScalarType::RegType => RegType(()),
1603 ScalarType::RegClass => RegClass(()),
1604 ScalarType::Int2Vector => Int2Vector(()),
1605
1606 ScalarType::Numeric { max_scale } => Numeric(max_scale.into_proto()),
1607 ScalarType::Char { length } => Char(ProtoChar {
1608 length: length.into_proto(),
1609 }),
1610 ScalarType::VarChar { max_length } => VarChar(ProtoVarChar {
1611 max_length: max_length.into_proto(),
1612 }),
1613
1614 ScalarType::List {
1615 element_type,
1616 custom_id,
1617 } => List(Box::new(ProtoList {
1618 element_type: Some(element_type.into_proto()),
1619 custom_id: custom_id.map(|id| id.into_proto()),
1620 })),
1621 ScalarType::Record { custom_id, fields } => Record(ProtoRecord {
1622 custom_id: custom_id.map(|id| id.into_proto()),
1623 fields: fields.into_proto(),
1624 }),
1625 ScalarType::Array(typ) => Array(typ.into_proto()),
1626 ScalarType::Map {
1627 value_type,
1628 custom_id,
1629 } => Map(Box::new(ProtoMap {
1630 value_type: Some(value_type.into_proto()),
1631 custom_id: custom_id.map(|id| id.into_proto()),
1632 })),
1633 ScalarType::MzTimestamp => MzTimestamp(()),
1634 ScalarType::Range { element_type } => Range(Box::new(ProtoRange {
1635 element_type: Some(element_type.into_proto()),
1636 })),
1637 ScalarType::MzAclItem => MzAclItem(()),
1638 ScalarType::AclItem => AclItem(()),
1639 }),
1640 }
1641 }
1642
1643 fn from_proto(proto: ProtoScalarType) -> Result<Self, TryFromProtoError> {
1644 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1645
1646 let kind = proto
1647 .kind
1648 .ok_or_else(|| TryFromProtoError::missing_field("ProtoScalarType::Kind"))?;
1649
1650 match kind {
1651 Bool(()) => Ok(ScalarType::Bool),
1652 Int16(()) => Ok(ScalarType::Int16),
1653 Int32(()) => Ok(ScalarType::Int32),
1654 Int64(()) => Ok(ScalarType::Int64),
1655 UInt16(()) => Ok(ScalarType::UInt16),
1656 UInt32(()) => Ok(ScalarType::UInt32),
1657 UInt64(()) => Ok(ScalarType::UInt64),
1658 Float32(()) => Ok(ScalarType::Float32),
1659 Float64(()) => Ok(ScalarType::Float64),
1660 Date(()) => Ok(ScalarType::Date),
1661 Time(()) => Ok(ScalarType::Time),
1662 Timestamp(x) => Ok(ScalarType::Timestamp {
1663 precision: x.precision.into_rust()?,
1664 }),
1665 TimestampTz(x) => Ok(ScalarType::TimestampTz {
1666 precision: x.precision.into_rust()?,
1667 }),
1668 Interval(()) => Ok(ScalarType::Interval),
1669 PgLegacyChar(()) => Ok(ScalarType::PgLegacyChar),
1670 PgLegacyName(()) => Ok(ScalarType::PgLegacyName),
1671 Bytes(()) => Ok(ScalarType::Bytes),
1672 String(()) => Ok(ScalarType::String),
1673 Jsonb(()) => Ok(ScalarType::Jsonb),
1674 Uuid(()) => Ok(ScalarType::Uuid),
1675 Oid(()) => Ok(ScalarType::Oid),
1676 RegProc(()) => Ok(ScalarType::RegProc),
1677 RegType(()) => Ok(ScalarType::RegType),
1678 RegClass(()) => Ok(ScalarType::RegClass),
1679 Int2Vector(()) => Ok(ScalarType::Int2Vector),
1680
1681 Numeric(x) => Ok(ScalarType::Numeric {
1682 max_scale: x.into_rust()?,
1683 }),
1684 Char(x) => Ok(ScalarType::Char {
1685 length: x.length.into_rust()?,
1686 }),
1687
1688 VarChar(x) => Ok(ScalarType::VarChar {
1689 max_length: x.max_length.into_rust()?,
1690 }),
1691 Array(x) => Ok(ScalarType::Array({
1692 let st: ScalarType = (*x).into_rust()?;
1693 st.into()
1694 })),
1695 List(x) => Ok(ScalarType::List {
1696 element_type: Box::new(
1697 x.element_type
1698 .map(|x| *x)
1699 .into_rust_if_some("ProtoList::element_type")?,
1700 ),
1701 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1702 }),
1703 Record(x) => Ok(ScalarType::Record {
1704 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1705 fields: x.fields.into_rust()?,
1706 }),
1707 Map(x) => Ok(ScalarType::Map {
1708 value_type: Box::new(
1709 x.value_type
1710 .map(|x| *x)
1711 .into_rust_if_some("ProtoMap::value_type")?,
1712 ),
1713 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1714 }),
1715 MzTimestamp(()) => Ok(ScalarType::MzTimestamp),
1716 Range(x) => Ok(ScalarType::Range {
1717 element_type: Box::new(
1718 x.element_type
1719 .map(|x| *x)
1720 .into_rust_if_some("ProtoRange::element_type")?,
1721 ),
1722 }),
1723 MzAclItem(()) => Ok(ScalarType::MzAclItem),
1724 AclItem(()) => Ok(ScalarType::AclItem),
1725 }
1726 }
1727}
1728
1729pub trait AsColumnType {
1731 fn as_column_type() -> ColumnType;
1733}
1734
1735pub trait DatumType<'a, E>: Sized {
1737 fn nullable() -> bool;
1739
1740 fn fallible() -> bool;
1742
1743 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>>;
1746
1747 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E>;
1749}
1750
1751#[derive(Debug)]
1754pub struct ArrayRustType<T>(pub Vec<T>);
1755
1756impl<B: AsColumnType> AsColumnType for Option<B> {
1757 fn as_column_type() -> ColumnType {
1758 B::as_column_type().nullable(true)
1759 }
1760}
1761
1762impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for Option<B> {
1763 fn nullable() -> bool {
1764 true
1765 }
1766 fn fallible() -> bool {
1767 false
1768 }
1769 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1770 match res {
1771 Ok(Datum::Null) => Ok(None),
1772 Ok(datum) => B::try_from_result(Ok(datum)).map(Some),
1773 _ => Err(res),
1774 }
1775 }
1776 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1777 match self {
1778 Some(inner) => inner.into_result(temp_storage),
1779 None => Ok(Datum::Null),
1780 }
1781 }
1782}
1783
1784impl<E, B: AsColumnType> AsColumnType for Result<B, E> {
1785 fn as_column_type() -> ColumnType {
1786 B::as_column_type()
1787 }
1788}
1789
1790impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for Result<B, E> {
1791 fn nullable() -> bool {
1792 B::nullable()
1793 }
1794 fn fallible() -> bool {
1795 true
1796 }
1797 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1798 B::try_from_result(res).map(Ok)
1799 }
1800 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1801 self.and_then(|inner| inner.into_result(temp_storage))
1802 }
1803}
1804
1805macro_rules! impl_datum_type_copy {
1807 ($lt:lifetime, $native:ty, $variant:ident) => {
1808 impl<$lt> AsColumnType for $native {
1809 fn as_column_type() -> ColumnType {
1810 ScalarType::$variant.nullable(false)
1811 }
1812 }
1813
1814 impl<$lt, E> DatumType<$lt, E> for $native {
1815 fn nullable() -> bool {
1816 false
1817 }
1818
1819 fn fallible() -> bool {
1820 false
1821 }
1822
1823 fn try_from_result(res: Result<Datum<$lt>, E>) -> Result<Self, Result<Datum<$lt>, E>> {
1824 match res {
1825 Ok(Datum::$variant(f)) => Ok(f.into()),
1826 _ => Err(res),
1827 }
1828 }
1829
1830 fn into_result(self, _temp_storage: &$lt RowArena) -> Result<Datum<$lt>, E> {
1831 Ok(Datum::$variant(self.into()))
1832 }
1833 }
1834 };
1835 ($native:ty, $variant:ident) => {
1836 impl_datum_type_copy!('a, $native, $variant);
1837 };
1838}
1839
1840impl_datum_type_copy!(f32, Float32);
1841impl_datum_type_copy!(f64, Float64);
1842impl_datum_type_copy!(i16, Int16);
1843impl_datum_type_copy!(i32, Int32);
1844impl_datum_type_copy!(i64, Int64);
1845impl_datum_type_copy!(u16, UInt16);
1846impl_datum_type_copy!(u32, UInt32);
1847impl_datum_type_copy!(u64, UInt64);
1848impl_datum_type_copy!(Interval, Interval);
1849impl_datum_type_copy!(Date, Date);
1850impl_datum_type_copy!(NaiveTime, Time);
1851impl_datum_type_copy!(Uuid, Uuid);
1852impl_datum_type_copy!('a, &'a str, String);
1853impl_datum_type_copy!('a, &'a [u8], Bytes);
1854impl_datum_type_copy!(crate::Timestamp, MzTimestamp);
1855
1856impl<'a, E> DatumType<'a, E> for Datum<'a> {
1857 fn nullable() -> bool {
1858 true
1859 }
1860
1861 fn fallible() -> bool {
1862 false
1863 }
1864
1865 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1866 match res {
1867 Ok(datum) => Ok(datum),
1868 _ => Err(res),
1869 }
1870 }
1871
1872 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1873 Ok(self)
1874 }
1875}
1876
1877impl<'a, E> DatumType<'a, E> for DatumList<'a> {
1878 fn nullable() -> bool {
1879 false
1880 }
1881
1882 fn fallible() -> bool {
1883 false
1884 }
1885
1886 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1887 match res {
1888 Ok(Datum::List(list)) => Ok(list),
1889 _ => Err(res),
1890 }
1891 }
1892
1893 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1894 Ok(Datum::List(self))
1895 }
1896}
1897
1898impl<'a, E> DatumType<'a, E> for DatumMap<'a> {
1899 fn nullable() -> bool {
1900 false
1901 }
1902
1903 fn fallible() -> bool {
1904 false
1905 }
1906
1907 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1908 match res {
1909 Ok(Datum::Map(map)) => Ok(map),
1910 _ => Err(res),
1911 }
1912 }
1913
1914 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1915 Ok(Datum::Map(self))
1916 }
1917}
1918
1919impl<'a, E> DatumType<'a, E> for Range<DatumNested<'a>> {
1920 fn nullable() -> bool {
1921 false
1922 }
1923
1924 fn fallible() -> bool {
1925 false
1926 }
1927
1928 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1929 match res {
1930 Ok(Datum::Range(range)) => Ok(range),
1931 _ => Err(res),
1932 }
1933 }
1934
1935 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1936 Ok(Datum::Range(self))
1937 }
1938}
1939
1940impl<'a, E> DatumType<'a, E> for Range<Datum<'a>> {
1941 fn nullable() -> bool {
1942 false
1943 }
1944
1945 fn fallible() -> bool {
1946 false
1947 }
1948
1949 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1950 match res {
1951 Ok(r @ Datum::Range(..)) => Ok(r.unwrap_range()),
1952 _ => Err(res),
1953 }
1954 }
1955
1956 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1957 let d =
1958 self.into_bounds(|bound| temp_storage.make_datum_nested(|packer| packer.push(bound)));
1959 Ok(Datum::Range(d))
1960 }
1961}
1962
1963impl AsColumnType for bool {
1964 fn as_column_type() -> ColumnType {
1965 ScalarType::Bool.nullable(false)
1966 }
1967}
1968
1969impl<'a, E> DatumType<'a, E> for bool {
1970 fn nullable() -> bool {
1971 false
1972 }
1973
1974 fn fallible() -> bool {
1975 false
1976 }
1977
1978 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1979 match res {
1980 Ok(Datum::True) => Ok(true),
1981 Ok(Datum::False) => Ok(false),
1982 _ => Err(res),
1983 }
1984 }
1985
1986 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1987 if self {
1988 Ok(Datum::True)
1989 } else {
1990 Ok(Datum::False)
1991 }
1992 }
1993}
1994
1995impl AsColumnType for String {
1996 fn as_column_type() -> ColumnType {
1997 ScalarType::String.nullable(false)
1998 }
1999}
2000
2001impl<'a, E> DatumType<'a, E> for String {
2002 fn nullable() -> bool {
2003 false
2004 }
2005
2006 fn fallible() -> bool {
2007 false
2008 }
2009
2010 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2011 match res {
2012 Ok(Datum::String(s)) => Ok(s.to_owned()),
2013 _ => Err(res),
2014 }
2015 }
2016
2017 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2018 Ok(Datum::String(temp_storage.push_string(self)))
2019 }
2020}
2021
2022impl AsColumnType for ArrayRustType<String> {
2023 fn as_column_type() -> ColumnType {
2024 ScalarType::Array(Box::new(ScalarType::String)).nullable(false)
2025 }
2026}
2027
2028impl<'a, E> DatumType<'a, E> for ArrayRustType<String> {
2029 fn nullable() -> bool {
2030 false
2031 }
2032
2033 fn fallible() -> bool {
2034 false
2035 }
2036
2037 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2038 match res {
2039 Ok(Datum::Array(arr)) => Ok(ArrayRustType(
2040 arr.elements()
2041 .into_iter()
2042 .map(|d| d.unwrap_str().to_string())
2043 .collect(),
2044 )),
2045 _ => Err(res),
2046 }
2047 }
2048
2049 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2050 Ok(temp_storage.make_datum(|packer| {
2051 packer
2052 .try_push_array(
2053 &[ArrayDimension {
2054 lower_bound: 1,
2055 length: self.0.len(),
2056 }],
2057 self.0.iter().map(|elem| Datum::String(elem.as_str())),
2058 )
2059 .expect("self is 1 dimensional, and its length is used for the array length");
2060 }))
2061 }
2062}
2063
2064impl AsColumnType for Vec<u8> {
2065 fn as_column_type() -> ColumnType {
2066 ScalarType::Bytes.nullable(false)
2067 }
2068}
2069
2070impl<'a, E> DatumType<'a, E> for Vec<u8> {
2071 fn nullable() -> bool {
2072 false
2073 }
2074
2075 fn fallible() -> bool {
2076 false
2077 }
2078
2079 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2080 match res {
2081 Ok(Datum::Bytes(b)) => Ok(b.to_owned()),
2082 _ => Err(res),
2083 }
2084 }
2085
2086 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2087 Ok(Datum::Bytes(temp_storage.push_bytes(self)))
2088 }
2089}
2090
2091impl AsColumnType for Numeric {
2092 fn as_column_type() -> ColumnType {
2093 ScalarType::Numeric { max_scale: None }.nullable(false)
2094 }
2095}
2096
2097impl<'a, E> DatumType<'a, E> for Numeric {
2098 fn nullable() -> bool {
2099 false
2100 }
2101
2102 fn fallible() -> bool {
2103 false
2104 }
2105
2106 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2107 match res {
2108 Ok(Datum::Numeric(n)) => Ok(n.into_inner()),
2109 _ => Err(res),
2110 }
2111 }
2112
2113 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2114 Ok(Datum::from(self))
2115 }
2116}
2117
2118impl<'a, E> DatumType<'a, E> for OrderedDecimal<Numeric> {
2119 fn nullable() -> bool {
2120 false
2121 }
2122
2123 fn fallible() -> bool {
2124 false
2125 }
2126
2127 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2128 match res {
2129 Ok(Datum::Numeric(n)) => Ok(n),
2130 _ => Err(res),
2131 }
2132 }
2133
2134 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2135 Ok(Datum::from(self))
2136 }
2137}
2138
2139impl AsColumnType for PgLegacyChar {
2140 fn as_column_type() -> ColumnType {
2141 ScalarType::PgLegacyChar.nullable(false)
2142 }
2143}
2144
2145impl<'a, E> DatumType<'a, E> for PgLegacyChar {
2146 fn nullable() -> bool {
2147 false
2148 }
2149
2150 fn fallible() -> bool {
2151 false
2152 }
2153
2154 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2155 match res {
2156 Ok(Datum::UInt8(a)) => Ok(PgLegacyChar(a)),
2157 _ => Err(res),
2158 }
2159 }
2160
2161 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2162 Ok(Datum::UInt8(self.0))
2163 }
2164}
2165
2166impl<S> AsColumnType for PgLegacyName<S>
2167where
2168 S: AsRef<str>,
2169{
2170 fn as_column_type() -> ColumnType {
2171 ScalarType::PgLegacyName.nullable(false)
2172 }
2173}
2174
2175impl<'a, E> DatumType<'a, E> for PgLegacyName<&'a str> {
2176 fn nullable() -> bool {
2177 false
2178 }
2179
2180 fn fallible() -> bool {
2181 false
2182 }
2183
2184 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2185 match res {
2186 Ok(Datum::String(a)) => Ok(PgLegacyName(a)),
2187 _ => Err(res),
2188 }
2189 }
2190
2191 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2192 Ok(Datum::String(self.0))
2193 }
2194}
2195
2196impl<'a, E> DatumType<'a, E> for PgLegacyName<String> {
2197 fn nullable() -> bool {
2198 false
2199 }
2200
2201 fn fallible() -> bool {
2202 false
2203 }
2204
2205 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2206 match res {
2207 Ok(Datum::String(a)) => Ok(PgLegacyName(a.to_owned())),
2208 _ => Err(res),
2209 }
2210 }
2211
2212 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2213 Ok(Datum::String(temp_storage.push_string(self.0)))
2214 }
2215}
2216
2217impl AsColumnType for Oid {
2218 fn as_column_type() -> ColumnType {
2219 ScalarType::Oid.nullable(false)
2220 }
2221}
2222
2223impl<'a, E> DatumType<'a, E> for Oid {
2224 fn nullable() -> bool {
2225 false
2226 }
2227
2228 fn fallible() -> bool {
2229 false
2230 }
2231
2232 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2233 match res {
2234 Ok(Datum::UInt32(a)) => Ok(Oid(a)),
2235 _ => Err(res),
2236 }
2237 }
2238
2239 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2240 Ok(Datum::UInt32(self.0))
2241 }
2242}
2243
2244impl AsColumnType for RegClass {
2245 fn as_column_type() -> ColumnType {
2246 ScalarType::RegClass.nullable(false)
2247 }
2248}
2249
2250impl<'a, E> DatumType<'a, E> for RegClass {
2251 fn nullable() -> bool {
2252 false
2253 }
2254
2255 fn fallible() -> bool {
2256 false
2257 }
2258
2259 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2260 match res {
2261 Ok(Datum::UInt32(a)) => Ok(RegClass(a)),
2262 _ => Err(res),
2263 }
2264 }
2265
2266 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2267 Ok(Datum::UInt32(self.0))
2268 }
2269}
2270
2271impl AsColumnType for RegProc {
2272 fn as_column_type() -> ColumnType {
2273 ScalarType::RegProc.nullable(false)
2274 }
2275}
2276
2277impl<'a, E> DatumType<'a, E> for RegProc {
2278 fn nullable() -> bool {
2279 false
2280 }
2281
2282 fn fallible() -> bool {
2283 false
2284 }
2285
2286 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2287 match res {
2288 Ok(Datum::UInt32(a)) => Ok(RegProc(a)),
2289 _ => Err(res),
2290 }
2291 }
2292
2293 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2294 Ok(Datum::UInt32(self.0))
2295 }
2296}
2297
2298impl AsColumnType for RegType {
2299 fn as_column_type() -> ColumnType {
2300 ScalarType::RegType.nullable(false)
2301 }
2302}
2303
2304impl<'a, E> DatumType<'a, E> for RegType {
2305 fn nullable() -> bool {
2306 false
2307 }
2308
2309 fn fallible() -> bool {
2310 false
2311 }
2312
2313 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2314 match res {
2315 Ok(Datum::UInt32(a)) => Ok(RegType(a)),
2316 _ => Err(res),
2317 }
2318 }
2319
2320 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2321 Ok(Datum::UInt32(self.0))
2322 }
2323}
2324
2325impl<S> AsColumnType for Char<S>
2326where
2327 S: AsRef<str>,
2328{
2329 fn as_column_type() -> ColumnType {
2330 ScalarType::Char { length: None }.nullable(false)
2331 }
2332}
2333
2334impl<'a, E> DatumType<'a, E> for Char<&'a str> {
2335 fn nullable() -> bool {
2336 false
2337 }
2338
2339 fn fallible() -> bool {
2340 false
2341 }
2342
2343 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2344 match res {
2345 Ok(Datum::String(a)) => Ok(Char(a)),
2346 _ => Err(res),
2347 }
2348 }
2349
2350 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2351 Ok(Datum::String(self.0))
2352 }
2353}
2354
2355impl<'a, E> DatumType<'a, E> for Char<String> {
2356 fn nullable() -> bool {
2357 false
2358 }
2359
2360 fn fallible() -> bool {
2361 false
2362 }
2363
2364 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2365 match res {
2366 Ok(Datum::String(a)) => Ok(Char(a.to_owned())),
2367 _ => Err(res),
2368 }
2369 }
2370
2371 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2372 Ok(Datum::String(temp_storage.push_string(self.0)))
2373 }
2374}
2375
2376impl<S> AsColumnType for VarChar<S>
2377where
2378 S: AsRef<str>,
2379{
2380 fn as_column_type() -> ColumnType {
2381 ScalarType::Char { length: None }.nullable(false)
2382 }
2383}
2384
2385impl<'a, E> DatumType<'a, E> for VarChar<&'a str> {
2386 fn nullable() -> bool {
2387 false
2388 }
2389
2390 fn fallible() -> bool {
2391 false
2392 }
2393
2394 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2395 match res {
2396 Ok(Datum::String(a)) => Ok(VarChar(a)),
2397 _ => Err(res),
2398 }
2399 }
2400
2401 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2402 Ok(Datum::String(self.0))
2403 }
2404}
2405
2406impl<'a, E> DatumType<'a, E> for VarChar<String> {
2407 fn nullable() -> bool {
2408 false
2409 }
2410
2411 fn fallible() -> bool {
2412 false
2413 }
2414
2415 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2416 match res {
2417 Ok(Datum::String(a)) => Ok(VarChar(a.to_owned())),
2418 _ => Err(res),
2419 }
2420 }
2421
2422 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2423 Ok(Datum::String(temp_storage.push_string(self.0)))
2424 }
2425}
2426
2427impl<'a, E> DatumType<'a, E> for Jsonb {
2428 fn nullable() -> bool {
2429 false
2430 }
2431
2432 fn fallible() -> bool {
2433 false
2434 }
2435
2436 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2437 Ok(JsonbRef::try_from_result(res)?.to_owned())
2438 }
2439
2440 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2441 Ok(temp_storage.push_unary_row(self.into_row()))
2442 }
2443}
2444
2445impl AsColumnType for Jsonb {
2446 fn as_column_type() -> ColumnType {
2447 ScalarType::Jsonb.nullable(false)
2448 }
2449}
2450
2451impl<'a, E> DatumType<'a, E> for JsonbRef<'a> {
2452 fn nullable() -> bool {
2453 false
2454 }
2455
2456 fn fallible() -> bool {
2457 false
2458 }
2459
2460 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2461 match res {
2462 Ok(
2463 d @ (Datum::JsonNull
2464 | Datum::True
2465 | Datum::False
2466 | Datum::Numeric(_)
2467 | Datum::String(_)
2468 | Datum::List(_)
2469 | Datum::Map(_)),
2470 ) => Ok(JsonbRef::from_datum(d)),
2471 _ => Err(res),
2472 }
2473 }
2474
2475 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2476 Ok(self.into_datum())
2477 }
2478}
2479
2480impl<'a> AsColumnType for JsonbRef<'a> {
2481 fn as_column_type() -> ColumnType {
2482 ScalarType::Jsonb.nullable(false)
2483 }
2484}
2485
2486impl AsColumnType for MzAclItem {
2487 fn as_column_type() -> ColumnType {
2488 ScalarType::MzAclItem.nullable(false)
2489 }
2490}
2491
2492impl<'a, E> DatumType<'a, E> for MzAclItem {
2493 fn nullable() -> bool {
2494 false
2495 }
2496
2497 fn fallible() -> bool {
2498 false
2499 }
2500
2501 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2502 match res {
2503 Ok(Datum::MzAclItem(mz_acl_item)) => Ok(mz_acl_item),
2504 _ => Err(res),
2505 }
2506 }
2507
2508 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2509 Ok(Datum::MzAclItem(self))
2510 }
2511}
2512
2513impl AsColumnType for AclItem {
2514 fn as_column_type() -> ColumnType {
2515 ScalarType::AclItem.nullable(false)
2516 }
2517}
2518
2519impl<'a, E> DatumType<'a, E> for AclItem {
2520 fn nullable() -> bool {
2521 false
2522 }
2523
2524 fn fallible() -> bool {
2525 false
2526 }
2527
2528 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2529 match res {
2530 Ok(Datum::AclItem(acl_item)) => Ok(acl_item),
2531 _ => Err(res),
2532 }
2533 }
2534
2535 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2536 Ok(Datum::AclItem(self))
2537 }
2538}
2539
2540impl AsColumnType for CheckedTimestamp<NaiveDateTime> {
2541 fn as_column_type() -> ColumnType {
2542 ScalarType::Timestamp { precision: None }.nullable(false)
2543 }
2544}
2545
2546impl<'a, E> DatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
2547 fn nullable() -> bool {
2548 false
2549 }
2550
2551 fn fallible() -> bool {
2552 false
2553 }
2554
2555 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2556 match res {
2557 Ok(Datum::Timestamp(a)) => Ok(a),
2558 _ => Err(res),
2559 }
2560 }
2561
2562 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2563 Ok(Datum::Timestamp(self))
2564 }
2565}
2566
2567impl AsColumnType for CheckedTimestamp<DateTime<Utc>> {
2568 fn as_column_type() -> ColumnType {
2569 ScalarType::TimestampTz { precision: None }.nullable(false)
2570 }
2571}
2572
2573impl<'a, E> DatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
2574 fn nullable() -> bool {
2575 false
2576 }
2577
2578 fn fallible() -> bool {
2579 false
2580 }
2581
2582 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2583 match res {
2584 Ok(Datum::TimestampTz(a)) => Ok(a),
2585 _ => Err(res),
2586 }
2587 }
2588
2589 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2590 Ok(Datum::TimestampTz(self))
2591 }
2592}
2593
2594impl ScalarType {
2595 pub fn unwrap_numeric_max_scale(&self) -> Option<NumericMaxScale> {
2601 match self {
2602 ScalarType::Numeric { max_scale } => *max_scale,
2603 _ => panic!("ScalarType::unwrap_numeric_scale called on {:?}", self),
2604 }
2605 }
2606
2607 pub fn unwrap_timestamp_precision(&self) -> Option<TimestampPrecision> {
2614 match self {
2615 ScalarType::Timestamp { precision } | ScalarType::TimestampTz { precision } => {
2616 *precision
2617 }
2618 _ => panic!(
2619 "ScalarType::unwrap_timestamp_precision called on {:?}",
2620 self
2621 ),
2622 }
2623 }
2624
2625 pub fn unwrap_list_element_type(&self) -> &ScalarType {
2631 match self {
2632 ScalarType::List { element_type, .. } => element_type,
2633 _ => panic!("ScalarType::unwrap_list_element_type called on {:?}", self),
2634 }
2635 }
2636
2637 pub fn unwrap_list_nth_layer_type(&self, layer: usize) -> &ScalarType {
2650 if layer == 0 {
2651 return self;
2652 }
2653 match self {
2654 ScalarType::List { element_type, .. } => {
2655 element_type.unwrap_list_nth_layer_type(layer - 1)
2656 }
2657 _ => panic!(
2658 "ScalarType::unwrap_list_nth_layer_type called on {:?}",
2659 self
2660 ),
2661 }
2662 }
2663
2664 pub fn unwrap_record_element_type(&self) -> Vec<&ScalarType> {
2670 match self {
2671 ScalarType::Record { fields, .. } => {
2672 fields.iter().map(|(_, t)| &t.scalar_type).collect_vec()
2673 }
2674 _ => panic!(
2675 "ScalarType::unwrap_record_element_type called on {:?}",
2676 self
2677 ),
2678 }
2679 }
2680
2681 pub fn unwrap_record_element_column_type(&self) -> Vec<&ColumnType> {
2687 match self {
2688 ScalarType::Record { fields, .. } => fields.iter().map(|(_, t)| t).collect_vec(),
2689 _ => panic!(
2690 "ScalarType::unwrap_record_element_column_type called on {:?}",
2691 self
2692 ),
2693 }
2694 }
2695
2696 pub fn unwrap_list_n_layers(&self) -> usize {
2703 let mut descender = self.unwrap_list_element_type();
2704 let mut layers = 1;
2705
2706 while let ScalarType::List { element_type, .. } = descender {
2707 layers += 1;
2708 descender = element_type;
2709 }
2710
2711 layers
2712 }
2713
2714 pub fn without_modifiers(&self) -> ScalarType {
2718 use ScalarType::*;
2719 match self {
2720 List {
2721 element_type,
2722 custom_id: None,
2723 } => List {
2724 element_type: Box::new(element_type.without_modifiers()),
2725 custom_id: None,
2726 },
2727 Map {
2728 value_type,
2729 custom_id: None,
2730 } => Map {
2731 value_type: Box::new(value_type.without_modifiers()),
2732 custom_id: None,
2733 },
2734 Record {
2735 fields,
2736 custom_id: None,
2737 } => {
2738 let fields = fields
2739 .iter()
2740 .map(|(column_name, column_type)| {
2741 (
2742 column_name.clone(),
2743 ColumnType {
2744 scalar_type: column_type.scalar_type.without_modifiers(),
2745 nullable: column_type.nullable,
2746 },
2747 )
2748 })
2749 .collect();
2750 Record {
2751 fields,
2752 custom_id: None,
2753 }
2754 }
2755 Array(a) => Array(Box::new(a.without_modifiers())),
2756 Numeric { .. } => Numeric { max_scale: None },
2757 Char { .. } => Char { length: None },
2760 VarChar { .. } => VarChar { max_length: None },
2761 Range { element_type } => Range {
2762 element_type: Box::new(element_type.without_modifiers()),
2763 },
2764 v => v.clone(),
2765 }
2766 }
2767
2768 pub fn unwrap_array_element_type(&self) -> &ScalarType {
2777 match self {
2778 ScalarType::Array(s) => &**s,
2779 ScalarType::Int2Vector => &ScalarType::Int16,
2780 _ => panic!("ScalarType::unwrap_array_element_type called on {:?}", self),
2781 }
2782 }
2783
2784 pub fn unwrap_collection_element_type(&self) -> &ScalarType {
2792 match self {
2793 ScalarType::Array(element_type) => element_type,
2794 ScalarType::Int2Vector => &ScalarType::Int16,
2795 ScalarType::List { element_type, .. } => element_type,
2796 _ => panic!(
2797 "ScalarType::unwrap_collection_element_type called on {:?}",
2798 self
2799 ),
2800 }
2801 }
2802
2803 pub fn unwrap_map_value_type(&self) -> &ScalarType {
2809 match self {
2810 ScalarType::Map { value_type, .. } => &**value_type,
2811 _ => panic!("ScalarType::unwrap_map_value_type called on {:?}", self),
2812 }
2813 }
2814
2815 pub fn unwrap_char_length(&self) -> Option<CharLength> {
2821 match self {
2822 ScalarType::Char { length, .. } => *length,
2823 _ => panic!("ScalarType::unwrap_char_length called on {:?}", self),
2824 }
2825 }
2826
2827 pub fn unwrap_varchar_max_length(&self) -> Option<VarCharMaxLength> {
2833 match self {
2834 ScalarType::VarChar { max_length, .. } => *max_length,
2835 _ => panic!("ScalarType::unwrap_varchar_max_length called on {:?}", self),
2836 }
2837 }
2838
2839 pub fn unwrap_range_element_type(&self) -> &ScalarType {
2845 match self {
2846 ScalarType::Range { element_type } => &**element_type,
2847 _ => panic!("ScalarType::unwrap_range_element_type called on {:?}", self),
2848 }
2849 }
2850
2851 pub fn near_match(&self) -> Option<&'static ScalarType> {
2875 match self {
2876 ScalarType::UInt16 => Some(&ScalarType::Int32),
2877 ScalarType::UInt32 => Some(&ScalarType::Int64),
2878 ScalarType::UInt64 => Some(&ScalarType::Numeric { max_scale: None }),
2879 _ => None,
2880 }
2881 }
2882
2883 pub const fn nullable(self, nullable: bool) -> ColumnType {
2886 ColumnType {
2887 nullable,
2888 scalar_type: self,
2889 }
2890 }
2891
2892 pub fn is_vec(&self) -> bool {
2896 matches!(
2897 self,
2898 ScalarType::Array(_) | ScalarType::Int2Vector | ScalarType::List { .. }
2899 )
2900 }
2901
2902 pub fn is_custom_type(&self) -> bool {
2903 use ScalarType::*;
2904 match self {
2905 List {
2906 element_type: t,
2907 custom_id,
2908 }
2909 | Map {
2910 value_type: t,
2911 custom_id,
2912 } => custom_id.is_some() || t.is_custom_type(),
2913 Record {
2914 fields, custom_id, ..
2915 } => {
2916 custom_id.is_some()
2917 || fields
2918 .iter()
2919 .map(|(_, t)| t)
2920 .any(|t| t.scalar_type.is_custom_type())
2921 }
2922 _ => false,
2923 }
2924 }
2925
2926 pub fn base_eq(&self, other: &ScalarType) -> bool {
2939 self.eq_inner(other, false)
2940 }
2941
2942 pub fn structural_eq(&self, other: &ScalarType) -> bool {
2945 self.eq_inner(other, true)
2946 }
2947
2948 pub fn eq_inner(&self, other: &ScalarType, structure_only: bool) -> bool {
2949 use ScalarType::*;
2950 match (self, other) {
2951 (
2952 List {
2953 element_type: l,
2954 custom_id: oid_l,
2955 },
2956 List {
2957 element_type: r,
2958 custom_id: oid_r,
2959 },
2960 )
2961 | (
2962 Map {
2963 value_type: l,
2964 custom_id: oid_l,
2965 },
2966 Map {
2967 value_type: r,
2968 custom_id: oid_r,
2969 },
2970 ) => l.eq_inner(r, structure_only) && (oid_l == oid_r || structure_only),
2971 (Array(a), Array(b)) | (Range { element_type: a }, Range { element_type: b }) => {
2972 a.eq_inner(b, structure_only)
2973 }
2974 (
2975 Record {
2976 fields: fields_a,
2977 custom_id: oid_a,
2978 },
2979 Record {
2980 fields: fields_b,
2981 custom_id: oid_b,
2982 },
2983 ) => {
2984 (oid_a == oid_b || structure_only)
2985 && fields_a.len() == fields_b.len()
2986 && fields_a
2987 .iter()
2988 .zip(fields_b)
2989 .all(|(a, b)| {
2991 (a.0 == b.0 || structure_only)
2992 && a.1.scalar_type.eq_inner(&b.1.scalar_type, structure_only)
2993 })
2994 }
2995 (s, o) => ScalarBaseType::from(s) == ScalarBaseType::from(o),
2996 }
2997 }
2998
2999 pub fn interesting_datums(&self) -> impl Iterator<Item = Datum<'static>> {
3001 static BOOL: LazyLock<Row> =
3007 LazyLock::new(|| Row::pack_slice(&[Datum::True, Datum::False]));
3008 static INT16: LazyLock<Row> = LazyLock::new(|| {
3009 Row::pack_slice(&[
3010 Datum::Int16(0),
3011 Datum::Int16(1),
3012 Datum::Int16(-1),
3013 Datum::Int16(i16::MIN),
3014 Datum::Int16(i16::MIN + 1),
3015 Datum::Int16(i16::MAX),
3016 Datum::Int16(127),
3024 Datum::Int16(128),
3025 ])
3026 });
3027 static INT32: LazyLock<Row> = LazyLock::new(|| {
3028 Row::pack_slice(&[
3029 Datum::Int32(0),
3030 Datum::Int32(1),
3031 Datum::Int32(-1),
3032 Datum::Int32(i32::MIN),
3033 Datum::Int32(i32::MIN + 1),
3034 Datum::Int32(i32::MAX),
3035 Datum::Int32(32767),
3039 Datum::Int32(32768),
3040 ])
3041 });
3042 static INT64: LazyLock<Row> = LazyLock::new(|| {
3043 Row::pack_slice(&[
3044 Datum::Int64(0),
3045 Datum::Int64(1),
3046 Datum::Int64(-1),
3047 Datum::Int64(i64::MIN),
3048 Datum::Int64(i64::MIN + 1),
3049 Datum::Int64(i64::MAX),
3050 Datum::Int64(2147483647),
3054 Datum::Int64(2147483648),
3055 ])
3056 });
3057 static UINT16: LazyLock<Row> = LazyLock::new(|| {
3058 Row::pack_slice(&[
3059 Datum::UInt16(0),
3060 Datum::UInt16(1),
3061 Datum::UInt16(u16::MAX),
3062 Datum::UInt16(255),
3066 Datum::UInt16(256),
3067 ])
3068 });
3069 static UINT32: LazyLock<Row> = LazyLock::new(|| {
3070 Row::pack_slice(&[
3071 Datum::UInt32(0),
3072 Datum::UInt32(1),
3073 Datum::UInt32(u32::MAX),
3074 Datum::UInt32(32767),
3078 Datum::UInt32(32768),
3079 ])
3080 });
3081 static UINT64: LazyLock<Row> = LazyLock::new(|| {
3082 Row::pack_slice(&[
3083 Datum::UInt64(0),
3084 Datum::UInt64(1),
3085 Datum::UInt64(u64::MAX),
3086 Datum::UInt64(2147483647),
3090 Datum::UInt64(2147483648),
3091 ])
3092 });
3093 static FLOAT32: LazyLock<Row> = LazyLock::new(|| {
3094 Row::pack_slice(&[
3095 Datum::Float32(OrderedFloat(0.0)),
3096 Datum::Float32(OrderedFloat(1.0)),
3097 Datum::Float32(OrderedFloat(-1.0)),
3098 Datum::Float32(OrderedFloat(f32::MIN)),
3099 Datum::Float32(OrderedFloat(f32::MIN_POSITIVE)),
3100 Datum::Float32(OrderedFloat(f32::MAX)),
3101 Datum::Float32(OrderedFloat(f32::EPSILON)),
3102 Datum::Float32(OrderedFloat(f32::NAN)),
3103 Datum::Float32(OrderedFloat(f32::INFINITY)),
3104 Datum::Float32(OrderedFloat(f32::NEG_INFINITY)),
3105 ])
3106 });
3107 static FLOAT64: LazyLock<Row> = LazyLock::new(|| {
3108 Row::pack_slice(&[
3109 Datum::Float64(OrderedFloat(0.0)),
3110 Datum::Float64(OrderedFloat(1.0)),
3111 Datum::Float64(OrderedFloat(-1.0)),
3112 Datum::Float64(OrderedFloat(f64::MIN)),
3113 Datum::Float64(OrderedFloat(f64::MIN_POSITIVE)),
3114 Datum::Float64(OrderedFloat(f64::MAX)),
3115 Datum::Float64(OrderedFloat(f64::EPSILON)),
3116 Datum::Float64(OrderedFloat(f64::NAN)),
3117 Datum::Float64(OrderedFloat(f64::INFINITY)),
3118 Datum::Float64(OrderedFloat(f64::NEG_INFINITY)),
3119 ])
3120 });
3121 static NUMERIC: LazyLock<Row> = LazyLock::new(|| {
3122 cfg_if::cfg_if! {
3123 if #[cfg(miri)] {
3125 Row::pack_slice(&[])
3126 } else {
3127 Row::pack_slice(&[
3128 Datum::Numeric(OrderedDecimal(Numeric::from(0.0))),
3129 Datum::Numeric(OrderedDecimal(Numeric::from(1.0))),
3130 Datum::Numeric(OrderedDecimal(Numeric::from(-1.0))),
3131 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN))),
3132 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN_POSITIVE))),
3133 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MAX))),
3134 Datum::Numeric(OrderedDecimal(Numeric::from(f64::EPSILON))),
3135 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NAN))),
3136 Datum::Numeric(OrderedDecimal(Numeric::from(f64::INFINITY))),
3137 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NEG_INFINITY))),
3138 ])
3139 }
3140 }
3141 });
3142 static DATE: LazyLock<Row> = LazyLock::new(|| {
3143 Row::pack_slice(&[
3144 Datum::Date(Date::from_pg_epoch(0).unwrap()),
3145 Datum::Date(Date::from_pg_epoch(Date::LOW_DAYS).unwrap()),
3146 Datum::Date(Date::from_pg_epoch(Date::HIGH_DAYS).unwrap()),
3147 ])
3148 });
3149 static TIME: LazyLock<Row> = LazyLock::new(|| {
3150 Row::pack_slice(&[
3151 Datum::Time(NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap()),
3152 Datum::Time(NaiveTime::from_hms_micro_opt(23, 59, 59, 999_999).unwrap()),
3153 ])
3154 });
3155 static TIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3156 Row::pack_slice(&[
3157 Datum::Timestamp(
3158 DateTime::from_timestamp(0, 0)
3159 .unwrap()
3160 .naive_utc()
3161 .try_into()
3162 .unwrap(),
3163 ),
3164 Datum::Timestamp(
3165 crate::adt::timestamp::LOW_DATE
3166 .and_hms_opt(0, 0, 0)
3167 .unwrap()
3168 .try_into()
3169 .unwrap(),
3170 ),
3171 Datum::Timestamp(
3172 crate::adt::timestamp::HIGH_DATE
3173 .and_hms_opt(23, 59, 59)
3174 .unwrap()
3175 .try_into()
3176 .unwrap(),
3177 ),
3178 Datum::Timestamp(
3180 DateTime::from_timestamp(0, 123456789)
3181 .unwrap()
3182 .naive_utc()
3183 .try_into()
3184 .unwrap(),
3185 ),
3186 Datum::Timestamp(
3188 CheckedTimestamp::from_timestamplike(
3189 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
3190 .unwrap()
3191 .and_hms_milli_opt(23, 59, 59, 1234)
3192 .unwrap(),
3193 )
3194 .unwrap(),
3195 ),
3196 ])
3197 });
3198 static TIMESTAMPTZ: LazyLock<Row> = LazyLock::new(|| {
3199 Row::pack_slice(&[
3200 Datum::TimestampTz(DateTime::from_timestamp(0, 0).unwrap().try_into().unwrap()),
3201 Datum::TimestampTz(
3202 DateTime::from_naive_utc_and_offset(
3203 crate::adt::timestamp::LOW_DATE
3204 .and_hms_opt(0, 0, 0)
3205 .unwrap(),
3206 Utc,
3207 )
3208 .try_into()
3209 .unwrap(),
3210 ),
3211 Datum::TimestampTz(
3212 DateTime::from_naive_utc_and_offset(
3213 crate::adt::timestamp::HIGH_DATE
3214 .and_hms_opt(23, 59, 59)
3215 .unwrap(),
3216 Utc,
3217 )
3218 .try_into()
3219 .unwrap(),
3220 ),
3221 Datum::TimestampTz(
3223 DateTime::from_timestamp(0, 123456789)
3224 .unwrap()
3225 .try_into()
3226 .unwrap(),
3227 ),
3228 ])
3229 });
3230 static INTERVAL: LazyLock<Row> = LazyLock::new(|| {
3231 Row::pack_slice(&[
3232 Datum::Interval(Interval::new(0, 0, 0)),
3233 Datum::Interval(Interval::new(1, 1, 1)),
3234 Datum::Interval(Interval::new(-1, -1, -1)),
3235 Datum::Interval(Interval::new(1, 0, 0)),
3236 Datum::Interval(Interval::new(0, 1, 0)),
3237 Datum::Interval(Interval::new(0, 0, 1)),
3238 Datum::Interval(Interval::new(-1, 0, 0)),
3239 Datum::Interval(Interval::new(0, -1, 0)),
3240 Datum::Interval(Interval::new(0, 0, -1)),
3241 Datum::Interval(Interval::new(i32::MIN, i32::MIN, i64::MIN)),
3242 Datum::Interval(Interval::new(i32::MAX, i32::MAX, i64::MAX)),
3243 Datum::Interval(Interval::new(i32::MIN, 0, 0)),
3244 Datum::Interval(Interval::new(i32::MAX, 0, 0)),
3245 Datum::Interval(Interval::new(0, i32::MIN, 0)),
3246 Datum::Interval(Interval::new(0, i32::MAX, 0)),
3247 Datum::Interval(Interval::new(0, 0, i64::MIN)),
3248 Datum::Interval(Interval::new(0, 0, i64::MAX)),
3249 ])
3250 });
3251 static PGLEGACYCHAR: LazyLock<Row> =
3252 LazyLock::new(|| Row::pack_slice(&[Datum::UInt8(u8::MIN), Datum::UInt8(u8::MAX)]));
3253 static PGLEGACYNAME: LazyLock<Row> = LazyLock::new(|| {
3254 Row::pack_slice(&[
3255 Datum::String(""),
3256 Datum::String(" "),
3257 Datum::String("'"),
3258 Datum::String("\""),
3259 Datum::String("."),
3260 Datum::String(&"x".repeat(64)),
3261 ])
3262 });
3263 static BYTES: LazyLock<Row> = LazyLock::new(|| {
3264 Row::pack_slice(&[Datum::Bytes(&[]), Datum::Bytes(&[0]), Datum::Bytes(&[255])])
3265 });
3266 static STRING: LazyLock<Row> = LazyLock::new(|| {
3267 Row::pack_slice(&[
3268 Datum::String(""),
3269 Datum::String(" "),
3270 Datum::String("'"),
3271 Datum::String("\""),
3272 Datum::String("."),
3273 Datum::String("2015-09-18T23:56:04.123Z"),
3274 Datum::String(&"x".repeat(100)),
3275 Datum::String("JAPAN"),
3277 Datum::String("1,2,3"),
3278 Datum::String("\r\n"),
3279 Datum::String("\"\""),
3280 ])
3281 });
3282 static CHAR: LazyLock<Row> = LazyLock::new(|| {
3283 Row::pack_slice(&[
3284 Datum::String(" "),
3285 Datum::String("'"),
3286 Datum::String("\""),
3287 Datum::String("."),
3288 Datum::String(","),
3289 Datum::String("\t"),
3290 Datum::String("\n"),
3291 Datum::String("\r"),
3292 Datum::String("\\"),
3293 Datum::String(std::str::from_utf8(b"\x00").unwrap()),
3295 Datum::String(std::str::from_utf8(b"\x02").unwrap()),
3297 Datum::String(std::str::from_utf8(b"\x03").unwrap()),
3299 Datum::String(std::str::from_utf8(b"\x08").unwrap()),
3301 Datum::String(std::str::from_utf8(b"\x1B").unwrap()),
3303 Datum::String(std::str::from_utf8(b"\x7F").unwrap()),
3305 ])
3306 });
3307 static JSONB: LazyLock<Row> = LazyLock::new(|| {
3308 let mut datums = vec![Datum::True, Datum::False, Datum::JsonNull];
3309 datums.extend(STRING.iter());
3310 datums.extend(NUMERIC.iter().filter(|n| {
3311 let Datum::Numeric(n) = n else {
3312 panic!("expected Numeric, found {n:?}");
3313 };
3314 !(n.0.is_nan() || n.0.is_infinite())
3316 }));
3317 Row::pack_slice(&datums)
3319 });
3320 static UUID: LazyLock<Row> = LazyLock::new(|| {
3321 Row::pack_slice(&[
3322 Datum::Uuid(Uuid::from_u128(u128::MIN)),
3323 Datum::Uuid(Uuid::from_u128(u128::MAX)),
3324 ])
3325 });
3326 static ARRAY: LazyLock<BTreeMap<&'static ScalarType, Row>> = LazyLock::new(|| {
3327 let generate_row = |inner_type: &ScalarType| {
3328 let datums: Vec<_> = inner_type.interesting_datums().collect();
3329
3330 let mut row = Row::default();
3331 row.packer()
3332 .try_push_array::<_, Datum<'static>>(
3333 &[ArrayDimension {
3334 lower_bound: 1,
3335 length: 0,
3336 }],
3337 [],
3338 )
3339 .expect("failed to push empty array");
3340 row.packer()
3341 .try_push_array(
3342 &[ArrayDimension {
3343 lower_bound: 1,
3344 length: datums.len(),
3345 }],
3346 datums,
3347 )
3348 .expect("failed to push array");
3349
3350 row
3351 };
3352
3353 ScalarType::enumerate()
3354 .into_iter()
3355 .filter(|ty| !matches!(ty, ScalarType::Array(_)))
3356 .map(|ty| (ty, generate_row(ty)))
3357 .collect()
3358 });
3359 static EMPTY_ARRAY: LazyLock<Row> = LazyLock::new(|| {
3360 let mut row = Row::default();
3361 row.packer()
3362 .try_push_array::<_, Datum<'static>>(
3363 &[ArrayDimension {
3364 lower_bound: 1,
3365 length: 0,
3366 }],
3367 [],
3368 )
3369 .expect("failed to push empty array");
3370 row
3371 });
3372 static LIST: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3373 static RECORD: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3374 static OID: LazyLock<Row> =
3375 LazyLock::new(|| Row::pack_slice(&[Datum::UInt32(u32::MIN), Datum::UInt32(u32::MAX)]));
3376 static MAP: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3377 static INT2VECTOR: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3378 static MZTIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3379 Row::pack_slice(&[
3380 Datum::MzTimestamp(crate::Timestamp::MIN),
3381 Datum::MzTimestamp(crate::Timestamp::MAX),
3382 ])
3383 });
3384 static RANGE: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3385 static MZACLITEM: LazyLock<Row> = LazyLock::new(|| {
3386 Row::pack_slice(&[
3387 Datum::MzAclItem(MzAclItem {
3388 grantee: RoleId::Public,
3389 grantor: RoleId::Public,
3390 acl_mode: AclMode::empty(),
3391 }),
3392 Datum::MzAclItem(MzAclItem {
3393 grantee: RoleId::Public,
3394 grantor: RoleId::Public,
3395 acl_mode: AclMode::all(),
3396 }),
3397 Datum::MzAclItem(MzAclItem {
3398 grantee: RoleId::User(42),
3399 grantor: RoleId::Public,
3400 acl_mode: AclMode::empty(),
3401 }),
3402 Datum::MzAclItem(MzAclItem {
3403 grantee: RoleId::User(42),
3404 grantor: RoleId::Public,
3405 acl_mode: AclMode::all(),
3406 }),
3407 Datum::MzAclItem(MzAclItem {
3408 grantee: RoleId::Public,
3409 grantor: RoleId::User(42),
3410 acl_mode: AclMode::empty(),
3411 }),
3412 Datum::MzAclItem(MzAclItem {
3413 grantee: RoleId::Public,
3414 grantor: RoleId::User(42),
3415 acl_mode: AclMode::all(),
3416 }),
3417 ])
3418 });
3419 static ACLITEM: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3421
3422 let iter: Box<dyn Iterator<Item = Datum<'static>>> = match self {
3423 ScalarType::Bool => Box::new((*BOOL).iter()),
3424 ScalarType::Int16 => Box::new((*INT16).iter()),
3425 ScalarType::Int32 => Box::new((*INT32).iter()),
3426 ScalarType::Int64 => Box::new((*INT64).iter()),
3427 ScalarType::UInt16 => Box::new((*UINT16).iter()),
3428 ScalarType::UInt32 => Box::new((*UINT32).iter()),
3429 ScalarType::UInt64 => Box::new((*UINT64).iter()),
3430 ScalarType::Float32 => Box::new((*FLOAT32).iter()),
3431 ScalarType::Float64 => Box::new((*FLOAT64).iter()),
3432 ScalarType::Numeric { .. } => Box::new((*NUMERIC).iter()),
3433 ScalarType::Date => Box::new((*DATE).iter()),
3434 ScalarType::Time => Box::new((*TIME).iter()),
3435 ScalarType::Timestamp { .. } => Box::new((*TIMESTAMP).iter()),
3436 ScalarType::TimestampTz { .. } => Box::new((*TIMESTAMPTZ).iter()),
3437 ScalarType::Interval => Box::new((*INTERVAL).iter()),
3438 ScalarType::PgLegacyChar => Box::new((*PGLEGACYCHAR).iter()),
3439 ScalarType::PgLegacyName => Box::new((*PGLEGACYNAME).iter()),
3440 ScalarType::Bytes => Box::new((*BYTES).iter()),
3441 ScalarType::String => Box::new((*STRING).iter().chain((*CHAR).iter())),
3442 ScalarType::Char { .. } => Box::new((*CHAR).iter()),
3443 ScalarType::VarChar { .. } => Box::new((*STRING).iter().chain((*CHAR).iter())),
3444 ScalarType::Jsonb => Box::new((*JSONB).iter()),
3445 ScalarType::Uuid => Box::new((*UUID).iter()),
3446 ScalarType::Array(inner_type) => {
3447 if matches!(inner_type.as_ref(), ScalarType::Array(_)) {
3448 panic!("ScalarType::Array cannot have a nested Array");
3449 }
3450
3451 Box::new(
3452 (*ARRAY)
3453 .get(inner_type.as_ref())
3454 .unwrap_or(&*EMPTY_ARRAY)
3455 .iter(),
3456 )
3457 }
3458 ScalarType::List { .. } => Box::new((*LIST).iter()),
3459 ScalarType::Record { .. } => Box::new((*RECORD).iter()),
3460 ScalarType::Oid => Box::new((*OID).iter()),
3461 ScalarType::Map { .. } => Box::new((*MAP).iter()),
3462 ScalarType::RegProc => Box::new((*OID).iter()),
3463 ScalarType::RegType => Box::new((*OID).iter()),
3464 ScalarType::RegClass => Box::new((*OID).iter()),
3465 ScalarType::Int2Vector => Box::new((*INT2VECTOR).iter()),
3466 ScalarType::MzTimestamp => Box::new((*MZTIMESTAMP).iter()),
3467 ScalarType::Range { .. } => Box::new((*RANGE).iter()),
3468 ScalarType::MzAclItem { .. } => Box::new((*MZACLITEM).iter()),
3469 ScalarType::AclItem { .. } => Box::new((*ACLITEM).iter()),
3470 };
3471
3472 iter
3473 }
3474
3475 pub fn enumerate() -> &'static [Self] {
3478 &[
3481 ScalarType::Bool,
3482 ScalarType::Int16,
3483 ScalarType::Int32,
3484 ScalarType::Int64,
3485 ScalarType::UInt16,
3486 ScalarType::UInt32,
3487 ScalarType::UInt64,
3488 ScalarType::Float32,
3489 ScalarType::Float64,
3490 ScalarType::Numeric {
3491 max_scale: Some(NumericMaxScale(
3492 crate::adt::numeric::NUMERIC_DATUM_MAX_PRECISION,
3493 )),
3494 },
3495 ScalarType::Date,
3496 ScalarType::Time,
3497 ScalarType::Timestamp {
3498 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3499 },
3500 ScalarType::Timestamp {
3501 precision: Some(TimestampPrecision(0)),
3502 },
3503 ScalarType::Timestamp { precision: None },
3504 ScalarType::TimestampTz {
3505 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3506 },
3507 ScalarType::TimestampTz {
3508 precision: Some(TimestampPrecision(0)),
3509 },
3510 ScalarType::TimestampTz { precision: None },
3511 ScalarType::Interval,
3512 ScalarType::PgLegacyChar,
3513 ScalarType::Bytes,
3514 ScalarType::String,
3515 ScalarType::Char {
3516 length: Some(CharLength(1)),
3517 },
3518 ScalarType::VarChar { max_length: None },
3519 ScalarType::Jsonb,
3520 ScalarType::Uuid,
3521 ScalarType::Oid,
3522 ScalarType::RegProc,
3523 ScalarType::RegType,
3524 ScalarType::RegClass,
3525 ScalarType::Int2Vector,
3526 ScalarType::MzTimestamp,
3527 ScalarType::MzAclItem,
3528 ]
3549 }
3550
3551 pub fn array_of_self_elem_type(self) -> Result<ScalarType, ScalarType> {
3556 match self {
3557 t @ (ScalarType::AclItem
3558 | ScalarType::Bool
3559 | ScalarType::Int16
3560 | ScalarType::Int32
3561 | ScalarType::Int64
3562 | ScalarType::UInt16
3563 | ScalarType::UInt32
3564 | ScalarType::UInt64
3565 | ScalarType::Float32
3566 | ScalarType::Float64
3567 | ScalarType::Numeric { .. }
3568 | ScalarType::Date
3569 | ScalarType::Time
3570 | ScalarType::Timestamp { .. }
3571 | ScalarType::TimestampTz { .. }
3572 | ScalarType::Interval
3573 | ScalarType::PgLegacyChar
3574 | ScalarType::PgLegacyName
3575 | ScalarType::Bytes
3576 | ScalarType::String
3577 | ScalarType::VarChar { .. }
3578 | ScalarType::Jsonb
3579 | ScalarType::Uuid
3580 | ScalarType::Record { .. }
3581 | ScalarType::Oid
3582 | ScalarType::RegProc
3583 | ScalarType::RegType
3584 | ScalarType::RegClass
3585 | ScalarType::Int2Vector
3586 | ScalarType::MzTimestamp
3587 | ScalarType::Range { .. }
3588 | ScalarType::MzAclItem { .. }) => Ok(t),
3589
3590 ScalarType::Array(elem) => Ok(elem.array_of_self_elem_type()?),
3591
3592 t @ (ScalarType::Char { .. }
3594 | ScalarType::Map { .. }
3596 | ScalarType::List { .. }) => Err(t),
3597 }
3598 }
3599}
3600
3601impl Arbitrary for ScalarType {
3604 type Parameters = ();
3605 type Strategy = BoxedStrategy<ScalarType>;
3606
3607 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
3608 let leaf = Union::new(vec![
3610 Just(ScalarType::Bool).boxed(),
3611 Just(ScalarType::UInt16).boxed(),
3612 Just(ScalarType::UInt32).boxed(),
3613 Just(ScalarType::UInt64).boxed(),
3614 Just(ScalarType::Int16).boxed(),
3615 Just(ScalarType::Int32).boxed(),
3616 Just(ScalarType::Int64).boxed(),
3617 Just(ScalarType::Float32).boxed(),
3618 Just(ScalarType::Float64).boxed(),
3619 any::<Option<NumericMaxScale>>()
3620 .prop_map(|max_scale| ScalarType::Numeric { max_scale })
3621 .boxed(),
3622 Just(ScalarType::Date).boxed(),
3623 Just(ScalarType::Time).boxed(),
3624 any::<Option<TimestampPrecision>>()
3625 .prop_map(|precision| ScalarType::Timestamp { precision })
3626 .boxed(),
3627 any::<Option<TimestampPrecision>>()
3628 .prop_map(|precision| ScalarType::TimestampTz { precision })
3629 .boxed(),
3630 Just(ScalarType::MzTimestamp).boxed(),
3631 Just(ScalarType::Interval).boxed(),
3632 Just(ScalarType::PgLegacyChar).boxed(),
3633 Just(ScalarType::Bytes).boxed(),
3634 Just(ScalarType::String).boxed(),
3635 any::<Option<CharLength>>()
3636 .prop_map(|length| ScalarType::Char { length })
3637 .boxed(),
3638 any::<Option<VarCharMaxLength>>()
3639 .prop_map(|max_length| ScalarType::VarChar { max_length })
3640 .boxed(),
3641 Just(ScalarType::PgLegacyName).boxed(),
3642 Just(ScalarType::Jsonb).boxed(),
3643 Just(ScalarType::Uuid).boxed(),
3644 Just(ScalarType::AclItem).boxed(),
3645 Just(ScalarType::MzAclItem).boxed(),
3646 Just(ScalarType::Oid).boxed(),
3647 Just(ScalarType::RegProc).boxed(),
3648 Just(ScalarType::RegType).boxed(),
3649 Just(ScalarType::RegClass).boxed(),
3650 Just(ScalarType::Int2Vector).boxed(),
3651 ])
3652 .no_shrink()
3655 .boxed();
3656
3657 let range_leaf = Union::new(vec![
3659 Just(ScalarType::Int32).boxed(),
3660 Just(ScalarType::Int64).boxed(),
3661 Just(ScalarType::Date).boxed(),
3662 any::<Option<NumericMaxScale>>()
3663 .prop_map(|max_scale| ScalarType::Numeric { max_scale })
3664 .boxed(),
3665 any::<Option<TimestampPrecision>>()
3666 .prop_map(|precision| ScalarType::Timestamp { precision })
3667 .boxed(),
3668 any::<Option<TimestampPrecision>>()
3669 .prop_map(|precision| ScalarType::TimestampTz { precision })
3670 .boxed(),
3671 ]);
3672 let range = range_leaf
3673 .prop_map(|inner_type| ScalarType::Range {
3674 element_type: Box::new(inner_type),
3675 })
3676 .boxed();
3677
3678 let array = leaf
3680 .clone()
3681 .prop_map(|inner_type| ScalarType::Array(Box::new(inner_type)))
3682 .boxed();
3683
3684 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
3685
3686 leaf.prop_recursive(2, 3, 5, |inner| {
3687 Union::new(vec![
3688 (inner.clone(), any::<Option<CatalogItemId>>())
3690 .prop_map(|(x, id)| ScalarType::List {
3691 element_type: Box::new(x),
3692 custom_id: id,
3693 })
3694 .boxed(),
3695 (inner.clone(), any::<Option<CatalogItemId>>())
3697 .prop_map(|(x, id)| ScalarType::Map {
3698 value_type: Box::new(x),
3699 custom_id: id,
3700 })
3701 .boxed(),
3702 {
3704 let column_type_strat =
3707 (inner, any::<bool>()).prop_map(|(scalar_type, nullable)| ColumnType {
3708 scalar_type,
3709 nullable,
3710 });
3711
3712 let fields_strat =
3715 prop::collection::vec((any::<ColumnName>(), column_type_strat), 0..10);
3716
3717 (fields_strat, any::<Option<CatalogItemId>>())
3719 .prop_map(|(fields, custom_id)| ScalarType::Record {
3720 fields: fields.into(),
3721 custom_id,
3722 })
3723 .boxed()
3724 },
3725 ])
3726 })
3727 .boxed()
3728 }
3729}
3730
3731static EMPTY_ARRAY_ROW: LazyLock<Row> = LazyLock::new(|| {
3732 let mut row = Row::default();
3733 row.packer()
3734 .try_push_array(&[], iter::empty::<Datum>())
3735 .expect("array known to be valid");
3736 row
3737});
3738
3739static EMPTY_LIST_ROW: LazyLock<Row> = LazyLock::new(|| {
3740 let mut row = Row::default();
3741 row.packer().push_list(iter::empty::<Datum>());
3742 row
3743});
3744
3745static EMPTY_MAP_ROW: LazyLock<Row> = LazyLock::new(|| {
3746 let mut row = Row::default();
3747 row.packer().push_dict(iter::empty::<(_, Datum)>());
3748 row
3749});
3750
3751impl Datum<'_> {
3752 pub fn empty_array() -> Datum<'static> {
3753 EMPTY_ARRAY_ROW.unpack_first()
3754 }
3755
3756 pub fn empty_list() -> Datum<'static> {
3757 EMPTY_LIST_ROW.unpack_first()
3758 }
3759
3760 pub fn empty_map() -> Datum<'static> {
3761 EMPTY_MAP_ROW.unpack_first()
3762 }
3763}
3764
3765#[derive(Debug, PartialEq, Clone)]
3767pub enum PropDatum {
3768 Null,
3769 Bool(bool),
3770 Int16(i16),
3771 Int32(i32),
3772 Int64(i64),
3773 UInt8(u8),
3774 UInt16(u16),
3775 UInt32(u32),
3776 UInt64(u64),
3777 Float32(f32),
3778 Float64(f64),
3779
3780 Date(Date),
3781 Time(chrono::NaiveTime),
3782 Timestamp(CheckedTimestamp<chrono::NaiveDateTime>),
3783 TimestampTz(CheckedTimestamp<chrono::DateTime<chrono::Utc>>),
3784 MzTimestamp(u64),
3785
3786 Interval(Interval),
3787 Numeric(Numeric),
3788
3789 Bytes(Vec<u8>),
3790 String(String),
3791
3792 Array(PropArray),
3793 List(PropList),
3794 Map(PropDict),
3795 Record(PropDict),
3796 Range(PropRange),
3797
3798 AclItem(AclItem),
3799 MzAclItem(MzAclItem),
3800
3801 JsonNull,
3802 Uuid(Uuid),
3803 Dummy,
3804}
3805
3806impl std::cmp::Eq for PropDatum {}
3807
3808impl PartialOrd for PropDatum {
3809 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
3810 Some(self.cmp(other))
3811 }
3812}
3813
3814impl Ord for PropDatum {
3815 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
3816 Datum::from(self).cmp(&Datum::from(other))
3817 }
3818}
3819
3820pub fn arb_datum() -> BoxedStrategy<PropDatum> {
3822 let leaf = Union::new(vec![
3823 Just(PropDatum::Null).boxed(),
3824 any::<bool>().prop_map(PropDatum::Bool).boxed(),
3825 any::<i16>().prop_map(PropDatum::Int16).boxed(),
3826 any::<i32>().prop_map(PropDatum::Int32).boxed(),
3827 any::<i64>().prop_map(PropDatum::Int64).boxed(),
3828 any::<u16>().prop_map(PropDatum::UInt16).boxed(),
3829 any::<u32>().prop_map(PropDatum::UInt32).boxed(),
3830 any::<u64>().prop_map(PropDatum::UInt64).boxed(),
3831 any::<f32>().prop_map(PropDatum::Float32).boxed(),
3832 any::<f64>().prop_map(PropDatum::Float64).boxed(),
3833 arb_date().prop_map(PropDatum::Date).boxed(),
3834 add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
3835 .prop_map(PropDatum::Time)
3836 .boxed(),
3837 arb_naive_date_time()
3838 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
3839 .boxed(),
3840 arb_utc_date_time()
3841 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
3842 .boxed(),
3843 any::<Interval>().prop_map(PropDatum::Interval).boxed(),
3844 arb_numeric().prop_map(PropDatum::Numeric).boxed(),
3845 prop::collection::vec(any::<u8>(), 1024)
3846 .prop_map(PropDatum::Bytes)
3847 .boxed(),
3848 ".*".prop_map(PropDatum::String).boxed(),
3849 Just(PropDatum::JsonNull).boxed(),
3850 any::<[u8; 16]>()
3851 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
3852 .boxed(),
3853 arb_range(arb_range_data())
3854 .prop_map(PropDatum::Range)
3855 .boxed(),
3856 Just(PropDatum::Dummy).boxed(),
3857 ]);
3858 leaf.prop_recursive(3, 8, 16, |inner| {
3859 Union::new(vec![
3860 arb_array(inner.clone()).prop_map(PropDatum::Array).boxed(),
3861 arb_list(inner.clone()).prop_map(PropDatum::List).boxed(),
3862 arb_dict(inner).prop_map(PropDatum::Map).boxed(),
3863 ])
3864 })
3865 .boxed()
3866}
3867
3868pub fn arb_datum_for_column(column_type: ColumnType) -> impl Strategy<Value = PropDatum> {
3870 let strat = arb_datum_for_scalar(column_type.scalar_type);
3871
3872 if column_type.nullable {
3873 Union::new_weighted(vec![(1, Just(PropDatum::Null).boxed()), (5, strat.boxed())]).boxed()
3874 } else {
3875 strat.boxed()
3876 }
3877}
3878
3879pub fn arb_datum_for_scalar(scalar_type: ScalarType) -> impl Strategy<Value = PropDatum> {
3881 match scalar_type {
3882 ScalarType::Bool => any::<bool>().prop_map(PropDatum::Bool).boxed(),
3883 ScalarType::Int16 => any::<i16>().prop_map(PropDatum::Int16).boxed(),
3884 ScalarType::Int32 => any::<i32>().prop_map(PropDatum::Int32).boxed(),
3885 ScalarType::Int64 => any::<i64>().prop_map(PropDatum::Int64).boxed(),
3886 ScalarType::PgLegacyChar => any::<u8>().prop_map(PropDatum::UInt8).boxed(),
3887 ScalarType::UInt16 => any::<u16>().prop_map(PropDatum::UInt16).boxed(),
3888 ScalarType::UInt32
3889 | ScalarType::Oid
3890 | ScalarType::RegClass
3891 | ScalarType::RegProc
3892 | ScalarType::RegType => any::<u32>().prop_map(PropDatum::UInt32).boxed(),
3893 ScalarType::UInt64 => any::<u64>().prop_map(PropDatum::UInt64).boxed(),
3894 ScalarType::Float32 => any::<f32>().prop_map(PropDatum::Float32).boxed(),
3895 ScalarType::Float64 => any::<f64>().prop_map(PropDatum::Float64).boxed(),
3896 ScalarType::Numeric { .. } => arb_numeric().prop_map(PropDatum::Numeric).boxed(),
3897 ScalarType::String
3898 | ScalarType::PgLegacyName
3899 | ScalarType::Char { length: None }
3900 | ScalarType::VarChar { max_length: None } => ".*".prop_map(PropDatum::String).boxed(),
3901 ScalarType::Char {
3902 length: Some(length),
3903 } => {
3904 let max_len = usize::cast_from(length.into_u32()).max(1);
3905 prop::collection::vec(any::<char>(), 0..max_len)
3906 .prop_map(move |chars| {
3907 let num_blanks = max_len - chars.len();
3909 let s = chars
3910 .into_iter()
3911 .chain(std::iter::repeat(' ').take(num_blanks))
3912 .collect();
3913 PropDatum::String(s)
3914 })
3915 .boxed()
3916 }
3917 ScalarType::VarChar {
3918 max_length: Some(length),
3919 } => {
3920 let max_len = usize::cast_from(length.into_u32()).max(1);
3921 prop::collection::vec(any::<char>(), 0..max_len)
3922 .prop_map(|chars| PropDatum::String(chars.into_iter().collect()))
3923 .boxed()
3924 }
3925 ScalarType::Bytes => prop::collection::vec(any::<u8>(), 300)
3926 .prop_map(PropDatum::Bytes)
3927 .boxed(),
3928 ScalarType::Date => arb_date().prop_map(PropDatum::Date).boxed(),
3929 ScalarType::Time => add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
3930 .prop_map(PropDatum::Time)
3931 .boxed(),
3932 ScalarType::Timestamp { .. } => arb_naive_date_time()
3933 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
3934 .boxed(),
3935 ScalarType::TimestampTz { .. } => arb_utc_date_time()
3936 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
3937 .boxed(),
3938 ScalarType::MzTimestamp => any::<u64>().prop_map(PropDatum::MzTimestamp).boxed(),
3939 ScalarType::Interval => any::<Interval>().prop_map(PropDatum::Interval).boxed(),
3940 ScalarType::Uuid => any::<[u8; 16]>()
3941 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
3942 .boxed(),
3943 ScalarType::AclItem => any::<AclItem>().prop_map(PropDatum::AclItem).boxed(),
3944 ScalarType::MzAclItem => any::<MzAclItem>().prop_map(PropDatum::MzAclItem).boxed(),
3945 ScalarType::Range { element_type } => {
3946 let data_strat = (
3947 arb_datum_for_scalar(*element_type.clone()),
3948 arb_datum_for_scalar(*element_type),
3949 );
3950 arb_range(data_strat).prop_map(PropDatum::Range).boxed()
3951 }
3952 ScalarType::List { element_type, .. } => arb_list(arb_datum_for_scalar(*element_type))
3953 .prop_map(PropDatum::List)
3954 .boxed(),
3955 ScalarType::Array(element_type) => arb_array(arb_datum_for_scalar(*element_type))
3956 .prop_map(PropDatum::Array)
3957 .boxed(),
3958 ScalarType::Int2Vector => arb_array(any::<i16>().prop_map(PropDatum::Int16).boxed())
3959 .prop_map(PropDatum::Array)
3960 .boxed(),
3961 ScalarType::Map { value_type, .. } => arb_dict(arb_datum_for_scalar(*value_type))
3962 .prop_map(PropDatum::Map)
3963 .boxed(),
3964 ScalarType::Record { fields, .. } => {
3965 let field_strats = fields.iter().map(|(name, ty)| {
3966 (
3967 name.to_string(),
3968 arb_datum_for_scalar(ty.scalar_type.clone()),
3969 )
3970 });
3971 arb_record(field_strats).prop_map(PropDatum::Record).boxed()
3972 }
3973 ScalarType::Jsonb => {
3974 let int_value = any::<i128>()
3975 .prop_map(|v| Numeric::try_from(v).unwrap())
3976 .boxed();
3977 let float_value = (1e-39f64..1e39)
3979 .prop_map(|v| Numeric::try_from(v).unwrap())
3980 .boxed();
3981 let json_number = Union::new(vec![int_value, float_value]);
3984
3985 let json_leaf = Union::new(vec![
3986 any::<()>().prop_map(|_| PropDatum::JsonNull).boxed(),
3987 any::<bool>().prop_map(PropDatum::Bool).boxed(),
3988 json_number.prop_map(PropDatum::Numeric).boxed(),
3989 ".*".prop_map(PropDatum::String).boxed(),
3990 ]);
3991 json_leaf
3992 .prop_recursive(4, 32, 8, |element| {
3993 Union::new(vec![
3994 prop::collection::vec(element.clone(), 0..16)
3995 .prop_map(|elements| {
3996 let datums: Vec<_> = elements.iter().map(|pd| pd.into()).collect();
3997 let mut row = Row::default();
3998 row.packer().push_list(datums.iter());
3999 PropDatum::List(PropList(row, elements))
4000 })
4001 .boxed(),
4002 prop::collection::hash_map(".*", element, 0..16)
4003 .prop_map(|elements| {
4004 let mut elements: Vec<_> = elements.into_iter().collect();
4005 elements.sort_by_key(|(k, _)| k.clone());
4006 elements.dedup_by_key(|(k, _)| k.clone());
4007 let mut row = Row::default();
4008 let entry_iter =
4009 elements.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4010 row.packer().push_dict(entry_iter);
4011 PropDatum::Map(PropDict(row, elements))
4012 })
4013 .boxed(),
4014 ])
4015 })
4016 .boxed()
4017 }
4018 }
4019}
4020
4021pub fn arb_naive_date_time() -> impl Strategy<Value = NaiveDateTime> {
4023 add_arb_duration(chrono::DateTime::from_timestamp(0, 0).unwrap().naive_utc())
4024}
4025
4026pub fn arb_utc_date_time() -> impl Strategy<Value = DateTime<Utc>> {
4028 add_arb_duration(chrono::Utc.timestamp_opt(0, 0).unwrap())
4029}
4030
4031fn arb_array_dimension() -> BoxedStrategy<ArrayDimension> {
4032 (1..4_usize)
4033 .prop_map(|length| ArrayDimension {
4034 lower_bound: 1,
4035 length,
4036 })
4037 .boxed()
4038}
4039
4040#[derive(Debug, PartialEq, Clone)]
4041pub struct PropArray(Row, Vec<PropDatum>);
4042
4043fn arb_array(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropArray> {
4044 let element_strategy = Union::new_weighted(vec![
4046 (20, element_strategy),
4047 (1, Just(PropDatum::Null).boxed()),
4048 ]);
4049
4050 prop::collection::vec(
4051 arb_array_dimension(),
4052 1..usize::from(crate::adt::array::MAX_ARRAY_DIMENSIONS),
4053 )
4054 .prop_flat_map(move |dimensions| {
4055 let n_elts: usize = dimensions.iter().map(|d| d.length).product();
4056 (
4057 Just(dimensions),
4058 prop::collection::vec(element_strategy.clone(), n_elts),
4059 )
4060 })
4061 .prop_map(|(dimensions, elements)| {
4062 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4063 let mut row = Row::default();
4064 row.packer()
4065 .try_push_array(&dimensions, element_datums)
4066 .unwrap();
4067 PropArray(row, elements)
4068 })
4069 .boxed()
4070}
4071
4072#[derive(Debug, PartialEq, Clone)]
4073pub struct PropList(Row, Vec<PropDatum>);
4074
4075fn arb_list(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropList> {
4076 let element_strategy = Union::new_weighted(vec![
4078 (20, element_strategy),
4079 (1, Just(PropDatum::Null).boxed()),
4080 ]);
4081
4082 prop::collection::vec(element_strategy, 1..50)
4083 .prop_map(|elements| {
4084 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4085 let mut row = Row::default();
4086 row.packer().push_list(element_datums.iter());
4087 PropList(row, elements)
4088 })
4089 .boxed()
4090}
4091
4092#[derive(Debug, PartialEq, Clone)]
4093pub struct PropRange(
4094 Row,
4095 Option<(
4096 (Option<Box<PropDatum>>, bool),
4097 (Option<Box<PropDatum>>, bool),
4098 )>,
4099);
4100
4101pub fn arb_range_type() -> Union<BoxedStrategy<ScalarType>> {
4102 Union::new(vec![
4103 Just(ScalarType::Int32).boxed(),
4104 Just(ScalarType::Int64).boxed(),
4105 Just(ScalarType::Date).boxed(),
4106 ])
4107}
4108
4109fn arb_range_data() -> Union<BoxedStrategy<(PropDatum, PropDatum)>> {
4110 Union::new(vec![
4111 (
4112 any::<i32>().prop_map(PropDatum::Int32),
4113 any::<i32>().prop_map(PropDatum::Int32),
4114 )
4115 .boxed(),
4116 (
4117 any::<i64>().prop_map(PropDatum::Int64),
4118 any::<i64>().prop_map(PropDatum::Int64),
4119 )
4120 .boxed(),
4121 (
4122 arb_date().prop_map(PropDatum::Date),
4123 arb_date().prop_map(PropDatum::Date),
4124 )
4125 .boxed(),
4126 ])
4127}
4128
4129fn arb_range(
4130 data: impl Strategy<Value = (PropDatum, PropDatum)> + 'static,
4131) -> BoxedStrategy<PropRange> {
4132 (
4133 any::<u16>(),
4134 any::<bool>(),
4135 any::<bool>(),
4136 any::<bool>(),
4137 any::<bool>(),
4138 data,
4139 )
4140 .prop_map(
4141 |(split, lower_inf, lower_inc, upper_inf, upper_inc, (a, b))| {
4142 let mut row = Row::default();
4143 let mut packer = row.packer();
4144 let r = if split % 32 == 0 {
4145 packer
4146 .push_range(Range::new(None))
4147 .expect("pushing empty ranges never fails");
4148 None
4149 } else {
4150 let b_is_lower = Datum::from(&b) < Datum::from(&a);
4151
4152 let (lower, upper) = if b_is_lower { (b, a) } else { (a, b) };
4153 let mut range = Range::new(Some((
4154 RangeLowerBound {
4155 inclusive: lower_inc,
4156 bound: if lower_inf {
4157 None
4158 } else {
4159 Some(Datum::from(&lower))
4160 },
4161 },
4162 RangeUpperBound {
4163 inclusive: upper_inc,
4164 bound: if upper_inf {
4165 None
4166 } else {
4167 Some(Datum::from(&upper))
4168 },
4169 },
4170 )));
4171
4172 range.canonicalize().unwrap();
4173
4174 let (empty, lower_inf, lower_inc, upper_inf, upper_inc) = match range.inner {
4177 None => (true, false, false, false, false),
4178 Some(inner) => (
4179 false
4180 || match inner.lower.bound {
4181 Some(b) => b != Datum::from(&lower),
4182 None => !lower_inf,
4183 }
4184 || match inner.upper.bound {
4185 Some(b) => b != Datum::from(&upper),
4186 None => !upper_inf,
4187 },
4188 inner.lower.bound.is_none(),
4189 inner.lower.inclusive,
4190 inner.upper.bound.is_none(),
4191 inner.upper.inclusive,
4192 ),
4193 };
4194
4195 if empty {
4196 packer.push_range(Range { inner: None }).unwrap();
4197 None
4198 } else {
4199 packer.push_range(range).unwrap();
4200 Some((
4201 (
4202 if lower_inf {
4203 None
4204 } else {
4205 Some(Box::new(lower))
4206 },
4207 lower_inc,
4208 ),
4209 (
4210 if upper_inf {
4211 None
4212 } else {
4213 Some(Box::new(upper))
4214 },
4215 upper_inc,
4216 ),
4217 ))
4218 }
4219 };
4220
4221 PropRange(row, r)
4222 },
4223 )
4224 .boxed()
4225}
4226
4227#[derive(Debug, PartialEq, Clone)]
4228pub struct PropDict(Row, Vec<(String, PropDatum)>);
4229
4230fn arb_dict(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropDict> {
4231 let element_strategy = Union::new_weighted(vec![
4233 (20, element_strategy),
4234 (1, Just(PropDatum::Null).boxed()),
4235 ]);
4236
4237 prop::collection::vec((".*", element_strategy), 1..50)
4238 .prop_map(|mut entries| {
4239 entries.sort_by_key(|(k, _)| k.clone());
4240 entries.dedup_by_key(|(k, _)| k.clone());
4241 let mut row = Row::default();
4242 let entry_iter = entries.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4243 row.packer().push_dict(entry_iter);
4244 PropDict(row, entries)
4245 })
4246 .boxed()
4247}
4248
4249fn arb_record(
4250 fields: impl Iterator<Item = (String, BoxedStrategy<PropDatum>)>,
4251) -> BoxedStrategy<PropDict> {
4252 let (names, strategies): (Vec<_>, Vec<_>) = fields.unzip();
4253
4254 strategies
4255 .prop_map(move |x| {
4256 let mut row = Row::default();
4257 row.packer().push_list(x.iter().map(Datum::from));
4258 let entries: Vec<_> = names.clone().into_iter().zip(x).collect();
4259 PropDict(row, entries)
4260 })
4261 .boxed()
4262}
4263
4264fn arb_date() -> BoxedStrategy<Date> {
4265 (Date::LOW_DAYS..Date::HIGH_DAYS)
4266 .prop_map(move |days| Date::from_pg_epoch(days).unwrap())
4267 .boxed()
4268}
4269
4270pub fn add_arb_duration<T: 'static + Copy + Add<chrono::Duration> + std::fmt::Debug>(
4271 to: T,
4272) -> BoxedStrategy<T::Output>
4273where
4274 T::Output: std::fmt::Debug,
4275{
4276 let lower = LOW_DATE
4277 .and_hms_opt(0, 0, 0)
4278 .unwrap()
4279 .and_utc()
4280 .timestamp_micros();
4281 let upper = HIGH_DATE
4282 .and_hms_opt(0, 0, 0)
4283 .unwrap()
4284 .and_utc()
4285 .timestamp_micros();
4286 (lower..upper)
4287 .prop_map(move |v| to + chrono::Duration::microseconds(v))
4288 .boxed()
4289}
4290
4291pub(crate) fn arb_numeric() -> BoxedStrategy<Numeric> {
4292 let int_value = any::<i128>()
4293 .prop_map(|v| Numeric::try_from(v).unwrap())
4294 .boxed();
4295 let float_value = (-1e39f64..1e39)
4296 .prop_map(|v| Numeric::try_from(v).unwrap())
4297 .boxed();
4298
4299 let tiny_floats = ((-10.0..10.0), (1u32..10))
4302 .prop_map(|(v, num_digits)| {
4303 let num_digits: f64 = 10u32.pow(num_digits).try_into().unwrap();
4305 let trunc = f64::trunc(v * num_digits) / num_digits;
4306 Numeric::try_from(trunc).unwrap()
4307 })
4308 .boxed();
4309 let small_ints = (-1_000_000..1_000_000)
4310 .prop_map(|v| Numeric::try_from(v).unwrap())
4311 .boxed();
4312 let small_floats = (-1_000_000.0..1_000_000.0)
4313 .prop_map(|v| Numeric::try_from(v).unwrap())
4314 .boxed();
4315
4316 Union::new_weighted(vec![
4317 (20, tiny_floats),
4318 (20, small_ints),
4319 (20, small_floats),
4320 (10, int_value),
4321 (10, float_value),
4322 (1, Just(Numeric::infinity()).boxed()),
4323 (1, Just(-Numeric::infinity()).boxed()),
4324 (1, Just(Numeric::nan()).boxed()),
4325 (1, Just(Numeric::zero()).boxed()),
4326 ])
4327 .boxed()
4328}
4329
4330impl<'a> From<&'a PropDatum> for Datum<'a> {
4331 #[inline]
4332 fn from(pd: &'a PropDatum) -> Self {
4333 use PropDatum::*;
4334 match pd {
4335 Null => Datum::Null,
4336 Bool(b) => Datum::from(*b),
4337 Int16(i) => Datum::from(*i),
4338 Int32(i) => Datum::from(*i),
4339 Int64(i) => Datum::from(*i),
4340 UInt8(u) => Datum::from(*u),
4341 UInt16(u) => Datum::from(*u),
4342 UInt32(u) => Datum::from(*u),
4343 UInt64(u) => Datum::from(*u),
4344 Float32(f) => Datum::from(*f),
4345 Float64(f) => Datum::from(*f),
4346 Date(d) => Datum::from(*d),
4347 Time(t) => Datum::from(*t),
4348 Timestamp(t) => Datum::from(*t),
4349 TimestampTz(t) => Datum::from(*t),
4350 MzTimestamp(t) => Datum::MzTimestamp((*t).into()),
4351 Interval(i) => Datum::from(*i),
4352 Numeric(s) => Datum::from(*s),
4353 Bytes(b) => Datum::from(&b[..]),
4354 String(s) => Datum::from(s.as_str()),
4355 Array(PropArray(row, _)) => {
4356 let array = row.unpack_first().unwrap_array();
4357 Datum::Array(array)
4358 }
4359 List(PropList(row, _)) => {
4360 let list = row.unpack_first().unwrap_list();
4361 Datum::List(list)
4362 }
4363 Map(PropDict(row, _)) => {
4364 let map = row.unpack_first().unwrap_map();
4365 Datum::Map(map)
4366 }
4367 Record(PropDict(row, _)) => {
4368 let list = row.unpack_first().unwrap_list();
4369 Datum::List(list)
4370 }
4371 Range(PropRange(row, _)) => {
4372 let d = row.unpack_first();
4373 assert!(matches!(d, Datum::Range(_)));
4374 d
4375 }
4376 AclItem(i) => Datum::AclItem(*i),
4377 MzAclItem(i) => Datum::MzAclItem(*i),
4378 JsonNull => Datum::JsonNull,
4379 Uuid(u) => Datum::from(*u),
4380 Dummy => Datum::Dummy,
4381 }
4382 }
4383}
4384
4385#[mz_ore::test]
4386fn verify_base_eq_record_nullability() {
4387 let s1 = ScalarType::Record {
4388 fields: [(
4389 "c".into(),
4390 ColumnType {
4391 scalar_type: ScalarType::Bool,
4392 nullable: true,
4393 },
4394 )]
4395 .into(),
4396 custom_id: None,
4397 };
4398 let s2 = ScalarType::Record {
4399 fields: [(
4400 "c".into(),
4401 ColumnType {
4402 scalar_type: ScalarType::Bool,
4403 nullable: false,
4404 },
4405 )]
4406 .into(),
4407 custom_id: None,
4408 };
4409 let s3 = ScalarType::Record {
4410 fields: [].into(),
4411 custom_id: None,
4412 };
4413 assert!(s1.base_eq(&s2));
4414 assert!(!s1.base_eq(&s3));
4415}
4416
4417#[cfg(test)]
4418mod tests {
4419 use mz_ore::assert_ok;
4420 use mz_proto::protobuf_roundtrip;
4421
4422 use super::*;
4423
4424 proptest! {
4425 #[mz_ore::test]
4426 #[cfg_attr(miri, ignore)] fn scalar_type_protobuf_roundtrip(expect in any::<ScalarType>() ) {
4428 let actual = protobuf_roundtrip::<_, ProtoScalarType>(&expect);
4429 assert_ok!(actual);
4430 assert_eq!(actual.unwrap(), expect);
4431 }
4432 }
4433
4434 proptest! {
4435 #[mz_ore::test]
4436 #[cfg_attr(miri, ignore)] fn array_packing_unpacks_correctly(array in arb_array(arb_datum())) {
4438 let PropArray(row, elts) = array;
4439 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
4440 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_array().elements().iter().collect();
4441 assert_eq!(unpacked_datums, datums);
4442 }
4443
4444 #[mz_ore::test]
4445 #[cfg_attr(miri, ignore)] fn list_packing_unpacks_correctly(array in arb_list(arb_datum())) {
4447 let PropList(row, elts) = array;
4448 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
4449 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_list().iter().collect();
4450 assert_eq!(unpacked_datums, datums);
4451 }
4452
4453 #[mz_ore::test]
4454 #[cfg_attr(miri, ignore)] fn dict_packing_unpacks_correctly(array in arb_dict(arb_datum())) {
4456 let PropDict(row, elts) = array;
4457 let datums: Vec<(&str, Datum<'_>)> = elts.iter().map(|(k, e)| (k.as_str(), e.into())).collect();
4458 let unpacked_datums: Vec<(&str, Datum<'_>)> = row.unpack_first().unwrap_map().iter().collect();
4459 assert_eq!(unpacked_datums, datums);
4460 }
4461
4462 #[mz_ore::test]
4463 #[cfg_attr(miri, ignore)] fn row_packing_roundtrips_single_valued(prop_datums in prop::collection::vec(arb_datum(), 1..100)) {
4465 let datums: Vec<Datum<'_>> = prop_datums.iter().map(|pd| pd.into()).collect();
4466 let row = Row::pack(&datums);
4467 let unpacked = row.unpack();
4468 assert_eq!(datums, unpacked);
4469 }
4470
4471 #[mz_ore::test]
4472 #[cfg_attr(miri, ignore)] fn range_packing_unpacks_correctly(range in arb_range(arb_range_data())) {
4474 let PropRange(row, prop_range) = range;
4475 let row = row.unpack_first();
4476 let d = row.unwrap_range();
4477
4478 let (((prop_lower, prop_lower_inc), (prop_upper, prop_upper_inc)), crate::adt::range::RangeInner {lower, upper}) = match (prop_range, d.inner) {
4479 (Some(prop_values), Some(inner_range)) => (prop_values, inner_range),
4480 (None, None) => return Ok(()),
4481 _ => panic!("inequivalent row packing"),
4482 };
4483
4484 for (prop_bound, prop_bound_inc, inner_bound, inner_bound_inc) in [
4485 (prop_lower, prop_lower_inc, lower.bound, lower.inclusive),
4486 (prop_upper, prop_upper_inc, upper.bound, upper.inclusive),
4487 ] {
4488 assert_eq!(prop_bound_inc, inner_bound_inc);
4489 match (prop_bound, inner_bound) {
4490 (None, None) => continue,
4491 (Some(p), Some(b)) => {
4492 assert_eq!(Datum::from(&*p), b);
4493 }
4494 _ => panic!("inequivalent row packing"),
4495 }
4496 }
4497 }
4498 }
4499}