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