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