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