1use std::collections::BTreeMap;
11use std::fmt::{self, Debug};
12use std::hash::Hash;
13use std::iter;
14use std::ops::Add;
15use std::sync::LazyLock;
16
17use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
18use dec::OrderedDecimal;
19use enum_kinds::EnumKind;
20use itertools::Itertools;
21use mz_lowertest::MzReflect;
22use mz_ore::Overflowing;
23use mz_ore::cast::CastFrom;
24use mz_ore::str::StrExt;
25use mz_proto::{IntoRustIfSome, ProtoType, RustType, TryFromProtoError};
26use ordered_float::OrderedFloat;
27use proptest::prelude::*;
28use proptest::strategy::Union;
29use serde::{Deserialize, Serialize};
30use uuid::Uuid;
31
32use crate::adt::array::{Array, ArrayDimension};
33use crate::adt::char::{Char, CharLength};
34use crate::adt::date::Date;
35use crate::adt::interval::Interval;
36use crate::adt::jsonb::{Jsonb, JsonbRef};
37use crate::adt::mz_acl_item::{AclItem, AclMode, MzAclItem};
38use crate::adt::numeric::{Numeric, NumericMaxScale};
39use crate::adt::pg_legacy_name::PgLegacyName;
40use crate::adt::range::{Range, RangeLowerBound, RangeUpperBound};
41use crate::adt::system::{Oid, PgLegacyChar, RegClass, RegProc, RegType};
42use crate::adt::timestamp::{
43 CheckedTimestamp, HIGH_DATE, LOW_DATE, TimestampError, TimestampPrecision,
44};
45use crate::adt::varchar::{VarChar, VarCharMaxLength};
46use crate::relation::ReprColumnType;
47pub use crate::relation_and_scalar::ProtoScalarType;
48pub use crate::relation_and_scalar::proto_scalar_type::ProtoRecordField;
49use crate::role_id::RoleId;
50use crate::row::DatumNested;
51use crate::{CatalogItemId, ColumnName, DatumList, DatumMap, Row, RowArena, SqlColumnType};
52
53#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, EnumKind)]
73#[enum_kind(DatumKind)]
74pub enum Datum<'a> {
75 False,
77 True,
79 Int16(i16),
81 Int32(i32),
83 Int64(i64),
85 UInt8(u8),
87 UInt16(u16),
89 UInt32(u32),
91 UInt64(u64),
93 Float32(OrderedFloat<f32>),
95 Float64(OrderedFloat<f64>),
97 Date(Date),
99 Time(NaiveTime),
101 Timestamp(CheckedTimestamp<NaiveDateTime>),
104 TimestampTz(CheckedTimestamp<DateTime<Utc>>),
106 Interval(Interval),
108 Bytes(&'a [u8]),
110 String(&'a str),
112 Array(Array<'a>),
115 List(DatumList<'a>),
119 Map(DatumMap<'a>),
121 Numeric(OrderedDecimal<Numeric>),
124 JsonNull,
129 Uuid(Uuid),
131 MzTimestamp(crate::Timestamp),
132 Range(Range<DatumNested<'a>>),
134 MzAclItem(MzAclItem),
137 AclItem(AclItem),
140 Dummy,
157 Null,
165 }
171
172impl Debug for Datum<'_> {
173 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174 use mz_ore::str::*;
175 match self {
176 Datum::False => write!(f, "False"),
177 Datum::True => write!(f, "True"),
178 Datum::Int16(x) => f.debug_tuple("Int16").field(&redact(x)).finish(),
179 Datum::Int32(x) => f.debug_tuple("Int32").field(&redact(x)).finish(),
180 Datum::Int64(x) => f.debug_tuple("Int64").field(&redact(x)).finish(),
181 Datum::UInt8(x) => f.debug_tuple("UInt8").field(&redact(x)).finish(),
182 Datum::UInt16(x) => f.debug_tuple("UInt16").field(&redact(x)).finish(),
183 Datum::UInt32(x) => f.debug_tuple("UInt32").field(&redact(x)).finish(),
184 Datum::UInt64(x) => f.debug_tuple("UInt64").field(&redact(x)).finish(),
185 Datum::Float32(x) => f.debug_tuple("Float32").field(&redact(x)).finish(),
186 Datum::Float64(x) => f.debug_tuple("Float64").field(&redact(x)).finish(),
187 Datum::Date(x) => f.debug_tuple("Date").field(&redact(x)).finish(),
188 Datum::Time(x) => f.debug_tuple("Time").field(&redact(x)).finish(),
189 Datum::Timestamp(x) => f
190 .debug_tuple("Timestamp")
191 .field(&redact(x.to_naive()))
192 .finish(),
193 Datum::TimestampTz(x) => f
194 .debug_tuple("TimestampTz")
195 .field(&redact(<DateTime<Utc>>::from(*x)))
196 .finish(),
197 Datum::Interval(x) => f.debug_tuple("Interval").field(&redact(x)).finish(),
198 Datum::Bytes(x) => f.debug_tuple("Bytes").field(&redact(x)).finish(),
199 Datum::String(x) => f.debug_tuple("String").field(&redact(x)).finish(),
200 Datum::Array(x) => f.debug_tuple("Array").field(x).finish(),
201 Datum::List(x) => f.debug_tuple("List").field(x).finish(),
202 Datum::Map(x) => f.debug_tuple("Map").field(x).finish(),
203 Datum::Numeric(x) => f.debug_tuple("Numeric").field(&redact(&x.0)).finish(),
204 Datum::JsonNull => f.debug_tuple("JsonNull").finish(),
205 Datum::Uuid(x) => f.debug_tuple("Uuid").field(&redact(x)).finish(),
206 Datum::MzTimestamp(x) => f.debug_tuple("MzTimestamp").field(&redact(x)).finish(),
207 Datum::Range(x) => f.debug_tuple("Range").field(&redact(x)).finish(),
208 Datum::MzAclItem(x) => f.debug_tuple("MzAclItem").field(&redact(x)).finish(),
209 Datum::AclItem(x) => f.debug_tuple("AclItem").field(&redact(x)).finish(),
210 Datum::Dummy => f.debug_tuple("Dummy").finish(),
211 Datum::Null => f.debug_tuple("Null").finish(),
212 }
213 }
214}
215
216impl TryFrom<Datum<'_>> for bool {
217 type Error = ();
218
219 #[inline]
220 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
221 match from {
222 Datum::False => Ok(false),
223 Datum::True => Ok(true),
224 _ => Err(()),
225 }
226 }
227}
228
229impl TryFrom<Datum<'_>> for Option<bool> {
230 type Error = ();
231
232 #[inline]
233 fn try_from(datum: Datum<'_>) -> Result<Self, Self::Error> {
234 match datum {
235 Datum::Null => Ok(None),
236 Datum::False => Ok(Some(false)),
237 Datum::True => Ok(Some(true)),
238 _ => Err(()),
239 }
240 }
241}
242
243impl TryFrom<Datum<'_>> for f32 {
244 type Error = ();
245
246 #[inline]
247 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
248 match from {
249 Datum::Float32(f) => Ok(*f),
250 _ => Err(()),
251 }
252 }
253}
254
255impl TryFrom<Datum<'_>> for Option<f32> {
256 type Error = ();
257
258 #[inline]
259 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
260 match from {
261 Datum::Null => Ok(None),
262 Datum::Float32(f) => Ok(Some(*f)),
263 _ => Err(()),
264 }
265 }
266}
267
268impl TryFrom<Datum<'_>> for OrderedFloat<f32> {
269 type Error = ();
270
271 #[inline]
272 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
273 match from {
274 Datum::Float32(f) => Ok(f),
275 _ => Err(()),
276 }
277 }
278}
279
280impl TryFrom<Datum<'_>> for Option<OrderedFloat<f32>> {
281 type Error = ();
282
283 #[inline]
284 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
285 match from {
286 Datum::Null => Ok(None),
287 Datum::Float32(f) => Ok(Some(f)),
288 _ => Err(()),
289 }
290 }
291}
292
293impl TryFrom<Datum<'_>> for f64 {
294 type Error = ();
295
296 #[inline]
297 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
298 match from {
299 Datum::Float64(f) => Ok(*f),
300 _ => Err(()),
301 }
302 }
303}
304
305impl TryFrom<Datum<'_>> for Option<f64> {
306 type Error = ();
307
308 #[inline]
309 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
310 match from {
311 Datum::Null => Ok(None),
312 Datum::Float64(f) => Ok(Some(*f)),
313 _ => Err(()),
314 }
315 }
316}
317
318impl TryFrom<Datum<'_>> for OrderedFloat<f64> {
319 type Error = ();
320
321 #[inline]
322 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
323 match from {
324 Datum::Float64(f) => Ok(f),
325 _ => Err(()),
326 }
327 }
328}
329
330impl TryFrom<Datum<'_>> for Option<OrderedFloat<f64>> {
331 type Error = ();
332
333 #[inline]
334 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
335 match from {
336 Datum::Null => Ok(None),
337 Datum::Float64(f) => Ok(Some(f)),
338 _ => Err(()),
339 }
340 }
341}
342
343impl TryFrom<Datum<'_>> for i16 {
344 type Error = ();
345
346 #[inline]
347 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
348 match from {
349 Datum::Int16(i) => Ok(i),
350 _ => Err(()),
351 }
352 }
353}
354
355impl TryFrom<Datum<'_>> for Option<i16> {
356 type Error = ();
357
358 #[inline]
359 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
360 match from {
361 Datum::Null => Ok(None),
362 Datum::Int16(i) => Ok(Some(i)),
363 _ => Err(()),
364 }
365 }
366}
367
368impl TryFrom<Datum<'_>> for i32 {
369 type Error = ();
370
371 #[inline]
372 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
373 match from {
374 Datum::Int32(i) => Ok(i),
375 _ => Err(()),
376 }
377 }
378}
379
380impl TryFrom<Datum<'_>> for Option<i32> {
381 type Error = ();
382
383 #[inline]
384 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
385 match from {
386 Datum::Null => Ok(None),
387 Datum::Int32(i) => Ok(Some(i)),
388 _ => Err(()),
389 }
390 }
391}
392
393impl TryFrom<Datum<'_>> for i64 {
394 type Error = ();
395
396 #[inline]
397 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
398 match from {
399 Datum::Int64(i) => Ok(i),
400 _ => Err(()),
401 }
402 }
403}
404
405impl TryFrom<Datum<'_>> for Option<i64> {
406 type Error = ();
407
408 #[inline]
409 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
410 match from {
411 Datum::Null => Ok(None),
412 Datum::Int64(i) => Ok(Some(i)),
413 _ => Err(()),
414 }
415 }
416}
417
418impl TryFrom<Datum<'_>> for u16 {
419 type Error = ();
420
421 #[inline]
422 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
423 match from {
424 Datum::UInt16(u) => Ok(u),
425 _ => Err(()),
426 }
427 }
428}
429
430impl TryFrom<Datum<'_>> for Option<u16> {
431 type Error = ();
432
433 #[inline]
434 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
435 match from {
436 Datum::Null => Ok(None),
437 Datum::UInt16(u) => Ok(Some(u)),
438 _ => Err(()),
439 }
440 }
441}
442
443impl TryFrom<Datum<'_>> for u32 {
444 type Error = ();
445
446 #[inline]
447 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
448 match from {
449 Datum::UInt32(u) => Ok(u),
450 _ => Err(()),
451 }
452 }
453}
454
455impl TryFrom<Datum<'_>> for Option<u32> {
456 type Error = ();
457
458 #[inline]
459 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
460 match from {
461 Datum::Null => Ok(None),
462 Datum::UInt32(u) => Ok(Some(u)),
463 _ => Err(()),
464 }
465 }
466}
467
468impl TryFrom<Datum<'_>> for u64 {
469 type Error = ();
470
471 #[inline]
472 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
473 match from {
474 Datum::UInt64(u) => Ok(u),
475 _ => Err(()),
476 }
477 }
478}
479
480impl TryFrom<Datum<'_>> for Option<u64> {
481 type Error = ();
482
483 #[inline]
484 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
485 match from {
486 Datum::Null => Ok(None),
487 Datum::UInt64(u) => Ok(Some(u)),
488 _ => Err(()),
489 }
490 }
491}
492
493impl TryFrom<Datum<'_>> for CheckedTimestamp<NaiveDateTime> {
494 type Error = ();
495
496 #[inline]
497 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
498 match from {
499 Datum::Timestamp(dt) => Ok(dt),
500 _ => Err(()),
501 }
502 }
503}
504
505impl TryFrom<Datum<'_>> for CheckedTimestamp<DateTime<Utc>> {
506 type Error = ();
507
508 #[inline]
509 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
510 match from {
511 Datum::TimestampTz(dt_tz) => Ok(dt_tz),
512 _ => Err(()),
513 }
514 }
515}
516
517impl TryFrom<Datum<'_>> for Date {
518 type Error = ();
519
520 #[inline]
521 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
522 match from {
523 Datum::Date(d) => Ok(d),
524 _ => Err(()),
525 }
526 }
527}
528
529impl TryFrom<Datum<'_>> for OrderedDecimal<Numeric> {
530 type Error = ();
531
532 #[inline]
533 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
534 match from {
535 Datum::Numeric(n) => Ok(n),
536 _ => Err(()),
537 }
538 }
539}
540
541impl TryFrom<Datum<'_>> for Option<OrderedDecimal<Numeric>> {
542 type Error = ();
543
544 #[inline]
545 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
546 match from {
547 Datum::Null => Ok(None),
548 Datum::Numeric(n) => Ok(Some(n)),
549 _ => Err(()),
550 }
551 }
552}
553
554impl TryFrom<Datum<'_>> for crate::Timestamp {
555 type Error = ();
556
557 #[inline]
558 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
559 match from {
560 Datum::MzTimestamp(n) => Ok(n),
561 _ => Err(()),
562 }
563 }
564}
565
566impl TryFrom<Datum<'_>> for Option<crate::Timestamp> {
567 type Error = ();
568
569 #[inline]
570 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
571 match from {
572 Datum::Null => Ok(None),
573 Datum::MzTimestamp(n) => Ok(Some(n)),
574 _ => Err(()),
575 }
576 }
577}
578
579impl TryFrom<Datum<'_>> for Interval {
580 type Error = ();
581
582 #[inline]
583 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
584 match from {
585 Datum::Interval(i) => Ok(i),
586 _ => Err(()),
587 }
588 }
589}
590
591impl TryFrom<Datum<'_>> for Option<Interval> {
592 type Error = ();
593
594 #[inline]
595 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
596 match from {
597 Datum::Null => Ok(None),
598 Datum::Interval(i) => Ok(Some(i)),
599 _ => Err(()),
600 }
601 }
602}
603
604impl TryFrom<Datum<'_>> for NaiveTime {
605 type Error = ();
606
607 #[inline]
608 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
609 match from {
610 Datum::Time(t) => Ok(t),
611 _ => Err(()),
612 }
613 }
614}
615
616impl TryFrom<Datum<'_>> for Option<NaiveTime> {
617 type Error = ();
618
619 #[inline]
620 fn try_from(from: Datum<'_>) -> Result<Self, Self::Error> {
621 match from {
622 Datum::Null => Ok(None),
623 Datum::Time(t) => Ok(Some(t)),
624 _ => Err(()),
625 }
626 }
627}
628
629impl<'a> Datum<'a> {
630 pub fn is_null(&self) -> bool {
632 matches!(self, Datum::Null)
633 }
634
635 #[track_caller]
641 pub fn unwrap_bool(&self) -> bool {
642 match self {
643 Datum::False => false,
644 Datum::True => true,
645 _ => panic!("Datum::unwrap_bool called on {:?}", self),
646 }
647 }
648
649 #[track_caller]
655 pub fn unwrap_int16(&self) -> i16 {
656 match self {
657 Datum::Int16(i) => *i,
658 _ => panic!("Datum::unwrap_int16 called on {:?}", self),
659 }
660 }
661
662 #[track_caller]
668 pub fn unwrap_int32(&self) -> i32 {
669 match self {
670 Datum::Int32(i) => *i,
671 _ => panic!("Datum::unwrap_int32 called on {:?}", self),
672 }
673 }
674
675 #[track_caller]
681 pub fn unwrap_int64(&self) -> i64 {
682 match self {
683 Datum::Int64(i) => *i,
684 _ => panic!("Datum::unwrap_int64 called on {:?}", self),
685 }
686 }
687
688 #[track_caller]
694 pub fn unwrap_uint8(&self) -> u8 {
695 match self {
696 Datum::UInt8(u) => *u,
697 _ => panic!("Datum::unwrap_uint8 called on {:?}", self),
698 }
699 }
700
701 #[track_caller]
707 pub fn unwrap_uint16(&self) -> u16 {
708 match self {
709 Datum::UInt16(u) => *u,
710 _ => panic!("Datum::unwrap_uint16 called on {:?}", self),
711 }
712 }
713
714 #[track_caller]
720 pub fn unwrap_uint32(&self) -> u32 {
721 match self {
722 Datum::UInt32(u) => *u,
723 _ => panic!("Datum::unwrap_uint32 called on {:?}", self),
724 }
725 }
726
727 #[track_caller]
733 pub fn unwrap_uint64(&self) -> u64 {
734 match self {
735 Datum::UInt64(u) => *u,
736 _ => panic!("Datum::unwrap_uint64 called on {:?}", self),
737 }
738 }
739
740 #[track_caller]
741 pub fn unwrap_ordered_float32(&self) -> OrderedFloat<f32> {
742 match self {
743 Datum::Float32(f) => *f,
744 _ => panic!("Datum::unwrap_ordered_float32 called on {:?}", self),
745 }
746 }
747
748 #[track_caller]
749 pub fn unwrap_ordered_float64(&self) -> OrderedFloat<f64> {
750 match self {
751 Datum::Float64(f) => *f,
752 _ => panic!("Datum::unwrap_ordered_float64 called on {:?}", self),
753 }
754 }
755
756 #[track_caller]
762 pub fn unwrap_float32(&self) -> f32 {
763 match self {
764 Datum::Float32(f) => f.into_inner(),
765 _ => panic!("Datum::unwrap_float32 called on {:?}", self),
766 }
767 }
768
769 #[track_caller]
775 pub fn unwrap_float64(&self) -> f64 {
776 match self {
777 Datum::Float64(f) => f.into_inner(),
778 _ => panic!("Datum::unwrap_float64 called on {:?}", self),
779 }
780 }
781
782 #[track_caller]
788 pub fn unwrap_date(&self) -> Date {
789 match self {
790 Datum::Date(d) => *d,
791 _ => panic!("Datum::unwrap_date called on {:?}", self),
792 }
793 }
794
795 #[track_caller]
801 pub fn unwrap_time(&self) -> chrono::NaiveTime {
802 match self {
803 Datum::Time(t) => *t,
804 _ => panic!("Datum::unwrap_time called on {:?}", self),
805 }
806 }
807
808 #[track_caller]
814 pub fn unwrap_timestamp(&self) -> CheckedTimestamp<chrono::NaiveDateTime> {
815 match self {
816 Datum::Timestamp(ts) => *ts,
817 _ => panic!("Datum::unwrap_timestamp called on {:?}", self),
818 }
819 }
820
821 #[track_caller]
827 pub fn unwrap_timestamptz(&self) -> CheckedTimestamp<chrono::DateTime<Utc>> {
828 match self {
829 Datum::TimestampTz(ts) => *ts,
830 _ => panic!("Datum::unwrap_timestamptz called on {:?}", self),
831 }
832 }
833
834 #[track_caller]
840 pub fn unwrap_interval(&self) -> Interval {
841 match self {
842 Datum::Interval(iv) => *iv,
843 _ => panic!("Datum::unwrap_interval called on {:?}", self),
844 }
845 }
846
847 #[track_caller]
853 pub fn unwrap_str(&self) -> &'a str {
854 match self {
855 Datum::String(s) => s,
856 _ => panic!("Datum::unwrap_string called on {:?}", self),
857 }
858 }
859
860 #[track_caller]
866 pub fn unwrap_bytes(&self) -> &'a [u8] {
867 match self {
868 Datum::Bytes(b) => b,
869 _ => panic!("Datum::unwrap_bytes called on {:?}", self),
870 }
871 }
872
873 #[track_caller]
879 pub fn unwrap_uuid(&self) -> Uuid {
880 match self {
881 Datum::Uuid(u) => *u,
882 _ => panic!("Datum::unwrap_uuid called on {:?}", self),
883 }
884 }
885
886 #[track_caller]
892 pub fn unwrap_array(&self) -> Array<'a> {
893 match self {
894 Datum::Array(array) => *array,
895 _ => panic!("Datum::unwrap_array called on {:?}", self),
896 }
897 }
898
899 #[track_caller]
905 pub fn unwrap_list(&self) -> DatumList<'a> {
906 match self {
907 Datum::List(list) => *list,
908 _ => panic!("Datum::unwrap_list called on {:?}", self),
909 }
910 }
911
912 #[track_caller]
918 pub fn unwrap_map(&self) -> DatumMap<'a> {
919 match self {
920 Datum::Map(dict) => *dict,
921 _ => panic!("Datum::unwrap_dict called on {:?}", self),
922 }
923 }
924
925 #[track_caller]
931 pub fn unwrap_numeric(&self) -> OrderedDecimal<Numeric> {
932 match self {
933 Datum::Numeric(n) => *n,
934 _ => panic!("Datum::unwrap_numeric called on {:?}", self),
935 }
936 }
937
938 #[track_caller]
944 pub fn unwrap_mz_timestamp(&self) -> crate::Timestamp {
945 match self {
946 Datum::MzTimestamp(t) => *t,
947 _ => panic!("Datum::unwrap_mz_timestamp called on {:?}", self),
948 }
949 }
950
951 #[track_caller]
962 pub fn unwrap_range(&self) -> Range<Datum<'a>> {
963 match self {
964 Datum::Range(range) => range.into_bounds(|b| b.datum()),
965 _ => panic!("Datum::unwrap_range called on {:?}", self),
966 }
967 }
968
969 #[track_caller]
975 pub fn unwrap_mz_acl_item(&self) -> MzAclItem {
976 match self {
977 Datum::MzAclItem(mz_acl_item) => *mz_acl_item,
978 _ => panic!("Datum::unwrap_mz_acl_item called on {:?}", self),
979 }
980 }
981
982 #[track_caller]
988 pub fn unwrap_acl_item(&self) -> AclItem {
989 match self {
990 Datum::AclItem(acl_item) => *acl_item,
991 _ => panic!("Datum::unwrap_acl_item called on {:?}", self),
992 }
993 }
994
995 pub fn is_instance_of(self, column_type: &ReprColumnType) -> bool {
999 fn is_instance_of_scalar(datum: Datum, scalar_type: &ReprScalarType) -> bool {
1000 if let ReprScalarType::Jsonb = scalar_type {
1001 match datum {
1003 Datum::Dummy => false,
1004 Datum::JsonNull
1005 | Datum::False
1006 | Datum::True
1007 | Datum::Numeric(_)
1008 | Datum::String(_) => true,
1009 Datum::List(list) => list
1010 .iter()
1011 .all(|elem| is_instance_of_scalar(elem, scalar_type)),
1012 Datum::Map(dict) => dict
1013 .iter()
1014 .all(|(_key, val)| is_instance_of_scalar(val, scalar_type)),
1015 _ => false,
1016 }
1017 } else {
1018 match (datum, scalar_type) {
1020 (Datum::Dummy, _) => false,
1021 (Datum::Null, _) => false,
1022 (Datum::False, ReprScalarType::Bool) => true,
1023 (Datum::False, _) => false,
1024 (Datum::True, ReprScalarType::Bool) => true,
1025 (Datum::True, _) => false,
1026 (Datum::Int16(_), ReprScalarType::Int16) => true,
1027 (Datum::Int16(_), _) => false,
1028 (Datum::Int32(_), ReprScalarType::Int32) => true,
1029 (Datum::Int32(_), _) => false,
1030 (Datum::Int64(_), ReprScalarType::Int64) => true,
1031 (Datum::Int64(_), _) => false,
1032 (Datum::UInt8(_), ReprScalarType::UInt8) => true,
1033 (Datum::UInt8(_), _) => false,
1034 (Datum::UInt16(_), ReprScalarType::UInt16) => true,
1035 (Datum::UInt16(_), _) => false,
1036 (Datum::UInt32(_), ReprScalarType::UInt32) => true,
1037 (Datum::UInt32(_), _) => false,
1038 (Datum::UInt64(_), ReprScalarType::UInt64) => true,
1039 (Datum::UInt64(_), _) => false,
1040 (Datum::Float32(_), ReprScalarType::Float32) => true,
1041 (Datum::Float32(_), _) => false,
1042 (Datum::Float64(_), ReprScalarType::Float64) => true,
1043 (Datum::Float64(_), _) => false,
1044 (Datum::Date(_), ReprScalarType::Date) => true,
1045 (Datum::Date(_), _) => false,
1046 (Datum::Time(_), ReprScalarType::Time) => true,
1047 (Datum::Time(_), _) => false,
1048 (Datum::Timestamp(_), ReprScalarType::Timestamp { .. }) => true,
1049 (Datum::Timestamp(_), _) => false,
1050 (Datum::TimestampTz(_), ReprScalarType::TimestampTz { .. }) => true,
1051 (Datum::TimestampTz(_), _) => false,
1052 (Datum::Interval(_), ReprScalarType::Interval) => true,
1053 (Datum::Interval(_), _) => false,
1054 (Datum::Bytes(_), ReprScalarType::Bytes) => true,
1055 (Datum::Bytes(_), _) => false,
1056 (Datum::String(_), ReprScalarType::String) => true,
1057 (Datum::String(_), _) => false,
1058 (Datum::Uuid(_), ReprScalarType::Uuid) => true,
1059 (Datum::Uuid(_), _) => false,
1060 (Datum::Array(array), ReprScalarType::Array(t)) => {
1061 array.elements.iter().all(|e| match e {
1062 Datum::Null => true,
1063 _ => is_instance_of_scalar(e, t),
1064 })
1065 }
1066 (Datum::Array(array), ReprScalarType::Int2Vector) => {
1067 array.dims().len() == 1
1068 && array
1069 .elements
1070 .iter()
1071 .all(|e| is_instance_of_scalar(e, &ReprScalarType::Int16))
1072 }
1073 (Datum::Array(_), _) => false,
1074 (Datum::List(list), ReprScalarType::List { element_type, .. }) => list
1075 .iter()
1076 .all(|e| e.is_null() || is_instance_of_scalar(e, element_type)),
1077 (Datum::List(list), ReprScalarType::Record { fields, .. }) => {
1078 if list.iter().count() != fields.len() {
1079 return false;
1080 }
1081
1082 list.iter().zip_eq(fields).all(|(e, t)| {
1083 (e.is_null() && t.nullable) || is_instance_of_scalar(e, &t.scalar_type)
1084 })
1085 }
1086 (Datum::List(_), _) => false,
1087 (Datum::Map(map), ReprScalarType::Map { value_type, .. }) => map
1088 .iter()
1089 .all(|(_k, v)| v.is_null() || is_instance_of_scalar(v, value_type)),
1090 (Datum::Map(_), _) => false,
1091 (Datum::JsonNull, _) => false,
1092 (Datum::Numeric(_), ReprScalarType::Numeric) => true,
1093 (Datum::Numeric(_), _) => false,
1094 (Datum::MzTimestamp(_), ReprScalarType::MzTimestamp) => true,
1095 (Datum::MzTimestamp(_), _) => false,
1096 (Datum::Range(Range { inner }), ReprScalarType::Range { element_type }) => {
1097 match inner {
1098 None => true,
1099 Some(inner) => {
1100 true && match inner.lower.bound {
1101 None => true,
1102 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1103 } && match inner.upper.bound {
1104 None => true,
1105 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1106 }
1107 }
1108 }
1109 }
1110 (Datum::Range(_), _) => false,
1111 (Datum::MzAclItem(_), ReprScalarType::MzAclItem) => true,
1112 (Datum::MzAclItem(_), _) => false,
1113 (Datum::AclItem(_), ReprScalarType::AclItem) => true,
1114 (Datum::AclItem(_), _) => false,
1115 }
1116 }
1117 }
1118 if column_type.nullable {
1119 if let Datum::Null = self {
1120 return true;
1121 }
1122 }
1123 is_instance_of_scalar(self, &column_type.scalar_type)
1124 }
1125
1126 pub fn is_instance_of_sql(self, column_type: &SqlColumnType) -> bool {
1130 fn is_instance_of_scalar(datum: Datum, scalar_type: &SqlScalarType) -> bool {
1131 if let SqlScalarType::Jsonb = scalar_type {
1132 match datum {
1134 Datum::Dummy => false,
1135 Datum::JsonNull
1136 | Datum::False
1137 | Datum::True
1138 | Datum::Numeric(_)
1139 | Datum::String(_) => true,
1140 Datum::List(list) => list
1141 .iter()
1142 .all(|elem| is_instance_of_scalar(elem, scalar_type)),
1143 Datum::Map(dict) => dict
1144 .iter()
1145 .all(|(_key, val)| is_instance_of_scalar(val, scalar_type)),
1146 _ => false,
1147 }
1148 } else {
1149 match (datum, scalar_type) {
1151 (Datum::Dummy, _) => false,
1152 (Datum::Null, _) => false,
1153 (Datum::False, SqlScalarType::Bool) => true,
1154 (Datum::False, _) => false,
1155 (Datum::True, SqlScalarType::Bool) => true,
1156 (Datum::True, _) => false,
1157 (Datum::Int16(_), SqlScalarType::Int16) => true,
1158 (Datum::Int16(_), _) => false,
1159 (Datum::Int32(_), SqlScalarType::Int32) => true,
1160 (Datum::Int32(_), _) => false,
1161 (Datum::Int64(_), SqlScalarType::Int64) => true,
1162 (Datum::Int64(_), _) => false,
1163 (Datum::UInt8(_), SqlScalarType::PgLegacyChar) => true,
1164 (Datum::UInt8(_), _) => false,
1165 (Datum::UInt16(_), SqlScalarType::UInt16) => true,
1166 (Datum::UInt16(_), _) => false,
1167 (Datum::UInt32(_), SqlScalarType::Oid) => true,
1168 (Datum::UInt32(_), SqlScalarType::RegClass) => true,
1169 (Datum::UInt32(_), SqlScalarType::RegProc) => true,
1170 (Datum::UInt32(_), SqlScalarType::RegType) => true,
1171 (Datum::UInt32(_), SqlScalarType::UInt32) => true,
1172 (Datum::UInt32(_), _) => false,
1173 (Datum::UInt64(_), SqlScalarType::UInt64) => true,
1174 (Datum::UInt64(_), _) => false,
1175 (Datum::Float32(_), SqlScalarType::Float32) => true,
1176 (Datum::Float32(_), _) => false,
1177 (Datum::Float64(_), SqlScalarType::Float64) => true,
1178 (Datum::Float64(_), _) => false,
1179 (Datum::Date(_), SqlScalarType::Date) => true,
1180 (Datum::Date(_), _) => false,
1181 (Datum::Time(_), SqlScalarType::Time) => true,
1182 (Datum::Time(_), _) => false,
1183 (Datum::Timestamp(_), SqlScalarType::Timestamp { .. }) => true,
1184 (Datum::Timestamp(_), _) => false,
1185 (Datum::TimestampTz(_), SqlScalarType::TimestampTz { .. }) => true,
1186 (Datum::TimestampTz(_), _) => false,
1187 (Datum::Interval(_), SqlScalarType::Interval) => true,
1188 (Datum::Interval(_), _) => false,
1189 (Datum::Bytes(_), SqlScalarType::Bytes) => true,
1190 (Datum::Bytes(_), _) => false,
1191 (Datum::String(_), SqlScalarType::String)
1192 | (Datum::String(_), SqlScalarType::VarChar { .. })
1193 | (Datum::String(_), SqlScalarType::Char { .. })
1194 | (Datum::String(_), SqlScalarType::PgLegacyName) => true,
1195 (Datum::String(_), _) => false,
1196 (Datum::Uuid(_), SqlScalarType::Uuid) => true,
1197 (Datum::Uuid(_), _) => false,
1198 (Datum::Array(array), SqlScalarType::Array(t)) => {
1199 array.elements.iter().all(|e| match e {
1200 Datum::Null => true,
1201 _ => is_instance_of_scalar(e, t),
1202 })
1203 }
1204 (Datum::Array(array), SqlScalarType::Int2Vector) => {
1205 array.dims().len() == 1
1206 && array
1207 .elements
1208 .iter()
1209 .all(|e| is_instance_of_scalar(e, &SqlScalarType::Int16))
1210 }
1211 (Datum::Array(_), _) => false,
1212 (Datum::List(list), SqlScalarType::List { element_type, .. }) => list
1213 .iter()
1214 .all(|e| e.is_null() || is_instance_of_scalar(e, element_type)),
1215 (Datum::List(list), SqlScalarType::Record { fields, .. }) => {
1216 if list.iter().count() != fields.len() {
1217 return false;
1218 }
1219
1220 list.iter().zip_eq(fields).all(|(e, (_, t))| {
1221 (e.is_null() && t.nullable) || is_instance_of_scalar(e, &t.scalar_type)
1222 })
1223 }
1224 (Datum::List(_), _) => false,
1225 (Datum::Map(map), SqlScalarType::Map { value_type, .. }) => map
1226 .iter()
1227 .all(|(_k, v)| v.is_null() || is_instance_of_scalar(v, value_type)),
1228 (Datum::Map(_), _) => false,
1229 (Datum::JsonNull, _) => false,
1230 (Datum::Numeric(_), SqlScalarType::Numeric { .. }) => true,
1231 (Datum::Numeric(_), _) => false,
1232 (Datum::MzTimestamp(_), SqlScalarType::MzTimestamp) => true,
1233 (Datum::MzTimestamp(_), _) => false,
1234 (Datum::Range(Range { inner }), SqlScalarType::Range { element_type }) => {
1235 match inner {
1236 None => true,
1237 Some(inner) => {
1238 true && match inner.lower.bound {
1239 None => true,
1240 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1241 } && match inner.upper.bound {
1242 None => true,
1243 Some(b) => is_instance_of_scalar(b.datum(), element_type),
1244 }
1245 }
1246 }
1247 }
1248 (Datum::Range(_), _) => false,
1249 (Datum::MzAclItem(_), SqlScalarType::MzAclItem) => true,
1250 (Datum::MzAclItem(_), _) => false,
1251 (Datum::AclItem(_), SqlScalarType::AclItem) => true,
1252 (Datum::AclItem(_), _) => false,
1253 }
1254 }
1255 }
1256 if column_type.nullable {
1257 if let Datum::Null = self {
1258 return true;
1259 }
1260 }
1261 is_instance_of_scalar(self, &column_type.scalar_type)
1262 }
1263}
1264
1265impl<'a> From<bool> for Datum<'a> {
1266 #[inline]
1267 fn from(b: bool) -> Datum<'a> {
1268 if b { Datum::True } else { Datum::False }
1269 }
1270}
1271
1272impl<'a, T> From<Overflowing<T>> for Datum<'a>
1275where
1276 Datum<'a>: From<T>,
1277{
1278 #[inline]
1279 fn from(i: Overflowing<T>) -> Datum<'a> {
1280 Datum::from(i.into_inner())
1281 }
1282}
1283
1284impl<'a> From<i16> for Datum<'a> {
1285 #[inline]
1286 fn from(i: i16) -> Datum<'a> {
1287 Datum::Int16(i)
1288 }
1289}
1290
1291impl<'a> From<i32> for Datum<'a> {
1292 #[inline]
1293 fn from(i: i32) -> Datum<'a> {
1294 Datum::Int32(i)
1295 }
1296}
1297
1298impl<'a> From<i64> for Datum<'a> {
1299 #[inline]
1300 fn from(i: i64) -> Datum<'a> {
1301 Datum::Int64(i)
1302 }
1303}
1304
1305impl<'a> From<u8> for Datum<'a> {
1306 #[inline]
1307 fn from(u: u8) -> Datum<'a> {
1308 Datum::UInt8(u)
1309 }
1310}
1311
1312impl<'a> From<u16> for Datum<'a> {
1313 #[inline]
1314 fn from(u: u16) -> Datum<'a> {
1315 Datum::UInt16(u)
1316 }
1317}
1318
1319impl<'a> From<u32> for Datum<'a> {
1320 #[inline]
1321 fn from(u: u32) -> Datum<'a> {
1322 Datum::UInt32(u)
1323 }
1324}
1325
1326impl<'a> From<u64> for Datum<'a> {
1327 #[inline]
1328 fn from(u: u64) -> Datum<'a> {
1329 Datum::UInt64(u)
1330 }
1331}
1332
1333impl<'a> From<OrderedFloat<f32>> for Datum<'a> {
1334 #[inline]
1335 fn from(f: OrderedFloat<f32>) -> Datum<'a> {
1336 Datum::Float32(f)
1337 }
1338}
1339
1340impl<'a> From<OrderedFloat<f64>> for Datum<'a> {
1341 #[inline]
1342 fn from(f: OrderedFloat<f64>) -> Datum<'a> {
1343 Datum::Float64(f)
1344 }
1345}
1346
1347impl<'a> From<f32> for Datum<'a> {
1348 #[inline]
1349 fn from(f: f32) -> Datum<'a> {
1350 Datum::Float32(OrderedFloat(f))
1351 }
1352}
1353
1354impl<'a> From<f64> for Datum<'a> {
1355 #[inline]
1356 fn from(f: f64) -> Datum<'a> {
1357 Datum::Float64(OrderedFloat(f))
1358 }
1359}
1360
1361impl<'a> From<i128> for Datum<'a> {
1362 #[inline]
1363 fn from(d: i128) -> Datum<'a> {
1364 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1365 }
1366}
1367
1368impl<'a> From<u128> for Datum<'a> {
1369 #[inline]
1370 fn from(d: u128) -> Datum<'a> {
1371 Datum::Numeric(OrderedDecimal(Numeric::try_from(d).unwrap()))
1372 }
1373}
1374
1375impl<'a> From<Numeric> for Datum<'a> {
1376 #[inline]
1377 fn from(n: Numeric) -> Datum<'a> {
1378 Datum::Numeric(OrderedDecimal(n))
1379 }
1380}
1381
1382impl<'a> From<OrderedDecimal<Numeric>> for Datum<'a> {
1383 #[inline]
1384 fn from(n: OrderedDecimal<Numeric>) -> Datum<'a> {
1385 Datum::Numeric(n)
1386 }
1387}
1388
1389impl<'a> From<chrono::Duration> for Datum<'a> {
1390 #[inline]
1391 fn from(duration: chrono::Duration) -> Datum<'a> {
1392 let micros = duration.num_microseconds().unwrap_or(0);
1393 Datum::Interval(Interval::new(0, 0, micros))
1394 }
1395}
1396
1397impl<'a> From<Interval> for Datum<'a> {
1398 #[inline]
1399 fn from(other: Interval) -> Datum<'a> {
1400 Datum::Interval(other)
1401 }
1402}
1403
1404impl<'a> From<&'a str> for Datum<'a> {
1405 #[inline]
1406 fn from(s: &'a str) -> Datum<'a> {
1407 Datum::String(s)
1408 }
1409}
1410
1411impl<'a> From<&'a [u8]> for Datum<'a> {
1412 #[inline]
1413 fn from(b: &'a [u8]) -> Datum<'a> {
1414 Datum::Bytes(b)
1415 }
1416}
1417
1418impl<'a> From<Date> for Datum<'a> {
1419 #[inline]
1420 fn from(d: Date) -> Datum<'a> {
1421 Datum::Date(d)
1422 }
1423}
1424
1425impl<'a> From<NaiveTime> for Datum<'a> {
1426 #[inline]
1427 fn from(t: NaiveTime) -> Datum<'a> {
1428 Datum::Time(t)
1429 }
1430}
1431
1432impl<'a> From<CheckedTimestamp<NaiveDateTime>> for Datum<'a> {
1433 #[inline]
1434 fn from(dt: CheckedTimestamp<NaiveDateTime>) -> Datum<'a> {
1435 Datum::Timestamp(dt)
1436 }
1437}
1438
1439impl<'a> From<CheckedTimestamp<DateTime<Utc>>> for Datum<'a> {
1440 #[inline]
1441 fn from(dt: CheckedTimestamp<DateTime<Utc>>) -> Datum<'a> {
1442 Datum::TimestampTz(dt)
1443 }
1444}
1445
1446impl<'a> TryInto<Datum<'a>> for NaiveDateTime {
1447 type Error = TimestampError;
1448
1449 #[inline]
1450 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1451 let t = CheckedTimestamp::from_timestamplike(self)?;
1452 Ok(t.into())
1453 }
1454}
1455
1456impl<'a> TryInto<Datum<'a>> for DateTime<Utc> {
1457 type Error = TimestampError;
1458
1459 #[inline]
1460 fn try_into(self) -> Result<Datum<'a>, Self::Error> {
1461 let t = CheckedTimestamp::from_timestamplike(self)?;
1462 Ok(t.into())
1463 }
1464}
1465
1466impl<'a> From<Uuid> for Datum<'a> {
1467 #[inline]
1468 fn from(uuid: Uuid) -> Datum<'a> {
1469 Datum::Uuid(uuid)
1470 }
1471}
1472impl<'a> From<crate::Timestamp> for Datum<'a> {
1473 #[inline]
1474 fn from(ts: crate::Timestamp) -> Datum<'a> {
1475 Datum::MzTimestamp(ts)
1476 }
1477}
1478
1479impl<'a> From<MzAclItem> for Datum<'a> {
1480 #[inline]
1481 fn from(mz_acl_item: MzAclItem) -> Self {
1482 Datum::MzAclItem(mz_acl_item)
1483 }
1484}
1485
1486impl<'a, T> From<Option<T>> for Datum<'a>
1487where
1488 Datum<'a>: From<T>,
1489{
1490 fn from(o: Option<T>) -> Datum<'a> {
1491 match o {
1492 Some(d) => d.into(),
1493 None => Datum::Null,
1494 }
1495 }
1496}
1497
1498fn write_delimited<T, TS, F>(
1499 f: &mut fmt::Formatter,
1500 delimiter: &str,
1501 things: TS,
1502 write: F,
1503) -> fmt::Result
1504where
1505 TS: IntoIterator<Item = T>,
1506 F: Fn(&mut fmt::Formatter, T) -> fmt::Result,
1507{
1508 let mut iter = things.into_iter().peekable();
1509 while let Some(thing) = iter.next() {
1510 write(f, thing)?;
1511 if iter.peek().is_some() {
1512 f.write_str(delimiter)?;
1513 }
1514 }
1515 Ok(())
1516}
1517
1518impl fmt::Display for Datum<'_> {
1519 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1520 match self {
1521 Datum::Null => f.write_str("null"),
1522 Datum::True => f.write_str("true"),
1523 Datum::False => f.write_str("false"),
1524 Datum::Int16(num) => write!(f, "{}", num),
1525 Datum::Int32(num) => write!(f, "{}", num),
1526 Datum::Int64(num) => write!(f, "{}", num),
1527 Datum::UInt8(num) => write!(f, "{}", num),
1528 Datum::UInt16(num) => write!(f, "{}", num),
1529 Datum::UInt32(num) => write!(f, "{}", num),
1530 Datum::UInt64(num) => write!(f, "{}", num),
1531 Datum::Float32(num) => write!(f, "{}", num),
1532 Datum::Float64(num) => write!(f, "{}", num),
1533 Datum::Date(d) => write!(f, "{}", d),
1534 Datum::Time(t) => write!(f, "{}", t),
1535 Datum::Timestamp(t) => write!(f, "{}", t),
1536 Datum::TimestampTz(t) => write!(f, "{}", t),
1537 Datum::Interval(iv) => write!(f, "{}", iv),
1538 Datum::Bytes(dat) => {
1539 f.write_str("0x")?;
1540 for b in dat.iter() {
1541 write!(f, "{:02x}", b)?;
1542 }
1543 Ok(())
1544 }
1545 Datum::String(s) => {
1546 write!(f, "{}", s.escaped())
1547 }
1548 Datum::Uuid(u) => write!(f, "{}", u),
1549 Datum::Array(array) => {
1550 if array.dims().into_iter().any(|dim| dim.lower_bound != 1) {
1551 write_delimited(f, "", array.dims().into_iter(), |f, e| {
1552 let (lower, upper) = e.dimension_bounds();
1553 write!(f, "[{}:{}]", lower, upper)
1554 })?;
1555 f.write_str("=")?;
1556 }
1557 f.write_str("{")?;
1558 write_delimited(f, ", ", &array.elements, |f, e| write!(f, "{}", e))?;
1559 f.write_str("}")
1560 }
1561 Datum::List(list) => {
1562 f.write_str("[")?;
1563 write_delimited(f, ", ", list, |f, e| write!(f, "{}", e))?;
1564 f.write_str("]")
1565 }
1566 Datum::Map(dict) => {
1567 f.write_str("{")?;
1568 write_delimited(f, ", ", dict, |f, (k, v)| write!(f, "{}: {}", k, v))?;
1569 f.write_str("}")
1570 }
1571 Datum::Numeric(n) => write!(f, "{}", n.0.to_standard_notation_string()),
1572 Datum::MzTimestamp(t) => write!(f, "{}", t),
1573 Datum::JsonNull => f.write_str("json_null"),
1574 Datum::Dummy => f.write_str("dummy"),
1575 Datum::Range(i) => write!(f, "{}", i),
1576 Datum::MzAclItem(mz_acl_item) => write!(f, "{mz_acl_item}"),
1577 Datum::AclItem(acl_item) => write!(f, "{acl_item}"),
1578 }
1579 }
1580}
1581
1582#[derive(
1592 Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash, EnumKind, MzReflect,
1593)]
1594#[enum_kind(ScalarBaseType, derive(PartialOrd, Ord, Hash))]
1595pub enum SqlScalarType {
1596 Bool,
1598 Int16,
1600 Int32,
1602 Int64,
1604 UInt16,
1606 UInt32,
1608 UInt64,
1610 Float32,
1612 Float64,
1614 Numeric {
1624 max_scale: Option<NumericMaxScale>,
1625 },
1626 Date,
1628 Time,
1630 Timestamp {
1632 precision: Option<TimestampPrecision>,
1633 },
1634 TimestampTz {
1636 precision: Option<TimestampPrecision>,
1637 },
1638 Interval,
1640 PgLegacyChar,
1645 PgLegacyName,
1651 Bytes,
1653 String,
1655 Char {
1661 length: Option<CharLength>,
1662 },
1663 VarChar {
1666 max_length: Option<VarCharMaxLength>,
1667 },
1668 Jsonb,
1680 Uuid,
1682 Array(Box<SqlScalarType>),
1688 List {
1693 element_type: Box<SqlScalarType>,
1694 custom_id: Option<CatalogItemId>,
1695 },
1696 Record {
1698 fields: Box<[(ColumnName, SqlColumnType)]>,
1703 custom_id: Option<CatalogItemId>,
1704 },
1705 Oid,
1707 Map {
1713 value_type: Box<SqlScalarType>,
1714 custom_id: Option<CatalogItemId>,
1715 },
1716 RegProc,
1718 RegType,
1720 RegClass,
1722 Int2Vector,
1725 MzTimestamp,
1727 Range {
1728 element_type: Box<SqlScalarType>,
1729 },
1730 MzAclItem,
1732 AclItem,
1734}
1735
1736impl RustType<ProtoRecordField> for (ColumnName, SqlColumnType) {
1737 fn into_proto(&self) -> ProtoRecordField {
1738 ProtoRecordField {
1739 column_name: Some(self.0.into_proto()),
1740 column_type: Some(self.1.into_proto()),
1741 }
1742 }
1743
1744 fn from_proto(proto: ProtoRecordField) -> Result<Self, TryFromProtoError> {
1745 Ok((
1746 proto
1747 .column_name
1748 .into_rust_if_some("ProtoRecordField::column_name")?,
1749 proto
1750 .column_type
1751 .into_rust_if_some("ProtoRecordField::column_type")?,
1752 ))
1753 }
1754}
1755
1756impl RustType<ProtoScalarType> for SqlScalarType {
1757 fn into_proto(&self) -> ProtoScalarType {
1758 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1759 use crate::relation_and_scalar::proto_scalar_type::*;
1760
1761 ProtoScalarType {
1762 kind: Some(match self {
1763 SqlScalarType::Bool => Bool(()),
1764 SqlScalarType::Int16 => Int16(()),
1765 SqlScalarType::Int32 => Int32(()),
1766 SqlScalarType::Int64 => Int64(()),
1767 SqlScalarType::UInt16 => UInt16(()),
1768 SqlScalarType::UInt32 => UInt32(()),
1769 SqlScalarType::UInt64 => UInt64(()),
1770 SqlScalarType::Float32 => Float32(()),
1771 SqlScalarType::Float64 => Float64(()),
1772 SqlScalarType::Date => Date(()),
1773 SqlScalarType::Time => Time(()),
1774 SqlScalarType::Timestamp { precision } => Timestamp(ProtoTimestamp {
1775 precision: precision.into_proto(),
1776 }),
1777 SqlScalarType::TimestampTz { precision } => TimestampTz(ProtoTimestampTz {
1778 precision: precision.into_proto(),
1779 }),
1780 SqlScalarType::Interval => Interval(()),
1781 SqlScalarType::PgLegacyChar => PgLegacyChar(()),
1782 SqlScalarType::PgLegacyName => PgLegacyName(()),
1783 SqlScalarType::Bytes => Bytes(()),
1784 SqlScalarType::String => String(()),
1785 SqlScalarType::Jsonb => Jsonb(()),
1786 SqlScalarType::Uuid => Uuid(()),
1787 SqlScalarType::Oid => Oid(()),
1788 SqlScalarType::RegProc => RegProc(()),
1789 SqlScalarType::RegType => RegType(()),
1790 SqlScalarType::RegClass => RegClass(()),
1791 SqlScalarType::Int2Vector => Int2Vector(()),
1792
1793 SqlScalarType::Numeric { max_scale } => Numeric(max_scale.into_proto()),
1794 SqlScalarType::Char { length } => Char(ProtoChar {
1795 length: length.into_proto(),
1796 }),
1797 SqlScalarType::VarChar { max_length } => VarChar(ProtoVarChar {
1798 max_length: max_length.into_proto(),
1799 }),
1800
1801 SqlScalarType::List {
1802 element_type,
1803 custom_id,
1804 } => List(Box::new(ProtoList {
1805 element_type: Some(element_type.into_proto()),
1806 custom_id: custom_id.map(|id| id.into_proto()),
1807 })),
1808 SqlScalarType::Record { custom_id, fields } => Record(ProtoRecord {
1809 custom_id: custom_id.map(|id| id.into_proto()),
1810 fields: fields.into_proto(),
1811 }),
1812 SqlScalarType::Array(typ) => Array(typ.into_proto()),
1813 SqlScalarType::Map {
1814 value_type,
1815 custom_id,
1816 } => Map(Box::new(ProtoMap {
1817 value_type: Some(value_type.into_proto()),
1818 custom_id: custom_id.map(|id| id.into_proto()),
1819 })),
1820 SqlScalarType::MzTimestamp => MzTimestamp(()),
1821 SqlScalarType::Range { element_type } => Range(Box::new(ProtoRange {
1822 element_type: Some(element_type.into_proto()),
1823 })),
1824 SqlScalarType::MzAclItem => MzAclItem(()),
1825 SqlScalarType::AclItem => AclItem(()),
1826 }),
1827 }
1828 }
1829
1830 fn from_proto(proto: ProtoScalarType) -> Result<Self, TryFromProtoError> {
1831 use crate::relation_and_scalar::proto_scalar_type::Kind::*;
1832
1833 let kind = proto
1834 .kind
1835 .ok_or_else(|| TryFromProtoError::missing_field("ProtoScalarType::Kind"))?;
1836
1837 match kind {
1838 Bool(()) => Ok(SqlScalarType::Bool),
1839 Int16(()) => Ok(SqlScalarType::Int16),
1840 Int32(()) => Ok(SqlScalarType::Int32),
1841 Int64(()) => Ok(SqlScalarType::Int64),
1842 UInt16(()) => Ok(SqlScalarType::UInt16),
1843 UInt32(()) => Ok(SqlScalarType::UInt32),
1844 UInt64(()) => Ok(SqlScalarType::UInt64),
1845 Float32(()) => Ok(SqlScalarType::Float32),
1846 Float64(()) => Ok(SqlScalarType::Float64),
1847 Date(()) => Ok(SqlScalarType::Date),
1848 Time(()) => Ok(SqlScalarType::Time),
1849 Timestamp(x) => Ok(SqlScalarType::Timestamp {
1850 precision: x.precision.into_rust()?,
1851 }),
1852 TimestampTz(x) => Ok(SqlScalarType::TimestampTz {
1853 precision: x.precision.into_rust()?,
1854 }),
1855 Interval(()) => Ok(SqlScalarType::Interval),
1856 PgLegacyChar(()) => Ok(SqlScalarType::PgLegacyChar),
1857 PgLegacyName(()) => Ok(SqlScalarType::PgLegacyName),
1858 Bytes(()) => Ok(SqlScalarType::Bytes),
1859 String(()) => Ok(SqlScalarType::String),
1860 Jsonb(()) => Ok(SqlScalarType::Jsonb),
1861 Uuid(()) => Ok(SqlScalarType::Uuid),
1862 Oid(()) => Ok(SqlScalarType::Oid),
1863 RegProc(()) => Ok(SqlScalarType::RegProc),
1864 RegType(()) => Ok(SqlScalarType::RegType),
1865 RegClass(()) => Ok(SqlScalarType::RegClass),
1866 Int2Vector(()) => Ok(SqlScalarType::Int2Vector),
1867
1868 Numeric(x) => Ok(SqlScalarType::Numeric {
1869 max_scale: x.into_rust()?,
1870 }),
1871 Char(x) => Ok(SqlScalarType::Char {
1872 length: x.length.into_rust()?,
1873 }),
1874
1875 VarChar(x) => Ok(SqlScalarType::VarChar {
1876 max_length: x.max_length.into_rust()?,
1877 }),
1878 Array(x) => Ok(SqlScalarType::Array({
1879 let st: SqlScalarType = (*x).into_rust()?;
1880 st.into()
1881 })),
1882 List(x) => Ok(SqlScalarType::List {
1883 element_type: Box::new(
1884 x.element_type
1885 .map(|x| *x)
1886 .into_rust_if_some("ProtoList::element_type")?,
1887 ),
1888 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1889 }),
1890 Record(x) => Ok(SqlScalarType::Record {
1891 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1892 fields: x.fields.into_rust()?,
1893 }),
1894 Map(x) => Ok(SqlScalarType::Map {
1895 value_type: Box::new(
1896 x.value_type
1897 .map(|x| *x)
1898 .into_rust_if_some("ProtoMap::value_type")?,
1899 ),
1900 custom_id: x.custom_id.map(|id| id.into_rust().unwrap()),
1901 }),
1902 MzTimestamp(()) => Ok(SqlScalarType::MzTimestamp),
1903 Range(x) => Ok(SqlScalarType::Range {
1904 element_type: Box::new(
1905 x.element_type
1906 .map(|x| *x)
1907 .into_rust_if_some("ProtoRange::element_type")?,
1908 ),
1909 }),
1910 MzAclItem(()) => Ok(SqlScalarType::MzAclItem),
1911 AclItem(()) => Ok(SqlScalarType::AclItem),
1912 }
1913 }
1914}
1915
1916pub trait AsColumnType {
1918 fn as_column_type() -> SqlColumnType;
1920}
1921
1922pub trait DatumType<'a, E>: Sized {
1924 fn nullable() -> bool;
1926
1927 fn fallible() -> bool;
1929
1930 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>>;
1933
1934 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E>;
1936}
1937
1938#[derive(Debug)]
1941pub struct ArrayRustType<T>(pub Vec<T>);
1942
1943impl<B: AsColumnType> AsColumnType for Option<B> {
1944 fn as_column_type() -> SqlColumnType {
1945 B::as_column_type().nullable(true)
1946 }
1947}
1948
1949impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for Option<B> {
1950 fn nullable() -> bool {
1951 true
1952 }
1953 fn fallible() -> bool {
1954 false
1955 }
1956 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1957 match res {
1958 Ok(Datum::Null) => Ok(None),
1959 Ok(datum) => B::try_from_result(Ok(datum)).map(Some),
1960 _ => Err(res),
1961 }
1962 }
1963 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1964 match self {
1965 Some(inner) => inner.into_result(temp_storage),
1966 None => Ok(Datum::Null),
1967 }
1968 }
1969}
1970
1971impl<E, B: AsColumnType> AsColumnType for Result<B, E> {
1972 fn as_column_type() -> SqlColumnType {
1973 B::as_column_type()
1974 }
1975}
1976
1977impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for Result<B, E> {
1978 fn nullable() -> bool {
1979 B::nullable()
1980 }
1981 fn fallible() -> bool {
1982 true
1983 }
1984 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
1985 B::try_from_result(res).map(Ok)
1986 }
1987 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
1988 self.and_then(|inner| inner.into_result(temp_storage))
1989 }
1990}
1991
1992macro_rules! impl_datum_type_copy {
1994 ($lt:lifetime, $native:ty, $variant:ident) => {
1995 impl<$lt> AsColumnType for $native {
1996 fn as_column_type() -> SqlColumnType {
1997 SqlScalarType::$variant.nullable(false)
1998 }
1999 }
2000
2001 impl<$lt, E> DatumType<$lt, E> for $native {
2002 fn nullable() -> bool {
2003 false
2004 }
2005
2006 fn fallible() -> bool {
2007 false
2008 }
2009
2010 fn try_from_result(res: Result<Datum<$lt>, E>) -> Result<Self, Result<Datum<$lt>, E>> {
2011 match res {
2012 Ok(Datum::$variant(f)) => Ok(f.into()),
2013 _ => Err(res),
2014 }
2015 }
2016
2017 fn into_result(self, _temp_storage: &$lt RowArena) -> Result<Datum<$lt>, E> {
2018 Ok(Datum::$variant(self.into()))
2019 }
2020 }
2021 };
2022 ($native:ty, $variant:ident) => {
2023 impl_datum_type_copy!('a, $native, $variant);
2024 };
2025}
2026
2027impl_datum_type_copy!(f32, Float32);
2028impl_datum_type_copy!(f64, Float64);
2029impl_datum_type_copy!(i16, Int16);
2030impl_datum_type_copy!(i32, Int32);
2031impl_datum_type_copy!(i64, Int64);
2032impl_datum_type_copy!(u16, UInt16);
2033impl_datum_type_copy!(u32, UInt32);
2034impl_datum_type_copy!(u64, UInt64);
2035impl_datum_type_copy!(Interval, Interval);
2036impl_datum_type_copy!(Date, Date);
2037impl_datum_type_copy!(NaiveTime, Time);
2038impl_datum_type_copy!(Uuid, Uuid);
2039impl_datum_type_copy!('a, &'a str, String);
2040impl_datum_type_copy!('a, &'a [u8], Bytes);
2041impl_datum_type_copy!(crate::Timestamp, MzTimestamp);
2042
2043impl<'a, E> DatumType<'a, E> for Datum<'a> {
2044 fn nullable() -> bool {
2045 true
2046 }
2047
2048 fn fallible() -> bool {
2049 false
2050 }
2051
2052 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2053 match res {
2054 Ok(datum) => Ok(datum),
2055 _ => Err(res),
2056 }
2057 }
2058
2059 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2060 Ok(self)
2061 }
2062}
2063
2064impl<'a, E> DatumType<'a, E> for DatumList<'a> {
2065 fn nullable() -> bool {
2066 false
2067 }
2068
2069 fn fallible() -> bool {
2070 false
2071 }
2072
2073 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2074 match res {
2075 Ok(Datum::List(list)) => Ok(list),
2076 _ => Err(res),
2077 }
2078 }
2079
2080 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2081 Ok(Datum::List(self))
2082 }
2083}
2084
2085impl<'a, E> DatumType<'a, E> for Array<'a> {
2086 fn nullable() -> bool {
2087 false
2088 }
2089
2090 fn fallible() -> bool {
2091 false
2092 }
2093
2094 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2095 match res {
2096 Ok(Datum::Array(array)) => Ok(array),
2097 _ => Err(res),
2098 }
2099 }
2100
2101 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2102 Ok(Datum::Array(self))
2103 }
2104}
2105
2106impl<'a, E> DatumType<'a, E> for DatumMap<'a> {
2107 fn nullable() -> bool {
2108 false
2109 }
2110
2111 fn fallible() -> bool {
2112 false
2113 }
2114
2115 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2116 match res {
2117 Ok(Datum::Map(map)) => Ok(map),
2118 _ => Err(res),
2119 }
2120 }
2121
2122 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2123 Ok(Datum::Map(self))
2124 }
2125}
2126
2127impl<'a, E> DatumType<'a, E> for Range<DatumNested<'a>> {
2128 fn nullable() -> bool {
2129 false
2130 }
2131
2132 fn fallible() -> bool {
2133 false
2134 }
2135
2136 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2137 match res {
2138 Ok(Datum::Range(range)) => Ok(range),
2139 _ => Err(res),
2140 }
2141 }
2142
2143 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2144 Ok(Datum::Range(self))
2145 }
2146}
2147
2148impl<'a, E> DatumType<'a, E> for Range<Datum<'a>> {
2149 fn nullable() -> bool {
2150 false
2151 }
2152
2153 fn fallible() -> bool {
2154 false
2155 }
2156
2157 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2158 match res {
2159 Ok(r @ Datum::Range(..)) => Ok(r.unwrap_range()),
2160 _ => Err(res),
2161 }
2162 }
2163
2164 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2165 let d =
2166 self.into_bounds(|bound| temp_storage.make_datum_nested(|packer| packer.push(bound)));
2167 Ok(Datum::Range(d))
2168 }
2169}
2170
2171impl AsColumnType for bool {
2172 fn as_column_type() -> SqlColumnType {
2173 SqlScalarType::Bool.nullable(false)
2174 }
2175}
2176
2177impl<'a, E> DatumType<'a, E> for bool {
2178 fn nullable() -> bool {
2179 false
2180 }
2181
2182 fn fallible() -> bool {
2183 false
2184 }
2185
2186 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2187 match res {
2188 Ok(Datum::True) => Ok(true),
2189 Ok(Datum::False) => Ok(false),
2190 _ => Err(res),
2191 }
2192 }
2193
2194 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2195 if self {
2196 Ok(Datum::True)
2197 } else {
2198 Ok(Datum::False)
2199 }
2200 }
2201}
2202
2203impl AsColumnType for String {
2204 fn as_column_type() -> SqlColumnType {
2205 SqlScalarType::String.nullable(false)
2206 }
2207}
2208
2209impl<'a, E> DatumType<'a, E> for String {
2210 fn nullable() -> bool {
2211 false
2212 }
2213
2214 fn fallible() -> bool {
2215 false
2216 }
2217
2218 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2219 match res {
2220 Ok(Datum::String(s)) => Ok(s.to_owned()),
2221 _ => Err(res),
2222 }
2223 }
2224
2225 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2226 Ok(Datum::String(temp_storage.push_string(self)))
2227 }
2228}
2229
2230impl AsColumnType for ArrayRustType<String> {
2231 fn as_column_type() -> SqlColumnType {
2232 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false)
2233 }
2234}
2235
2236impl<'a, E> DatumType<'a, E> for ArrayRustType<String> {
2237 fn nullable() -> bool {
2238 false
2239 }
2240
2241 fn fallible() -> bool {
2242 false
2243 }
2244
2245 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2246 match res {
2247 Ok(Datum::Array(arr)) => Ok(ArrayRustType(
2248 arr.elements()
2249 .into_iter()
2250 .map(|d| d.unwrap_str().to_string())
2251 .collect(),
2252 )),
2253 _ => Err(res),
2254 }
2255 }
2256
2257 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2258 Ok(temp_storage.make_datum(|packer| {
2259 packer
2260 .try_push_array(
2261 &[ArrayDimension {
2262 lower_bound: 1,
2263 length: self.0.len(),
2264 }],
2265 self.0.iter().map(|elem| Datum::String(elem.as_str())),
2266 )
2267 .expect("self is 1 dimensional, and its length is used for the array length");
2268 }))
2269 }
2270}
2271
2272impl AsColumnType for Vec<u8> {
2273 fn as_column_type() -> SqlColumnType {
2274 SqlScalarType::Bytes.nullable(false)
2275 }
2276}
2277
2278impl<'a, E> DatumType<'a, E> for Vec<u8> {
2279 fn nullable() -> bool {
2280 false
2281 }
2282
2283 fn fallible() -> bool {
2284 false
2285 }
2286
2287 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2288 match res {
2289 Ok(Datum::Bytes(b)) => Ok(b.to_owned()),
2290 _ => Err(res),
2291 }
2292 }
2293
2294 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2295 Ok(Datum::Bytes(temp_storage.push_bytes(self)))
2296 }
2297}
2298
2299impl AsColumnType for Numeric {
2300 fn as_column_type() -> SqlColumnType {
2301 SqlScalarType::Numeric { max_scale: None }.nullable(false)
2302 }
2303}
2304
2305impl<'a, E> DatumType<'a, E> for Numeric {
2306 fn nullable() -> bool {
2307 false
2308 }
2309
2310 fn fallible() -> bool {
2311 false
2312 }
2313
2314 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2315 match res {
2316 Ok(Datum::Numeric(n)) => Ok(n.into_inner()),
2317 _ => Err(res),
2318 }
2319 }
2320
2321 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2322 Ok(Datum::from(self))
2323 }
2324}
2325
2326impl<'a, E> DatumType<'a, E> for OrderedDecimal<Numeric> {
2327 fn nullable() -> bool {
2328 false
2329 }
2330
2331 fn fallible() -> bool {
2332 false
2333 }
2334
2335 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2336 match res {
2337 Ok(Datum::Numeric(n)) => Ok(n),
2338 _ => Err(res),
2339 }
2340 }
2341
2342 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2343 Ok(Datum::from(self))
2344 }
2345}
2346
2347impl AsColumnType for PgLegacyChar {
2348 fn as_column_type() -> SqlColumnType {
2349 SqlScalarType::PgLegacyChar.nullable(false)
2350 }
2351}
2352
2353impl<'a, E> DatumType<'a, E> for PgLegacyChar {
2354 fn nullable() -> bool {
2355 false
2356 }
2357
2358 fn fallible() -> bool {
2359 false
2360 }
2361
2362 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2363 match res {
2364 Ok(Datum::UInt8(a)) => Ok(PgLegacyChar(a)),
2365 _ => Err(res),
2366 }
2367 }
2368
2369 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2370 Ok(Datum::UInt8(self.0))
2371 }
2372}
2373
2374impl<S> AsColumnType for PgLegacyName<S>
2375where
2376 S: AsRef<str>,
2377{
2378 fn as_column_type() -> SqlColumnType {
2379 SqlScalarType::PgLegacyName.nullable(false)
2380 }
2381}
2382
2383impl<'a, E> DatumType<'a, E> for PgLegacyName<&'a str> {
2384 fn nullable() -> bool {
2385 false
2386 }
2387
2388 fn fallible() -> bool {
2389 false
2390 }
2391
2392 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2393 match res {
2394 Ok(Datum::String(a)) => Ok(PgLegacyName(a)),
2395 _ => Err(res),
2396 }
2397 }
2398
2399 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2400 Ok(Datum::String(self.0))
2401 }
2402}
2403
2404impl<'a, E> DatumType<'a, E> for PgLegacyName<String> {
2405 fn nullable() -> bool {
2406 false
2407 }
2408
2409 fn fallible() -> bool {
2410 false
2411 }
2412
2413 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2414 match res {
2415 Ok(Datum::String(a)) => Ok(PgLegacyName(a.to_owned())),
2416 _ => Err(res),
2417 }
2418 }
2419
2420 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2421 Ok(Datum::String(temp_storage.push_string(self.0)))
2422 }
2423}
2424
2425impl AsColumnType for Oid {
2426 fn as_column_type() -> SqlColumnType {
2427 SqlScalarType::Oid.nullable(false)
2428 }
2429}
2430
2431impl<'a, E> DatumType<'a, E> for Oid {
2432 fn nullable() -> bool {
2433 false
2434 }
2435
2436 fn fallible() -> bool {
2437 false
2438 }
2439
2440 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2441 match res {
2442 Ok(Datum::UInt32(a)) => Ok(Oid(a)),
2443 _ => Err(res),
2444 }
2445 }
2446
2447 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2448 Ok(Datum::UInt32(self.0))
2449 }
2450}
2451
2452impl AsColumnType for RegClass {
2453 fn as_column_type() -> SqlColumnType {
2454 SqlScalarType::RegClass.nullable(false)
2455 }
2456}
2457
2458impl<'a, E> DatumType<'a, E> for RegClass {
2459 fn nullable() -> bool {
2460 false
2461 }
2462
2463 fn fallible() -> bool {
2464 false
2465 }
2466
2467 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2468 match res {
2469 Ok(Datum::UInt32(a)) => Ok(RegClass(a)),
2470 _ => Err(res),
2471 }
2472 }
2473
2474 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2475 Ok(Datum::UInt32(self.0))
2476 }
2477}
2478
2479impl AsColumnType for RegProc {
2480 fn as_column_type() -> SqlColumnType {
2481 SqlScalarType::RegProc.nullable(false)
2482 }
2483}
2484
2485impl<'a, E> DatumType<'a, E> for RegProc {
2486 fn nullable() -> bool {
2487 false
2488 }
2489
2490 fn fallible() -> bool {
2491 false
2492 }
2493
2494 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2495 match res {
2496 Ok(Datum::UInt32(a)) => Ok(RegProc(a)),
2497 _ => Err(res),
2498 }
2499 }
2500
2501 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2502 Ok(Datum::UInt32(self.0))
2503 }
2504}
2505
2506impl AsColumnType for RegType {
2507 fn as_column_type() -> SqlColumnType {
2508 SqlScalarType::RegType.nullable(false)
2509 }
2510}
2511
2512impl<'a, E> DatumType<'a, E> for RegType {
2513 fn nullable() -> bool {
2514 false
2515 }
2516
2517 fn fallible() -> bool {
2518 false
2519 }
2520
2521 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2522 match res {
2523 Ok(Datum::UInt32(a)) => Ok(RegType(a)),
2524 _ => Err(res),
2525 }
2526 }
2527
2528 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2529 Ok(Datum::UInt32(self.0))
2530 }
2531}
2532
2533impl<S> AsColumnType for Char<S>
2534where
2535 S: AsRef<str>,
2536{
2537 fn as_column_type() -> SqlColumnType {
2538 SqlScalarType::Char { length: None }.nullable(false)
2539 }
2540}
2541
2542impl<'a, E> DatumType<'a, E> for Char<&'a str> {
2543 fn nullable() -> bool {
2544 false
2545 }
2546
2547 fn fallible() -> bool {
2548 false
2549 }
2550
2551 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2552 match res {
2553 Ok(Datum::String(a)) => Ok(Char(a)),
2554 _ => Err(res),
2555 }
2556 }
2557
2558 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2559 Ok(Datum::String(self.0))
2560 }
2561}
2562
2563impl<'a, E> DatumType<'a, E> for Char<String> {
2564 fn nullable() -> bool {
2565 false
2566 }
2567
2568 fn fallible() -> bool {
2569 false
2570 }
2571
2572 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2573 match res {
2574 Ok(Datum::String(a)) => Ok(Char(a.to_owned())),
2575 _ => Err(res),
2576 }
2577 }
2578
2579 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2580 Ok(Datum::String(temp_storage.push_string(self.0)))
2581 }
2582}
2583
2584impl<S> AsColumnType for VarChar<S>
2585where
2586 S: AsRef<str>,
2587{
2588 fn as_column_type() -> SqlColumnType {
2589 SqlScalarType::Char { length: None }.nullable(false)
2590 }
2591}
2592
2593impl<'a, E> DatumType<'a, E> for VarChar<&'a str> {
2594 fn nullable() -> bool {
2595 false
2596 }
2597
2598 fn fallible() -> bool {
2599 false
2600 }
2601
2602 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2603 match res {
2604 Ok(Datum::String(a)) => Ok(VarChar(a)),
2605 _ => Err(res),
2606 }
2607 }
2608
2609 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2610 Ok(Datum::String(self.0))
2611 }
2612}
2613
2614impl<'a, E> DatumType<'a, E> for VarChar<String> {
2615 fn nullable() -> bool {
2616 false
2617 }
2618
2619 fn fallible() -> bool {
2620 false
2621 }
2622
2623 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2624 match res {
2625 Ok(Datum::String(a)) => Ok(VarChar(a.to_owned())),
2626 _ => Err(res),
2627 }
2628 }
2629
2630 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2631 Ok(Datum::String(temp_storage.push_string(self.0)))
2632 }
2633}
2634
2635impl<'a, E> DatumType<'a, E> for Jsonb {
2636 fn nullable() -> bool {
2637 false
2638 }
2639
2640 fn fallible() -> bool {
2641 false
2642 }
2643
2644 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2645 Ok(JsonbRef::try_from_result(res)?.to_owned())
2646 }
2647
2648 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2649 Ok(temp_storage.push_unary_row(self.into_row()))
2650 }
2651}
2652
2653impl AsColumnType for Jsonb {
2654 fn as_column_type() -> SqlColumnType {
2655 SqlScalarType::Jsonb.nullable(false)
2656 }
2657}
2658
2659impl<'a, E> DatumType<'a, E> for JsonbRef<'a> {
2660 fn nullable() -> bool {
2661 false
2662 }
2663
2664 fn fallible() -> bool {
2665 false
2666 }
2667
2668 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2669 match res {
2670 Ok(
2671 d @ (Datum::JsonNull
2672 | Datum::True
2673 | Datum::False
2674 | Datum::Numeric(_)
2675 | Datum::String(_)
2676 | Datum::List(_)
2677 | Datum::Map(_)),
2678 ) => Ok(JsonbRef::from_datum(d)),
2679 _ => Err(res),
2680 }
2681 }
2682
2683 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2684 Ok(self.into_datum())
2685 }
2686}
2687
2688impl<'a> AsColumnType for JsonbRef<'a> {
2689 fn as_column_type() -> SqlColumnType {
2690 SqlScalarType::Jsonb.nullable(false)
2691 }
2692}
2693
2694impl AsColumnType for MzAclItem {
2695 fn as_column_type() -> SqlColumnType {
2696 SqlScalarType::MzAclItem.nullable(false)
2697 }
2698}
2699
2700impl<'a, E> DatumType<'a, E> for MzAclItem {
2701 fn nullable() -> bool {
2702 false
2703 }
2704
2705 fn fallible() -> bool {
2706 false
2707 }
2708
2709 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2710 match res {
2711 Ok(Datum::MzAclItem(mz_acl_item)) => Ok(mz_acl_item),
2712 _ => Err(res),
2713 }
2714 }
2715
2716 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2717 Ok(Datum::MzAclItem(self))
2718 }
2719}
2720
2721impl AsColumnType for AclItem {
2722 fn as_column_type() -> SqlColumnType {
2723 SqlScalarType::AclItem.nullable(false)
2724 }
2725}
2726
2727impl<'a, E> DatumType<'a, E> for AclItem {
2728 fn nullable() -> bool {
2729 false
2730 }
2731
2732 fn fallible() -> bool {
2733 false
2734 }
2735
2736 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2737 match res {
2738 Ok(Datum::AclItem(acl_item)) => Ok(acl_item),
2739 _ => Err(res),
2740 }
2741 }
2742
2743 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2744 Ok(Datum::AclItem(self))
2745 }
2746}
2747
2748impl AsColumnType for CheckedTimestamp<NaiveDateTime> {
2749 fn as_column_type() -> SqlColumnType {
2750 SqlScalarType::Timestamp { precision: None }.nullable(false)
2751 }
2752}
2753
2754impl<'a, E> DatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
2755 fn nullable() -> bool {
2756 false
2757 }
2758
2759 fn fallible() -> bool {
2760 false
2761 }
2762
2763 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2764 match res {
2765 Ok(Datum::Timestamp(a)) => Ok(a),
2766 _ => Err(res),
2767 }
2768 }
2769
2770 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2771 Ok(Datum::Timestamp(self))
2772 }
2773}
2774
2775impl AsColumnType for CheckedTimestamp<DateTime<Utc>> {
2776 fn as_column_type() -> SqlColumnType {
2777 SqlScalarType::TimestampTz { precision: None }.nullable(false)
2778 }
2779}
2780
2781impl<'a, E> DatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
2782 fn nullable() -> bool {
2783 false
2784 }
2785
2786 fn fallible() -> bool {
2787 false
2788 }
2789
2790 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2791 match res {
2792 Ok(Datum::TimestampTz(a)) => Ok(a),
2793 _ => Err(res),
2794 }
2795 }
2796
2797 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2798 Ok(Datum::TimestampTz(self))
2799 }
2800}
2801
2802impl SqlScalarType {
2803 pub fn unwrap_numeric_max_scale(&self) -> Option<NumericMaxScale> {
2809 match self {
2810 SqlScalarType::Numeric { max_scale } => *max_scale,
2811 _ => panic!("SqlScalarType::unwrap_numeric_scale called on {:?}", self),
2812 }
2813 }
2814
2815 pub fn unwrap_timestamp_precision(&self) -> Option<TimestampPrecision> {
2822 match self {
2823 SqlScalarType::Timestamp { precision } | SqlScalarType::TimestampTz { precision } => {
2824 *precision
2825 }
2826 _ => panic!(
2827 "SqlScalarType::unwrap_timestamp_precision called on {:?}",
2828 self
2829 ),
2830 }
2831 }
2832
2833 pub fn unwrap_list_element_type(&self) -> &SqlScalarType {
2839 match self {
2840 SqlScalarType::List { element_type, .. } => element_type,
2841 _ => panic!(
2842 "SqlScalarType::unwrap_list_element_type called on {:?}",
2843 self
2844 ),
2845 }
2846 }
2847
2848 pub fn unwrap_list_nth_layer_type(&self, layer: usize) -> &SqlScalarType {
2861 if layer == 0 {
2862 return self;
2863 }
2864 match self {
2865 SqlScalarType::List { element_type, .. } => {
2866 element_type.unwrap_list_nth_layer_type(layer - 1)
2867 }
2868 _ => panic!(
2869 "SqlScalarType::unwrap_list_nth_layer_type called on {:?}",
2870 self
2871 ),
2872 }
2873 }
2874
2875 pub fn unwrap_record_element_type(&self) -> Vec<&SqlScalarType> {
2881 match self {
2882 SqlScalarType::Record { fields, .. } => {
2883 fields.iter().map(|(_, t)| &t.scalar_type).collect_vec()
2884 }
2885 _ => panic!(
2886 "SqlScalarType::unwrap_record_element_type called on {:?}",
2887 self
2888 ),
2889 }
2890 }
2891
2892 pub fn unwrap_record_element_column_type(&self) -> Vec<&SqlColumnType> {
2898 match self {
2899 SqlScalarType::Record { fields, .. } => fields.iter().map(|(_, t)| t).collect_vec(),
2900 _ => panic!(
2901 "SqlScalarType::unwrap_record_element_column_type called on {:?}",
2902 self
2903 ),
2904 }
2905 }
2906
2907 pub fn unwrap_list_n_layers(&self) -> usize {
2914 let mut descender = self.unwrap_list_element_type();
2915 let mut layers = 1;
2916
2917 while let SqlScalarType::List { element_type, .. } = descender {
2918 layers += 1;
2919 descender = element_type;
2920 }
2921
2922 layers
2923 }
2924
2925 pub fn without_modifiers(&self) -> SqlScalarType {
2929 use SqlScalarType::*;
2930 match self {
2931 List {
2932 element_type,
2933 custom_id: None,
2934 } => List {
2935 element_type: Box::new(element_type.without_modifiers()),
2936 custom_id: None,
2937 },
2938 Map {
2939 value_type,
2940 custom_id: None,
2941 } => Map {
2942 value_type: Box::new(value_type.without_modifiers()),
2943 custom_id: None,
2944 },
2945 Record {
2946 fields,
2947 custom_id: None,
2948 } => {
2949 let fields = fields
2950 .iter()
2951 .map(|(column_name, column_type)| {
2952 (
2953 column_name.clone(),
2954 SqlColumnType {
2955 scalar_type: column_type.scalar_type.without_modifiers(),
2956 nullable: column_type.nullable,
2957 },
2958 )
2959 })
2960 .collect();
2961 Record {
2962 fields,
2963 custom_id: None,
2964 }
2965 }
2966 Array(a) => Array(Box::new(a.without_modifiers())),
2967 Numeric { .. } => Numeric { max_scale: None },
2968 Char { .. } => Char { length: None },
2971 VarChar { .. } => VarChar { max_length: None },
2972 Range { element_type } => Range {
2973 element_type: Box::new(element_type.without_modifiers()),
2974 },
2975 v => v.clone(),
2976 }
2977 }
2978
2979 pub fn unwrap_array_element_type(&self) -> &SqlScalarType {
2988 match self {
2989 SqlScalarType::Array(s) => &**s,
2990 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
2991 _ => panic!(
2992 "SqlScalarType::unwrap_array_element_type called on {:?}",
2993 self
2994 ),
2995 }
2996 }
2997
2998 pub fn unwrap_collection_element_type(&self) -> &SqlScalarType {
3006 match self {
3007 SqlScalarType::Array(element_type) => element_type,
3008 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3009 SqlScalarType::List { element_type, .. } => element_type,
3010 _ => panic!(
3011 "SqlScalarType::unwrap_collection_element_type called on {:?}",
3012 self
3013 ),
3014 }
3015 }
3016
3017 pub fn unwrap_map_value_type(&self) -> &SqlScalarType {
3023 match self {
3024 SqlScalarType::Map { value_type, .. } => &**value_type,
3025 _ => panic!("SqlScalarType::unwrap_map_value_type called on {:?}", self),
3026 }
3027 }
3028
3029 pub fn unwrap_char_length(&self) -> Option<CharLength> {
3035 match self {
3036 SqlScalarType::Char { length, .. } => *length,
3037 _ => panic!("SqlScalarType::unwrap_char_length called on {:?}", self),
3038 }
3039 }
3040
3041 pub fn unwrap_varchar_max_length(&self) -> Option<VarCharMaxLength> {
3047 match self {
3048 SqlScalarType::VarChar { max_length, .. } => *max_length,
3049 _ => panic!(
3050 "SqlScalarType::unwrap_varchar_max_length called on {:?}",
3051 self
3052 ),
3053 }
3054 }
3055
3056 pub fn unwrap_range_element_type(&self) -> &SqlScalarType {
3062 match self {
3063 SqlScalarType::Range { element_type } => &**element_type,
3064 _ => panic!(
3065 "SqlScalarType::unwrap_range_element_type called on {:?}",
3066 self
3067 ),
3068 }
3069 }
3070
3071 pub fn near_match(&self) -> Option<&'static SqlScalarType> {
3095 match self {
3096 SqlScalarType::UInt16 => Some(&SqlScalarType::Int32),
3097 SqlScalarType::UInt32 => Some(&SqlScalarType::Int64),
3098 SqlScalarType::UInt64 => Some(&SqlScalarType::Numeric { max_scale: None }),
3099 _ => None,
3100 }
3101 }
3102
3103 pub const fn nullable(self, nullable: bool) -> SqlColumnType {
3106 SqlColumnType {
3107 nullable,
3108 scalar_type: self,
3109 }
3110 }
3111
3112 pub fn is_vec(&self) -> bool {
3116 matches!(
3117 self,
3118 SqlScalarType::Array(_) | SqlScalarType::Int2Vector | SqlScalarType::List { .. }
3119 )
3120 }
3121
3122 pub fn is_custom_type(&self) -> bool {
3123 use SqlScalarType::*;
3124 match self {
3125 List {
3126 element_type: t,
3127 custom_id,
3128 }
3129 | Map {
3130 value_type: t,
3131 custom_id,
3132 } => custom_id.is_some() || t.is_custom_type(),
3133 Record {
3134 fields, custom_id, ..
3135 } => {
3136 custom_id.is_some()
3137 || fields
3138 .iter()
3139 .map(|(_, t)| t)
3140 .any(|t| t.scalar_type.is_custom_type())
3141 }
3142 _ => false,
3143 }
3144 }
3145
3146 pub fn base_eq(&self, other: &SqlScalarType) -> bool {
3159 self.eq_inner(other, false)
3160 }
3161
3162 pub fn structural_eq(&self, other: &SqlScalarType) -> bool {
3165 self.eq_inner(other, true)
3166 }
3167
3168 pub fn eq_inner(&self, other: &SqlScalarType, structure_only: bool) -> bool {
3169 use SqlScalarType::*;
3170 match (self, other) {
3171 (
3172 List {
3173 element_type: l,
3174 custom_id: oid_l,
3175 },
3176 List {
3177 element_type: r,
3178 custom_id: oid_r,
3179 },
3180 )
3181 | (
3182 Map {
3183 value_type: l,
3184 custom_id: oid_l,
3185 },
3186 Map {
3187 value_type: r,
3188 custom_id: oid_r,
3189 },
3190 ) => l.eq_inner(r, structure_only) && (oid_l == oid_r || structure_only),
3191 (Array(a), Array(b)) | (Range { element_type: a }, Range { element_type: b }) => {
3192 a.eq_inner(b, structure_only)
3193 }
3194 (
3195 Record {
3196 fields: fields_a,
3197 custom_id: oid_a,
3198 },
3199 Record {
3200 fields: fields_b,
3201 custom_id: oid_b,
3202 },
3203 ) => {
3204 (oid_a == oid_b || structure_only)
3205 && fields_a.len() == fields_b.len()
3206 && fields_a
3207 .iter()
3208 .zip_eq(fields_b)
3209 .all(|(a, b)| {
3211 (a.0 == b.0 || structure_only)
3212 && a.1.scalar_type.eq_inner(&b.1.scalar_type, structure_only)
3213 })
3214 }
3215 (s, o) => ScalarBaseType::from(s) == ScalarBaseType::from(o),
3216 }
3217 }
3218
3219 pub fn interesting_datums(&self) -> impl Iterator<Item = Datum<'static>> {
3221 static BOOL: LazyLock<Row> =
3227 LazyLock::new(|| Row::pack_slice(&[Datum::True, Datum::False]));
3228 static INT16: LazyLock<Row> = LazyLock::new(|| {
3229 Row::pack_slice(&[
3230 Datum::Int16(0),
3231 Datum::Int16(1),
3232 Datum::Int16(-1),
3233 Datum::Int16(i16::MIN),
3234 Datum::Int16(i16::MIN + 1),
3235 Datum::Int16(i16::MAX),
3236 Datum::Int16(127),
3244 Datum::Int16(128),
3245 ])
3246 });
3247 static INT32: LazyLock<Row> = LazyLock::new(|| {
3248 Row::pack_slice(&[
3249 Datum::Int32(0),
3250 Datum::Int32(1),
3251 Datum::Int32(-1),
3252 Datum::Int32(i32::MIN),
3253 Datum::Int32(i32::MIN + 1),
3254 Datum::Int32(i32::MAX),
3255 Datum::Int32(32767),
3259 Datum::Int32(32768),
3260 ])
3261 });
3262 static INT64: LazyLock<Row> = LazyLock::new(|| {
3263 Row::pack_slice(&[
3264 Datum::Int64(0),
3265 Datum::Int64(1),
3266 Datum::Int64(-1),
3267 Datum::Int64(i64::MIN),
3268 Datum::Int64(i64::MIN + 1),
3269 Datum::Int64(i64::MAX),
3270 Datum::Int64(2147483647),
3274 Datum::Int64(2147483648),
3275 ])
3276 });
3277 static UINT16: LazyLock<Row> = LazyLock::new(|| {
3278 Row::pack_slice(&[
3279 Datum::UInt16(0),
3280 Datum::UInt16(1),
3281 Datum::UInt16(u16::MAX),
3282 Datum::UInt16(255),
3286 Datum::UInt16(256),
3287 ])
3288 });
3289 static UINT32: LazyLock<Row> = LazyLock::new(|| {
3290 Row::pack_slice(&[
3291 Datum::UInt32(0),
3292 Datum::UInt32(1),
3293 Datum::UInt32(u32::MAX),
3294 Datum::UInt32(32767),
3298 Datum::UInt32(32768),
3299 ])
3300 });
3301 static UINT64: LazyLock<Row> = LazyLock::new(|| {
3302 Row::pack_slice(&[
3303 Datum::UInt64(0),
3304 Datum::UInt64(1),
3305 Datum::UInt64(u64::MAX),
3306 Datum::UInt64(2147483647),
3310 Datum::UInt64(2147483648),
3311 ])
3312 });
3313 static FLOAT32: LazyLock<Row> = LazyLock::new(|| {
3314 Row::pack_slice(&[
3315 Datum::Float32(OrderedFloat(0.0)),
3316 Datum::Float32(OrderedFloat(1.0)),
3317 Datum::Float32(OrderedFloat(-1.0)),
3318 Datum::Float32(OrderedFloat(f32::MIN)),
3319 Datum::Float32(OrderedFloat(f32::MIN_POSITIVE)),
3320 Datum::Float32(OrderedFloat(f32::MAX)),
3321 Datum::Float32(OrderedFloat(f32::EPSILON)),
3322 Datum::Float32(OrderedFloat(f32::NAN)),
3323 Datum::Float32(OrderedFloat(f32::INFINITY)),
3324 Datum::Float32(OrderedFloat(f32::NEG_INFINITY)),
3325 ])
3326 });
3327 static FLOAT64: LazyLock<Row> = LazyLock::new(|| {
3328 Row::pack_slice(&[
3329 Datum::Float64(OrderedFloat(0.0)),
3330 Datum::Float64(OrderedFloat(1.0)),
3331 Datum::Float64(OrderedFloat(-1.0)),
3332 Datum::Float64(OrderedFloat(f64::MIN)),
3333 Datum::Float64(OrderedFloat(f64::MIN_POSITIVE)),
3334 Datum::Float64(OrderedFloat(f64::MAX)),
3335 Datum::Float64(OrderedFloat(f64::EPSILON)),
3336 Datum::Float64(OrderedFloat(f64::NAN)),
3337 Datum::Float64(OrderedFloat(f64::INFINITY)),
3338 Datum::Float64(OrderedFloat(f64::NEG_INFINITY)),
3339 ])
3340 });
3341 static NUMERIC: LazyLock<Row> = LazyLock::new(|| {
3342 cfg_if::cfg_if! {
3343 if #[cfg(miri)] {
3345 Row::pack_slice(&[])
3346 } else {
3347 Row::pack_slice(&[
3348 Datum::Numeric(OrderedDecimal(Numeric::from(0.0))),
3349 Datum::Numeric(OrderedDecimal(Numeric::from(1.0))),
3350 Datum::Numeric(OrderedDecimal(Numeric::from(-1.0))),
3351 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN))),
3352 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN_POSITIVE))),
3353 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MAX))),
3354 Datum::Numeric(OrderedDecimal(Numeric::from(f64::EPSILON))),
3355 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NAN))),
3356 Datum::Numeric(OrderedDecimal(Numeric::from(f64::INFINITY))),
3357 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NEG_INFINITY))),
3358 ])
3359 }
3360 }
3361 });
3362 static DATE: LazyLock<Row> = LazyLock::new(|| {
3363 Row::pack_slice(&[
3364 Datum::Date(Date::from_pg_epoch(0).unwrap()),
3365 Datum::Date(Date::from_pg_epoch(Date::LOW_DAYS).unwrap()),
3366 Datum::Date(Date::from_pg_epoch(Date::HIGH_DAYS).unwrap()),
3367 ])
3368 });
3369 static TIME: LazyLock<Row> = LazyLock::new(|| {
3370 Row::pack_slice(&[
3371 Datum::Time(NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap()),
3372 Datum::Time(NaiveTime::from_hms_micro_opt(23, 59, 59, 999_999).unwrap()),
3373 ])
3374 });
3375 static TIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3376 Row::pack_slice(&[
3377 Datum::Timestamp(
3378 DateTime::from_timestamp(0, 0)
3379 .unwrap()
3380 .naive_utc()
3381 .try_into()
3382 .unwrap(),
3383 ),
3384 Datum::Timestamp(
3385 crate::adt::timestamp::LOW_DATE
3386 .and_hms_opt(0, 0, 0)
3387 .unwrap()
3388 .try_into()
3389 .unwrap(),
3390 ),
3391 Datum::Timestamp(
3392 crate::adt::timestamp::HIGH_DATE
3393 .and_hms_opt(23, 59, 59)
3394 .unwrap()
3395 .try_into()
3396 .unwrap(),
3397 ),
3398 Datum::Timestamp(
3400 DateTime::from_timestamp(0, 123456789)
3401 .unwrap()
3402 .naive_utc()
3403 .try_into()
3404 .unwrap(),
3405 ),
3406 Datum::Timestamp(
3408 CheckedTimestamp::from_timestamplike(
3409 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
3410 .unwrap()
3411 .and_hms_milli_opt(23, 59, 59, 1234)
3412 .unwrap(),
3413 )
3414 .unwrap(),
3415 ),
3416 ])
3417 });
3418 static TIMESTAMPTZ: LazyLock<Row> = LazyLock::new(|| {
3419 Row::pack_slice(&[
3420 Datum::TimestampTz(DateTime::from_timestamp(0, 0).unwrap().try_into().unwrap()),
3421 Datum::TimestampTz(
3422 DateTime::from_naive_utc_and_offset(
3423 crate::adt::timestamp::LOW_DATE
3424 .and_hms_opt(0, 0, 0)
3425 .unwrap(),
3426 Utc,
3427 )
3428 .try_into()
3429 .unwrap(),
3430 ),
3431 Datum::TimestampTz(
3432 DateTime::from_naive_utc_and_offset(
3433 crate::adt::timestamp::HIGH_DATE
3434 .and_hms_opt(23, 59, 59)
3435 .unwrap(),
3436 Utc,
3437 )
3438 .try_into()
3439 .unwrap(),
3440 ),
3441 Datum::TimestampTz(
3443 DateTime::from_timestamp(0, 123456789)
3444 .unwrap()
3445 .try_into()
3446 .unwrap(),
3447 ),
3448 ])
3449 });
3450 static INTERVAL: LazyLock<Row> = LazyLock::new(|| {
3451 Row::pack_slice(&[
3452 Datum::Interval(Interval::new(0, 0, 0)),
3453 Datum::Interval(Interval::new(1, 1, 1)),
3454 Datum::Interval(Interval::new(-1, -1, -1)),
3455 Datum::Interval(Interval::new(1, 0, 0)),
3456 Datum::Interval(Interval::new(0, 1, 0)),
3457 Datum::Interval(Interval::new(0, 0, 1)),
3458 Datum::Interval(Interval::new(-1, 0, 0)),
3459 Datum::Interval(Interval::new(0, -1, 0)),
3460 Datum::Interval(Interval::new(0, 0, -1)),
3461 Datum::Interval(Interval::new(i32::MIN, i32::MIN, i64::MIN)),
3462 Datum::Interval(Interval::new(i32::MAX, i32::MAX, i64::MAX)),
3463 Datum::Interval(Interval::new(i32::MIN, 0, 0)),
3464 Datum::Interval(Interval::new(i32::MAX, 0, 0)),
3465 Datum::Interval(Interval::new(0, i32::MIN, 0)),
3466 Datum::Interval(Interval::new(0, i32::MAX, 0)),
3467 Datum::Interval(Interval::new(0, 0, i64::MIN)),
3468 Datum::Interval(Interval::new(0, 0, i64::MAX)),
3469 ])
3470 });
3471 static PGLEGACYCHAR: LazyLock<Row> =
3472 LazyLock::new(|| Row::pack_slice(&[Datum::UInt8(u8::MIN), Datum::UInt8(u8::MAX)]));
3473 static PGLEGACYNAME: LazyLock<Row> = LazyLock::new(|| {
3474 Row::pack_slice(&[
3475 Datum::String(""),
3476 Datum::String(" "),
3477 Datum::String("'"),
3478 Datum::String("\""),
3479 Datum::String("."),
3480 Datum::String(&"x".repeat(64)),
3481 ])
3482 });
3483 static BYTES: LazyLock<Row> = LazyLock::new(|| {
3484 Row::pack_slice(&[Datum::Bytes(&[]), Datum::Bytes(&[0]), Datum::Bytes(&[255])])
3485 });
3486 static STRING: LazyLock<Row> = LazyLock::new(|| {
3487 Row::pack_slice(&[
3488 Datum::String(""),
3489 Datum::String(" "),
3490 Datum::String("'"),
3491 Datum::String("\""),
3492 Datum::String("."),
3493 Datum::String("2015-09-18T23:56:04.123Z"),
3494 Datum::String(&"x".repeat(100)),
3495 Datum::String("JAPAN"),
3497 Datum::String("1,2,3"),
3498 Datum::String("\r\n"),
3499 Datum::String("\"\""),
3500 ])
3501 });
3502 static CHAR: LazyLock<Row> = LazyLock::new(|| {
3503 Row::pack_slice(&[
3504 Datum::String(" "),
3505 Datum::String("'"),
3506 Datum::String("\""),
3507 Datum::String("."),
3508 Datum::String(","),
3509 Datum::String("\t"),
3510 Datum::String("\n"),
3511 Datum::String("\r"),
3512 Datum::String("\\"),
3513 Datum::String(std::str::from_utf8(b"\x00").unwrap()),
3515 Datum::String(std::str::from_utf8(b"\x02").unwrap()),
3517 Datum::String(std::str::from_utf8(b"\x03").unwrap()),
3519 Datum::String(std::str::from_utf8(b"\x08").unwrap()),
3521 Datum::String(std::str::from_utf8(b"\x1B").unwrap()),
3523 Datum::String(std::str::from_utf8(b"\x7F").unwrap()),
3525 ])
3526 });
3527 static JSONB: LazyLock<Row> = LazyLock::new(|| {
3528 let mut datums = vec![Datum::True, Datum::False, Datum::JsonNull];
3529 datums.extend(STRING.iter());
3530 datums.extend(NUMERIC.iter().filter(|n| {
3531 let Datum::Numeric(n) = n else {
3532 panic!("expected Numeric, found {n:?}");
3533 };
3534 !(n.0.is_nan() || n.0.is_infinite())
3536 }));
3537 Row::pack_slice(&datums)
3539 });
3540 static UUID: LazyLock<Row> = LazyLock::new(|| {
3541 Row::pack_slice(&[
3542 Datum::Uuid(Uuid::from_u128(u128::MIN)),
3543 Datum::Uuid(Uuid::from_u128(u128::MAX)),
3544 ])
3545 });
3546 static ARRAY: LazyLock<BTreeMap<&'static SqlScalarType, Row>> = LazyLock::new(|| {
3547 let generate_row = |inner_type: &SqlScalarType| {
3548 let datums: Vec<_> = inner_type.interesting_datums().collect();
3549
3550 let mut row = Row::default();
3551 row.packer()
3552 .try_push_array::<_, Datum<'static>>(
3553 &[ArrayDimension {
3554 lower_bound: 1,
3555 length: 0,
3556 }],
3557 [],
3558 )
3559 .expect("failed to push empty array");
3560 row.packer()
3561 .try_push_array(
3562 &[ArrayDimension {
3563 lower_bound: 1,
3564 length: datums.len(),
3565 }],
3566 datums,
3567 )
3568 .expect("failed to push array");
3569
3570 row
3571 };
3572
3573 SqlScalarType::enumerate()
3574 .into_iter()
3575 .filter(|ty| !matches!(ty, SqlScalarType::Array(_)))
3576 .map(|ty| (ty, generate_row(ty)))
3577 .collect()
3578 });
3579 static EMPTY_ARRAY: LazyLock<Row> = LazyLock::new(|| {
3580 let mut row = Row::default();
3581 row.packer()
3582 .try_push_array::<_, Datum<'static>>(
3583 &[ArrayDimension {
3584 lower_bound: 1,
3585 length: 0,
3586 }],
3587 [],
3588 )
3589 .expect("failed to push empty array");
3590 row
3591 });
3592 static LIST: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3593 static RECORD: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3594 static OID: LazyLock<Row> =
3595 LazyLock::new(|| Row::pack_slice(&[Datum::UInt32(u32::MIN), Datum::UInt32(u32::MAX)]));
3596 static MAP: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3597 static INT2VECTOR: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3598 static MZTIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3599 Row::pack_slice(&[
3600 Datum::MzTimestamp(crate::Timestamp::MIN),
3601 Datum::MzTimestamp(crate::Timestamp::MAX),
3602 ])
3603 });
3604 static RANGE: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3605 static MZACLITEM: LazyLock<Row> = LazyLock::new(|| {
3606 Row::pack_slice(&[
3607 Datum::MzAclItem(MzAclItem {
3608 grantee: RoleId::Public,
3609 grantor: RoleId::Public,
3610 acl_mode: AclMode::empty(),
3611 }),
3612 Datum::MzAclItem(MzAclItem {
3613 grantee: RoleId::Public,
3614 grantor: RoleId::Public,
3615 acl_mode: AclMode::all(),
3616 }),
3617 Datum::MzAclItem(MzAclItem {
3618 grantee: RoleId::User(42),
3619 grantor: RoleId::Public,
3620 acl_mode: AclMode::empty(),
3621 }),
3622 Datum::MzAclItem(MzAclItem {
3623 grantee: RoleId::User(42),
3624 grantor: RoleId::Public,
3625 acl_mode: AclMode::all(),
3626 }),
3627 Datum::MzAclItem(MzAclItem {
3628 grantee: RoleId::Public,
3629 grantor: RoleId::User(42),
3630 acl_mode: AclMode::empty(),
3631 }),
3632 Datum::MzAclItem(MzAclItem {
3633 grantee: RoleId::Public,
3634 grantor: RoleId::User(42),
3635 acl_mode: AclMode::all(),
3636 }),
3637 ])
3638 });
3639 static ACLITEM: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3641
3642 let iter: Box<dyn Iterator<Item = Datum<'static>>> = match self {
3643 SqlScalarType::Bool => Box::new((*BOOL).iter()),
3644 SqlScalarType::Int16 => Box::new((*INT16).iter()),
3645 SqlScalarType::Int32 => Box::new((*INT32).iter()),
3646 SqlScalarType::Int64 => Box::new((*INT64).iter()),
3647 SqlScalarType::UInt16 => Box::new((*UINT16).iter()),
3648 SqlScalarType::UInt32 => Box::new((*UINT32).iter()),
3649 SqlScalarType::UInt64 => Box::new((*UINT64).iter()),
3650 SqlScalarType::Float32 => Box::new((*FLOAT32).iter()),
3651 SqlScalarType::Float64 => Box::new((*FLOAT64).iter()),
3652 SqlScalarType::Numeric { .. } => Box::new((*NUMERIC).iter()),
3653 SqlScalarType::Date => Box::new((*DATE).iter()),
3654 SqlScalarType::Time => Box::new((*TIME).iter()),
3655 SqlScalarType::Timestamp { .. } => Box::new((*TIMESTAMP).iter()),
3656 SqlScalarType::TimestampTz { .. } => Box::new((*TIMESTAMPTZ).iter()),
3657 SqlScalarType::Interval => Box::new((*INTERVAL).iter()),
3658 SqlScalarType::PgLegacyChar => Box::new((*PGLEGACYCHAR).iter()),
3659 SqlScalarType::PgLegacyName => Box::new((*PGLEGACYNAME).iter()),
3660 SqlScalarType::Bytes => Box::new((*BYTES).iter()),
3661 SqlScalarType::String => Box::new((*STRING).iter().chain((*CHAR).iter())),
3662 SqlScalarType::Char { .. } => Box::new((*CHAR).iter()),
3663 SqlScalarType::VarChar { .. } => Box::new((*STRING).iter().chain((*CHAR).iter())),
3664 SqlScalarType::Jsonb => Box::new((*JSONB).iter()),
3665 SqlScalarType::Uuid => Box::new((*UUID).iter()),
3666 SqlScalarType::Array(inner_type) => {
3667 if matches!(inner_type.as_ref(), SqlScalarType::Array(_)) {
3668 panic!("SqlScalarType::Array cannot have a nested Array");
3669 }
3670
3671 Box::new(
3672 (*ARRAY)
3673 .get(inner_type.as_ref())
3674 .unwrap_or(&*EMPTY_ARRAY)
3675 .iter(),
3676 )
3677 }
3678 SqlScalarType::List { .. } => Box::new((*LIST).iter()),
3679 SqlScalarType::Record { .. } => Box::new((*RECORD).iter()),
3680 SqlScalarType::Oid => Box::new((*OID).iter()),
3681 SqlScalarType::Map { .. } => Box::new((*MAP).iter()),
3682 SqlScalarType::RegProc => Box::new((*OID).iter()),
3683 SqlScalarType::RegType => Box::new((*OID).iter()),
3684 SqlScalarType::RegClass => Box::new((*OID).iter()),
3685 SqlScalarType::Int2Vector => Box::new((*INT2VECTOR).iter()),
3686 SqlScalarType::MzTimestamp => Box::new((*MZTIMESTAMP).iter()),
3687 SqlScalarType::Range { .. } => Box::new((*RANGE).iter()),
3688 SqlScalarType::MzAclItem { .. } => Box::new((*MZACLITEM).iter()),
3689 SqlScalarType::AclItem { .. } => Box::new((*ACLITEM).iter()),
3690 };
3691
3692 iter
3693 }
3694
3695 pub fn enumerate() -> &'static [Self] {
3698 &[
3701 SqlScalarType::Bool,
3702 SqlScalarType::Int16,
3703 SqlScalarType::Int32,
3704 SqlScalarType::Int64,
3705 SqlScalarType::UInt16,
3706 SqlScalarType::UInt32,
3707 SqlScalarType::UInt64,
3708 SqlScalarType::Float32,
3709 SqlScalarType::Float64,
3710 SqlScalarType::Numeric {
3711 max_scale: Some(NumericMaxScale(
3712 crate::adt::numeric::NUMERIC_DATUM_MAX_PRECISION,
3713 )),
3714 },
3715 SqlScalarType::Date,
3716 SqlScalarType::Time,
3717 SqlScalarType::Timestamp {
3718 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3719 },
3720 SqlScalarType::Timestamp {
3721 precision: Some(TimestampPrecision(0)),
3722 },
3723 SqlScalarType::Timestamp { precision: None },
3724 SqlScalarType::TimestampTz {
3725 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3726 },
3727 SqlScalarType::TimestampTz {
3728 precision: Some(TimestampPrecision(0)),
3729 },
3730 SqlScalarType::TimestampTz { precision: None },
3731 SqlScalarType::Interval,
3732 SqlScalarType::PgLegacyChar,
3733 SqlScalarType::Bytes,
3734 SqlScalarType::String,
3735 SqlScalarType::Char {
3736 length: Some(CharLength(1)),
3737 },
3738 SqlScalarType::VarChar { max_length: None },
3739 SqlScalarType::Jsonb,
3740 SqlScalarType::Uuid,
3741 SqlScalarType::Oid,
3742 SqlScalarType::RegProc,
3743 SqlScalarType::RegType,
3744 SqlScalarType::RegClass,
3745 SqlScalarType::Int2Vector,
3746 SqlScalarType::MzTimestamp,
3747 SqlScalarType::MzAclItem,
3748 ]
3769 }
3770
3771 pub fn array_of_self_elem_type(self) -> Result<SqlScalarType, SqlScalarType> {
3776 match self {
3777 t @ (SqlScalarType::AclItem
3778 | SqlScalarType::Bool
3779 | SqlScalarType::Int16
3780 | SqlScalarType::Int32
3781 | SqlScalarType::Int64
3782 | SqlScalarType::UInt16
3783 | SqlScalarType::UInt32
3784 | SqlScalarType::UInt64
3785 | SqlScalarType::Float32
3786 | SqlScalarType::Float64
3787 | SqlScalarType::Numeric { .. }
3788 | SqlScalarType::Date
3789 | SqlScalarType::Time
3790 | SqlScalarType::Timestamp { .. }
3791 | SqlScalarType::TimestampTz { .. }
3792 | SqlScalarType::Interval
3793 | SqlScalarType::PgLegacyChar
3794 | SqlScalarType::PgLegacyName
3795 | SqlScalarType::Bytes
3796 | SqlScalarType::String
3797 | SqlScalarType::VarChar { .. }
3798 | SqlScalarType::Jsonb
3799 | SqlScalarType::Uuid
3800 | SqlScalarType::Record { .. }
3801 | SqlScalarType::Oid
3802 | SqlScalarType::RegProc
3803 | SqlScalarType::RegType
3804 | SqlScalarType::RegClass
3805 | SqlScalarType::Int2Vector
3806 | SqlScalarType::MzTimestamp
3807 | SqlScalarType::Range { .. }
3808 | SqlScalarType::MzAclItem { .. }) => Ok(t),
3809
3810 SqlScalarType::Array(elem) => Ok(elem.array_of_self_elem_type()?),
3811
3812 t @ (SqlScalarType::Char { .. }
3814 | SqlScalarType::Map { .. }
3816 | SqlScalarType::List { .. }) => Err(t),
3817 }
3818 }
3819}
3820
3821impl Arbitrary for SqlScalarType {
3824 type Parameters = ();
3825 type Strategy = BoxedStrategy<SqlScalarType>;
3826
3827 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
3828 let leaf = Union::new(vec![
3830 Just(SqlScalarType::Bool).boxed(),
3831 Just(SqlScalarType::UInt16).boxed(),
3832 Just(SqlScalarType::UInt32).boxed(),
3833 Just(SqlScalarType::UInt64).boxed(),
3834 Just(SqlScalarType::Int16).boxed(),
3835 Just(SqlScalarType::Int32).boxed(),
3836 Just(SqlScalarType::Int64).boxed(),
3837 Just(SqlScalarType::Float32).boxed(),
3838 Just(SqlScalarType::Float64).boxed(),
3839 any::<Option<NumericMaxScale>>()
3840 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
3841 .boxed(),
3842 Just(SqlScalarType::Date).boxed(),
3843 Just(SqlScalarType::Time).boxed(),
3844 any::<Option<TimestampPrecision>>()
3845 .prop_map(|precision| SqlScalarType::Timestamp { precision })
3846 .boxed(),
3847 any::<Option<TimestampPrecision>>()
3848 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
3849 .boxed(),
3850 Just(SqlScalarType::MzTimestamp).boxed(),
3851 Just(SqlScalarType::Interval).boxed(),
3852 Just(SqlScalarType::PgLegacyChar).boxed(),
3853 Just(SqlScalarType::Bytes).boxed(),
3854 Just(SqlScalarType::String).boxed(),
3855 any::<Option<CharLength>>()
3856 .prop_map(|length| SqlScalarType::Char { length })
3857 .boxed(),
3858 any::<Option<VarCharMaxLength>>()
3859 .prop_map(|max_length| SqlScalarType::VarChar { max_length })
3860 .boxed(),
3861 Just(SqlScalarType::PgLegacyName).boxed(),
3862 Just(SqlScalarType::Jsonb).boxed(),
3863 Just(SqlScalarType::Uuid).boxed(),
3864 Just(SqlScalarType::AclItem).boxed(),
3865 Just(SqlScalarType::MzAclItem).boxed(),
3866 Just(SqlScalarType::Oid).boxed(),
3867 Just(SqlScalarType::RegProc).boxed(),
3868 Just(SqlScalarType::RegType).boxed(),
3869 Just(SqlScalarType::RegClass).boxed(),
3870 Just(SqlScalarType::Int2Vector).boxed(),
3871 ])
3872 .no_shrink()
3875 .boxed();
3876
3877 let range_leaf = Union::new(vec![
3879 Just(SqlScalarType::Int32).boxed(),
3880 Just(SqlScalarType::Int64).boxed(),
3881 Just(SqlScalarType::Date).boxed(),
3882 any::<Option<NumericMaxScale>>()
3883 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
3884 .boxed(),
3885 any::<Option<TimestampPrecision>>()
3886 .prop_map(|precision| SqlScalarType::Timestamp { precision })
3887 .boxed(),
3888 any::<Option<TimestampPrecision>>()
3889 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
3890 .boxed(),
3891 ]);
3892 let range = range_leaf
3893 .prop_map(|inner_type| SqlScalarType::Range {
3894 element_type: Box::new(inner_type),
3895 })
3896 .boxed();
3897
3898 let array = leaf
3900 .clone()
3901 .prop_map(|inner_type| SqlScalarType::Array(Box::new(inner_type)))
3902 .boxed();
3903
3904 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
3905
3906 leaf.prop_recursive(2, 3, 5, |inner| {
3907 Union::new(vec![
3908 (inner.clone(), any::<Option<CatalogItemId>>())
3910 .prop_map(|(x, id)| SqlScalarType::List {
3911 element_type: Box::new(x),
3912 custom_id: id,
3913 })
3914 .boxed(),
3915 (inner.clone(), any::<Option<CatalogItemId>>())
3917 .prop_map(|(x, id)| SqlScalarType::Map {
3918 value_type: Box::new(x),
3919 custom_id: id,
3920 })
3921 .boxed(),
3922 {
3924 let column_type_strat =
3927 (inner, any::<bool>()).prop_map(|(scalar_type, nullable)| SqlColumnType {
3928 scalar_type,
3929 nullable,
3930 });
3931
3932 let fields_strat =
3935 prop::collection::vec((any::<ColumnName>(), column_type_strat), 0..10);
3936
3937 (fields_strat, any::<Option<CatalogItemId>>())
3939 .prop_map(|(fields, custom_id)| SqlScalarType::Record {
3940 fields: fields.into(),
3941 custom_id,
3942 })
3943 .boxed()
3944 },
3945 ])
3946 })
3947 .boxed()
3948 }
3949}
3950
3951#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash, MzReflect)]
3959pub enum ReprScalarType {
3960 Bool,
3961 Int16,
3962 Int32,
3963 Int64,
3964 UInt8, UInt16,
3966 UInt32, UInt64,
3968 Float32,
3969 Float64,
3970 Numeric,
3971 Date,
3972 Time,
3973 Timestamp {
3974 precision: Option<TimestampPrecision>,
3975 },
3976 TimestampTz {
3977 precision: Option<TimestampPrecision>,
3978 },
3979 MzTimestamp,
3980 Interval,
3981 Bytes,
3982 Jsonb,
3983 String, Uuid,
3985 Array(Box<ReprScalarType>),
3986 Int2Vector, List {
3988 element_type: Box<ReprScalarType>,
3989 },
3990 Record {
3991 fields: Box<[ReprColumnType]>,
3992 },
3993 Map {
3994 value_type: Box<ReprScalarType>,
3995 },
3996 Range {
3997 element_type: Box<ReprScalarType>,
3998 },
3999 MzAclItem,
4000 AclItem,
4001}
4002
4003impl From<SqlScalarType> for ReprScalarType {
4004 fn from(typ: SqlScalarType) -> Self {
4005 match typ {
4006 SqlScalarType::Bool => ReprScalarType::Bool,
4007 SqlScalarType::Int16 => ReprScalarType::Int16,
4008 SqlScalarType::Int32 => ReprScalarType::Int32,
4009 SqlScalarType::Int64 => ReprScalarType::Int64,
4010 SqlScalarType::UInt16 => ReprScalarType::UInt16,
4011 SqlScalarType::UInt32 => ReprScalarType::UInt32,
4012 SqlScalarType::UInt64 => ReprScalarType::UInt64,
4013 SqlScalarType::Float32 => ReprScalarType::Float32,
4014 SqlScalarType::Float64 => ReprScalarType::Float64,
4015 SqlScalarType::Numeric { max_scale: _ } => ReprScalarType::Numeric,
4016 SqlScalarType::Date => ReprScalarType::Date,
4017 SqlScalarType::Time => ReprScalarType::Time,
4018 SqlScalarType::Timestamp { precision } => ReprScalarType::Timestamp { precision },
4019 SqlScalarType::TimestampTz { precision } => ReprScalarType::TimestampTz { precision },
4020 SqlScalarType::Interval => ReprScalarType::Interval,
4021 SqlScalarType::PgLegacyChar => ReprScalarType::UInt8,
4022 SqlScalarType::PgLegacyName => ReprScalarType::String,
4023 SqlScalarType::Bytes => ReprScalarType::Bytes,
4024 SqlScalarType::String => ReprScalarType::String,
4025 SqlScalarType::Char { length: _ } => ReprScalarType::String,
4026 SqlScalarType::VarChar { max_length: _ } => ReprScalarType::String,
4027 SqlScalarType::Jsonb => ReprScalarType::Jsonb,
4028 SqlScalarType::Uuid => ReprScalarType::Uuid,
4029 SqlScalarType::Array(element_type) => {
4030 ReprScalarType::Array(Box::new((*element_type).into()))
4031 }
4032 SqlScalarType::List {
4033 element_type,
4034 custom_id: _,
4035 } => ReprScalarType::List {
4036 element_type: Box::new((*element_type).into()),
4037 },
4038 SqlScalarType::Record {
4039 fields,
4040 custom_id: _,
4041 } => ReprScalarType::Record {
4042 fields: fields.into_iter().map(|(_, typ)| typ.into()).collect(),
4043 },
4044 SqlScalarType::Oid => ReprScalarType::UInt32,
4045 SqlScalarType::Map {
4046 value_type,
4047 custom_id: _,
4048 } => ReprScalarType::Map {
4049 value_type: Box::new((*value_type).into()),
4050 },
4051 SqlScalarType::RegProc => ReprScalarType::UInt32,
4052 SqlScalarType::RegType => ReprScalarType::UInt32,
4053 SqlScalarType::RegClass => ReprScalarType::UInt32,
4054 SqlScalarType::Int2Vector => ReprScalarType::Int2Vector,
4055 SqlScalarType::MzTimestamp => ReprScalarType::MzTimestamp,
4056 SqlScalarType::Range { element_type } => ReprScalarType::Range {
4057 element_type: Box::new((*element_type).into()),
4058 },
4059 SqlScalarType::MzAclItem => ReprScalarType::MzAclItem,
4060 SqlScalarType::AclItem => ReprScalarType::AclItem,
4061 }
4062 }
4063}
4064
4065static EMPTY_ARRAY_ROW: LazyLock<Row> = LazyLock::new(|| {
4066 let mut row = Row::default();
4067 row.packer()
4068 .try_push_array(&[], iter::empty::<Datum>())
4069 .expect("array known to be valid");
4070 row
4071});
4072
4073static EMPTY_LIST_ROW: LazyLock<Row> = LazyLock::new(|| {
4074 let mut row = Row::default();
4075 row.packer().push_list(iter::empty::<Datum>());
4076 row
4077});
4078
4079static EMPTY_MAP_ROW: LazyLock<Row> = LazyLock::new(|| {
4080 let mut row = Row::default();
4081 row.packer().push_dict(iter::empty::<(_, Datum)>());
4082 row
4083});
4084
4085impl Datum<'_> {
4086 pub fn empty_array() -> Datum<'static> {
4087 EMPTY_ARRAY_ROW.unpack_first()
4088 }
4089
4090 pub fn empty_list() -> Datum<'static> {
4091 EMPTY_LIST_ROW.unpack_first()
4092 }
4093
4094 pub fn empty_map() -> Datum<'static> {
4095 EMPTY_MAP_ROW.unpack_first()
4096 }
4097}
4098
4099#[derive(Debug, PartialEq, Clone)]
4101pub enum PropDatum {
4102 Null,
4103 Bool(bool),
4104 Int16(i16),
4105 Int32(i32),
4106 Int64(i64),
4107 UInt8(u8),
4108 UInt16(u16),
4109 UInt32(u32),
4110 UInt64(u64),
4111 Float32(f32),
4112 Float64(f64),
4113
4114 Date(Date),
4115 Time(chrono::NaiveTime),
4116 Timestamp(CheckedTimestamp<chrono::NaiveDateTime>),
4117 TimestampTz(CheckedTimestamp<chrono::DateTime<chrono::Utc>>),
4118 MzTimestamp(u64),
4119
4120 Interval(Interval),
4121 Numeric(Numeric),
4122
4123 Bytes(Vec<u8>),
4124 String(String),
4125
4126 Array(PropArray),
4127 List(PropList),
4128 Map(PropDict),
4129 Record(PropDict),
4130 Range(PropRange),
4131
4132 AclItem(AclItem),
4133 MzAclItem(MzAclItem),
4134
4135 JsonNull,
4136 Uuid(Uuid),
4137 Dummy,
4138}
4139
4140impl std::cmp::Eq for PropDatum {}
4141
4142impl PartialOrd for PropDatum {
4143 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
4144 Some(self.cmp(other))
4145 }
4146}
4147
4148impl Ord for PropDatum {
4149 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
4150 Datum::from(self).cmp(&Datum::from(other))
4151 }
4152}
4153
4154pub fn arb_datum() -> BoxedStrategy<PropDatum> {
4156 let leaf = Union::new(vec![
4157 Just(PropDatum::Dummy).boxed(),
4158 any::<bool>().prop_map(PropDatum::Bool).boxed(),
4159 any::<i16>().prop_map(PropDatum::Int16).boxed(),
4160 any::<i32>().prop_map(PropDatum::Int32).boxed(),
4161 any::<i64>().prop_map(PropDatum::Int64).boxed(),
4162 any::<u16>().prop_map(PropDatum::UInt16).boxed(),
4163 any::<u32>().prop_map(PropDatum::UInt32).boxed(),
4164 any::<u64>().prop_map(PropDatum::UInt64).boxed(),
4165 any::<f32>().prop_map(PropDatum::Float32).boxed(),
4166 any::<f64>().prop_map(PropDatum::Float64).boxed(),
4167 arb_date().prop_map(PropDatum::Date).boxed(),
4168 add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
4169 .prop_map(PropDatum::Time)
4170 .boxed(),
4171 arb_naive_date_time()
4172 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
4173 .boxed(),
4174 arb_utc_date_time()
4175 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
4176 .boxed(),
4177 any::<Interval>().prop_map(PropDatum::Interval).boxed(),
4178 arb_numeric().prop_map(PropDatum::Numeric).boxed(),
4179 prop::collection::vec(any::<u8>(), 1024)
4180 .prop_map(PropDatum::Bytes)
4181 .boxed(),
4182 ".*".prop_map(PropDatum::String).boxed(),
4183 Just(PropDatum::JsonNull).boxed(),
4184 any::<[u8; 16]>()
4185 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
4186 .boxed(),
4187 arb_range(arb_range_data())
4188 .prop_map(PropDatum::Range)
4189 .boxed(),
4190 Just(PropDatum::Dummy).boxed(),
4191 ]);
4192
4193 leaf.prop_recursive(3, 8, 16, |inner| {
4194 Union::new(vec![
4195 arb_array(inner.clone()).prop_map(PropDatum::Array).boxed(),
4196 arb_list(inner.clone()).prop_map(PropDatum::List).boxed(),
4197 arb_dict(inner).prop_map(PropDatum::Map).boxed(),
4198 ])
4199 })
4200 .boxed()
4201}
4202
4203pub fn arb_datum_for_column(column_type: SqlColumnType) -> impl Strategy<Value = PropDatum> {
4205 let strat = arb_datum_for_scalar(column_type.scalar_type);
4206
4207 if column_type.nullable {
4208 Union::new_weighted(vec![(1, Just(PropDatum::Null).boxed()), (5, strat.boxed())]).boxed()
4209 } else {
4210 strat.boxed()
4211 }
4212}
4213
4214pub fn arb_datum_for_scalar(scalar_type: SqlScalarType) -> impl Strategy<Value = PropDatum> {
4216 match scalar_type {
4217 SqlScalarType::Bool => any::<bool>().prop_map(PropDatum::Bool).boxed(),
4218 SqlScalarType::Int16 => any::<i16>().prop_map(PropDatum::Int16).boxed(),
4219 SqlScalarType::Int32 => any::<i32>().prop_map(PropDatum::Int32).boxed(),
4220 SqlScalarType::Int64 => any::<i64>().prop_map(PropDatum::Int64).boxed(),
4221 SqlScalarType::PgLegacyChar => any::<u8>().prop_map(PropDatum::UInt8).boxed(),
4222 SqlScalarType::UInt16 => any::<u16>().prop_map(PropDatum::UInt16).boxed(),
4223 SqlScalarType::UInt32
4224 | SqlScalarType::Oid
4225 | SqlScalarType::RegClass
4226 | SqlScalarType::RegProc
4227 | SqlScalarType::RegType => any::<u32>().prop_map(PropDatum::UInt32).boxed(),
4228 SqlScalarType::UInt64 => any::<u64>().prop_map(PropDatum::UInt64).boxed(),
4229 SqlScalarType::Float32 => any::<f32>().prop_map(PropDatum::Float32).boxed(),
4230 SqlScalarType::Float64 => any::<f64>().prop_map(PropDatum::Float64).boxed(),
4231 SqlScalarType::Numeric { .. } => arb_numeric().prop_map(PropDatum::Numeric).boxed(),
4232 SqlScalarType::String
4233 | SqlScalarType::PgLegacyName
4234 | SqlScalarType::Char { length: None }
4235 | SqlScalarType::VarChar { max_length: None } => ".*".prop_map(PropDatum::String).boxed(),
4236 SqlScalarType::Char {
4237 length: Some(length),
4238 } => {
4239 let max_len = usize::cast_from(length.into_u32()).max(1);
4240 prop::collection::vec(any::<char>(), 0..max_len)
4241 .prop_map(move |chars| {
4242 let num_blanks = max_len - chars.len();
4244 let s = chars
4245 .into_iter()
4246 .chain(std::iter::repeat(' ').take(num_blanks))
4247 .collect();
4248 PropDatum::String(s)
4249 })
4250 .boxed()
4251 }
4252 SqlScalarType::VarChar {
4253 max_length: Some(length),
4254 } => {
4255 let max_len = usize::cast_from(length.into_u32()).max(1);
4256 prop::collection::vec(any::<char>(), 0..max_len)
4257 .prop_map(|chars| PropDatum::String(chars.into_iter().collect()))
4258 .boxed()
4259 }
4260 SqlScalarType::Bytes => prop::collection::vec(any::<u8>(), 300)
4261 .prop_map(PropDatum::Bytes)
4262 .boxed(),
4263 SqlScalarType::Date => arb_date().prop_map(PropDatum::Date).boxed(),
4264 SqlScalarType::Time => add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
4265 .prop_map(PropDatum::Time)
4266 .boxed(),
4267 SqlScalarType::Timestamp { .. } => arb_naive_date_time()
4268 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
4269 .boxed(),
4270 SqlScalarType::TimestampTz { .. } => arb_utc_date_time()
4271 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
4272 .boxed(),
4273 SqlScalarType::MzTimestamp => any::<u64>().prop_map(PropDatum::MzTimestamp).boxed(),
4274 SqlScalarType::Interval => any::<Interval>().prop_map(PropDatum::Interval).boxed(),
4275 SqlScalarType::Uuid => any::<[u8; 16]>()
4276 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
4277 .boxed(),
4278 SqlScalarType::AclItem => any::<AclItem>().prop_map(PropDatum::AclItem).boxed(),
4279 SqlScalarType::MzAclItem => any::<MzAclItem>().prop_map(PropDatum::MzAclItem).boxed(),
4280 SqlScalarType::Range { element_type } => {
4281 let data_strat = (
4282 arb_datum_for_scalar(*element_type.clone()),
4283 arb_datum_for_scalar(*element_type),
4284 );
4285 arb_range(data_strat).prop_map(PropDatum::Range).boxed()
4286 }
4287 SqlScalarType::List { element_type, .. } => arb_list(arb_datum_for_scalar(*element_type))
4288 .prop_map(PropDatum::List)
4289 .boxed(),
4290 SqlScalarType::Array(element_type) => arb_array(arb_datum_for_scalar(*element_type))
4291 .prop_map(PropDatum::Array)
4292 .boxed(),
4293 SqlScalarType::Int2Vector => arb_array(any::<i16>().prop_map(PropDatum::Int16).boxed())
4294 .prop_map(PropDatum::Array)
4295 .boxed(),
4296 SqlScalarType::Map { value_type, .. } => arb_dict(arb_datum_for_scalar(*value_type))
4297 .prop_map(PropDatum::Map)
4298 .boxed(),
4299 SqlScalarType::Record { fields, .. } => {
4300 let field_strats = fields.iter().map(|(name, ty)| {
4301 (
4302 name.to_string(),
4303 arb_datum_for_scalar(ty.scalar_type.clone()),
4304 )
4305 });
4306 arb_record(field_strats).prop_map(PropDatum::Record).boxed()
4307 }
4308 SqlScalarType::Jsonb => {
4309 let int_value = any::<i128>()
4310 .prop_map(|v| Numeric::try_from(v).unwrap())
4311 .boxed();
4312 let float_value = (1e-39f64..1e39)
4314 .prop_map(|v| Numeric::try_from(v).unwrap())
4315 .boxed();
4316 let json_number = Union::new(vec![int_value, float_value]);
4319
4320 let json_leaf = Union::new(vec![
4321 any::<()>().prop_map(|_| PropDatum::JsonNull).boxed(),
4322 any::<bool>().prop_map(PropDatum::Bool).boxed(),
4323 json_number.prop_map(PropDatum::Numeric).boxed(),
4324 ".*".prop_map(PropDatum::String).boxed(),
4325 ]);
4326 json_leaf
4327 .prop_recursive(4, 32, 8, |element| {
4328 Union::new(vec![
4329 prop::collection::vec(element.clone(), 0..16)
4330 .prop_map(|elements| {
4331 let datums: Vec<_> = elements.iter().map(|pd| pd.into()).collect();
4332 let mut row = Row::default();
4333 row.packer().push_list(datums.iter());
4334 PropDatum::List(PropList(row, elements))
4335 })
4336 .boxed(),
4337 prop::collection::hash_map(".*", element, 0..16)
4338 .prop_map(|elements| {
4339 let mut elements: Vec<_> = elements.into_iter().collect();
4340 elements.sort_by_key(|(k, _)| k.clone());
4341 elements.dedup_by_key(|(k, _)| k.clone());
4342 let mut row = Row::default();
4343 let entry_iter =
4344 elements.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4345 row.packer().push_dict(entry_iter);
4346 PropDatum::Map(PropDict(row, elements))
4347 })
4348 .boxed(),
4349 ])
4350 })
4351 .boxed()
4352 }
4353 }
4354}
4355
4356pub fn arb_naive_date_time() -> impl Strategy<Value = NaiveDateTime> {
4358 add_arb_duration(chrono::DateTime::from_timestamp(0, 0).unwrap().naive_utc())
4359}
4360
4361pub fn arb_utc_date_time() -> impl Strategy<Value = DateTime<Utc>> {
4363 add_arb_duration(chrono::Utc.timestamp_opt(0, 0).unwrap())
4364}
4365
4366fn arb_array_dimension() -> BoxedStrategy<ArrayDimension> {
4367 (1..4_usize)
4368 .prop_map(|length| ArrayDimension {
4369 lower_bound: 1,
4370 length,
4371 })
4372 .boxed()
4373}
4374
4375#[derive(Debug, PartialEq, Clone)]
4376pub struct PropArray(Row, Vec<PropDatum>);
4377
4378fn arb_array(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropArray> {
4379 let element_strategy = Union::new_weighted(vec![
4381 (20, element_strategy),
4382 (1, Just(PropDatum::Null).boxed()),
4383 ]);
4384
4385 prop::collection::vec(
4386 arb_array_dimension(),
4387 1..usize::from(crate::adt::array::MAX_ARRAY_DIMENSIONS),
4388 )
4389 .prop_flat_map(move |dimensions| {
4390 let n_elts: usize = dimensions.iter().map(|d| d.length).product();
4391 (
4392 Just(dimensions),
4393 prop::collection::vec(element_strategy.clone(), n_elts),
4394 )
4395 })
4396 .prop_map(|(dimensions, elements)| {
4397 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4398 let mut row = Row::default();
4399 row.packer()
4400 .try_push_array(&dimensions, element_datums)
4401 .unwrap();
4402 PropArray(row, elements)
4403 })
4404 .boxed()
4405}
4406
4407#[derive(Debug, PartialEq, Clone)]
4408pub struct PropList(Row, Vec<PropDatum>);
4409
4410fn arb_list(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropList> {
4411 let element_strategy = Union::new_weighted(vec![
4413 (20, element_strategy),
4414 (1, Just(PropDatum::Null).boxed()),
4415 ]);
4416
4417 prop::collection::vec(element_strategy, 1..50)
4418 .prop_map(|elements| {
4419 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4420 let mut row = Row::default();
4421 row.packer().push_list(element_datums.iter());
4422 PropList(row, elements)
4423 })
4424 .boxed()
4425}
4426
4427#[derive(Debug, PartialEq, Clone)]
4428pub struct PropRange(
4429 Row,
4430 Option<(
4431 (Option<Box<PropDatum>>, bool),
4432 (Option<Box<PropDatum>>, bool),
4433 )>,
4434);
4435
4436pub fn arb_range_type() -> Union<BoxedStrategy<SqlScalarType>> {
4437 Union::new(vec![
4438 Just(SqlScalarType::Int32).boxed(),
4439 Just(SqlScalarType::Int64).boxed(),
4440 Just(SqlScalarType::Date).boxed(),
4441 ])
4442}
4443
4444fn arb_range_data() -> Union<BoxedStrategy<(PropDatum, PropDatum)>> {
4445 Union::new(vec![
4446 (
4447 any::<i32>().prop_map(PropDatum::Int32),
4448 any::<i32>().prop_map(PropDatum::Int32),
4449 )
4450 .boxed(),
4451 (
4452 any::<i64>().prop_map(PropDatum::Int64),
4453 any::<i64>().prop_map(PropDatum::Int64),
4454 )
4455 .boxed(),
4456 (
4457 arb_date().prop_map(PropDatum::Date),
4458 arb_date().prop_map(PropDatum::Date),
4459 )
4460 .boxed(),
4461 ])
4462}
4463
4464fn arb_range(
4465 data: impl Strategy<Value = (PropDatum, PropDatum)> + 'static,
4466) -> BoxedStrategy<PropRange> {
4467 (
4468 any::<u16>(),
4469 any::<bool>(),
4470 any::<bool>(),
4471 any::<bool>(),
4472 any::<bool>(),
4473 data,
4474 )
4475 .prop_map(
4476 |(split, lower_inf, lower_inc, upper_inf, upper_inc, (a, b))| {
4477 let mut row = Row::default();
4478 let mut packer = row.packer();
4479 let r = if split % 32 == 0 {
4480 packer
4481 .push_range(Range::new(None))
4482 .expect("pushing empty ranges never fails");
4483 None
4484 } else {
4485 let b_is_lower = Datum::from(&b) < Datum::from(&a);
4486
4487 let (lower, upper) = if b_is_lower { (b, a) } else { (a, b) };
4488 let mut range = Range::new(Some((
4489 RangeLowerBound {
4490 inclusive: lower_inc,
4491 bound: if lower_inf {
4492 None
4493 } else {
4494 Some(Datum::from(&lower))
4495 },
4496 },
4497 RangeUpperBound {
4498 inclusive: upper_inc,
4499 bound: if upper_inf {
4500 None
4501 } else {
4502 Some(Datum::from(&upper))
4503 },
4504 },
4505 )));
4506
4507 range.canonicalize().unwrap();
4508
4509 let (empty, lower_inf, lower_inc, upper_inf, upper_inc) = match range.inner {
4512 None => (true, false, false, false, false),
4513 Some(inner) => (
4514 false
4515 || match inner.lower.bound {
4516 Some(b) => b != Datum::from(&lower),
4517 None => !lower_inf,
4518 }
4519 || match inner.upper.bound {
4520 Some(b) => b != Datum::from(&upper),
4521 None => !upper_inf,
4522 },
4523 inner.lower.bound.is_none(),
4524 inner.lower.inclusive,
4525 inner.upper.bound.is_none(),
4526 inner.upper.inclusive,
4527 ),
4528 };
4529
4530 if empty {
4531 packer.push_range(Range { inner: None }).unwrap();
4532 None
4533 } else {
4534 packer.push_range(range).unwrap();
4535 Some((
4536 (
4537 if lower_inf {
4538 None
4539 } else {
4540 Some(Box::new(lower))
4541 },
4542 lower_inc,
4543 ),
4544 (
4545 if upper_inf {
4546 None
4547 } else {
4548 Some(Box::new(upper))
4549 },
4550 upper_inc,
4551 ),
4552 ))
4553 }
4554 };
4555
4556 PropRange(row, r)
4557 },
4558 )
4559 .boxed()
4560}
4561
4562#[derive(Debug, PartialEq, Clone)]
4563pub struct PropDict(Row, Vec<(String, PropDatum)>);
4564
4565fn arb_dict(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropDict> {
4566 let element_strategy = Union::new_weighted(vec![
4568 (20, element_strategy),
4569 (1, Just(PropDatum::Null).boxed()),
4570 ]);
4571
4572 prop::collection::vec((".*", element_strategy), 1..50)
4573 .prop_map(|mut entries| {
4574 entries.sort_by_key(|(k, _)| k.clone());
4575 entries.dedup_by_key(|(k, _)| k.clone());
4576 let mut row = Row::default();
4577 let entry_iter = entries.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4578 row.packer().push_dict(entry_iter);
4579 PropDict(row, entries)
4580 })
4581 .boxed()
4582}
4583
4584fn arb_record(
4585 fields: impl Iterator<Item = (String, BoxedStrategy<PropDatum>)>,
4586) -> BoxedStrategy<PropDict> {
4587 let (names, strategies): (Vec<_>, Vec<_>) = fields.unzip();
4588
4589 strategies
4590 .prop_map(move |x| {
4591 let mut row = Row::default();
4592 row.packer().push_list(x.iter().map(Datum::from));
4593 let entries: Vec<_> = names.clone().into_iter().zip_eq(x).collect();
4594 PropDict(row, entries)
4595 })
4596 .boxed()
4597}
4598
4599fn arb_date() -> BoxedStrategy<Date> {
4600 (Date::LOW_DAYS..Date::HIGH_DAYS)
4601 .prop_map(move |days| Date::from_pg_epoch(days).unwrap())
4602 .boxed()
4603}
4604
4605pub fn add_arb_duration<T: 'static + Copy + Add<chrono::Duration> + std::fmt::Debug>(
4606 to: T,
4607) -> BoxedStrategy<T::Output>
4608where
4609 T::Output: std::fmt::Debug,
4610{
4611 let lower = LOW_DATE
4612 .and_hms_opt(0, 0, 0)
4613 .unwrap()
4614 .and_utc()
4615 .timestamp_micros();
4616 let upper = HIGH_DATE
4617 .and_hms_opt(0, 0, 0)
4618 .unwrap()
4619 .and_utc()
4620 .timestamp_micros();
4621 (lower..upper)
4622 .prop_map(move |v| to + chrono::Duration::microseconds(v))
4623 .boxed()
4624}
4625
4626pub(crate) fn arb_numeric() -> BoxedStrategy<Numeric> {
4627 let int_value = any::<i128>()
4628 .prop_map(|v| Numeric::try_from(v).unwrap())
4629 .boxed();
4630 let float_value = (-1e39f64..1e39)
4631 .prop_map(|v| Numeric::try_from(v).unwrap())
4632 .boxed();
4633
4634 let tiny_floats = ((-10.0..10.0), (1u32..10))
4637 .prop_map(|(v, num_digits)| {
4638 let num_digits: f64 = 10u32.pow(num_digits).try_into().unwrap();
4640 let trunc = f64::trunc(v * num_digits) / num_digits;
4641 Numeric::try_from(trunc).unwrap()
4642 })
4643 .boxed();
4644 let small_ints = (-1_000_000..1_000_000)
4645 .prop_map(|v| Numeric::try_from(v).unwrap())
4646 .boxed();
4647 let small_floats = (-1_000_000.0..1_000_000.0)
4648 .prop_map(|v| Numeric::try_from(v).unwrap())
4649 .boxed();
4650
4651 Union::new_weighted(vec![
4652 (20, tiny_floats),
4653 (20, small_ints),
4654 (20, small_floats),
4655 (10, int_value),
4656 (10, float_value),
4657 (1, Just(Numeric::infinity()).boxed()),
4658 (1, Just(-Numeric::infinity()).boxed()),
4659 (1, Just(Numeric::nan()).boxed()),
4660 (1, Just(Numeric::zero()).boxed()),
4661 ])
4662 .boxed()
4663}
4664
4665impl<'a> From<&'a PropDatum> for Datum<'a> {
4666 #[inline]
4667 fn from(pd: &'a PropDatum) -> Self {
4668 use PropDatum::*;
4669 match pd {
4670 Null => Datum::Null,
4671 Bool(b) => Datum::from(*b),
4672 Int16(i) => Datum::from(*i),
4673 Int32(i) => Datum::from(*i),
4674 Int64(i) => Datum::from(*i),
4675 UInt8(u) => Datum::from(*u),
4676 UInt16(u) => Datum::from(*u),
4677 UInt32(u) => Datum::from(*u),
4678 UInt64(u) => Datum::from(*u),
4679 Float32(f) => Datum::from(*f),
4680 Float64(f) => Datum::from(*f),
4681 Date(d) => Datum::from(*d),
4682 Time(t) => Datum::from(*t),
4683 Timestamp(t) => Datum::from(*t),
4684 TimestampTz(t) => Datum::from(*t),
4685 MzTimestamp(t) => Datum::MzTimestamp((*t).into()),
4686 Interval(i) => Datum::from(*i),
4687 Numeric(s) => Datum::from(*s),
4688 Bytes(b) => Datum::from(&b[..]),
4689 String(s) => Datum::from(s.as_str()),
4690 Array(PropArray(row, _)) => {
4691 let array = row.unpack_first().unwrap_array();
4692 Datum::Array(array)
4693 }
4694 List(PropList(row, _)) => {
4695 let list = row.unpack_first().unwrap_list();
4696 Datum::List(list)
4697 }
4698 Map(PropDict(row, _)) => {
4699 let map = row.unpack_first().unwrap_map();
4700 Datum::Map(map)
4701 }
4702 Record(PropDict(row, _)) => {
4703 let list = row.unpack_first().unwrap_list();
4704 Datum::List(list)
4705 }
4706 Range(PropRange(row, _)) => {
4707 let d = row.unpack_first();
4708 assert!(matches!(d, Datum::Range(_)));
4709 d
4710 }
4711 AclItem(i) => Datum::AclItem(*i),
4712 MzAclItem(i) => Datum::MzAclItem(*i),
4713 JsonNull => Datum::JsonNull,
4714 Uuid(u) => Datum::from(*u),
4715 Dummy => Datum::Dummy,
4716 }
4717 }
4718}
4719
4720#[mz_ore::test]
4721fn verify_base_eq_record_nullability() {
4722 let s1 = SqlScalarType::Record {
4723 fields: [(
4724 "c".into(),
4725 SqlColumnType {
4726 scalar_type: SqlScalarType::Bool,
4727 nullable: true,
4728 },
4729 )]
4730 .into(),
4731 custom_id: None,
4732 };
4733 let s2 = SqlScalarType::Record {
4734 fields: [(
4735 "c".into(),
4736 SqlColumnType {
4737 scalar_type: SqlScalarType::Bool,
4738 nullable: false,
4739 },
4740 )]
4741 .into(),
4742 custom_id: None,
4743 };
4744 let s3 = SqlScalarType::Record {
4745 fields: [].into(),
4746 custom_id: None,
4747 };
4748 assert!(s1.base_eq(&s2));
4749 assert!(!s1.base_eq(&s3));
4750}
4751
4752#[cfg(test)]
4753mod tests {
4754 use mz_ore::assert_ok;
4755 use mz_proto::protobuf_roundtrip;
4756
4757 use super::*;
4758
4759 proptest! {
4760 #[mz_ore::test]
4761 #[cfg_attr(miri, ignore)] fn scalar_type_protobuf_roundtrip(expect in any::<SqlScalarType>() ) {
4763 let actual = protobuf_roundtrip::<_, ProtoScalarType>(&expect);
4764 assert_ok!(actual);
4765 assert_eq!(actual.unwrap(), expect);
4766 }
4767 }
4768
4769 proptest! {
4770 #[mz_ore::test]
4771 #[cfg_attr(miri, ignore)]
4772 fn sql_repr_types_agree_on_valid_data((src, datum) in any::<SqlColumnType>().prop_flat_map(|src| {
4773 let datum = arb_datum_for_column(src.clone());
4774 (Just(src.clone()), datum) }
4775 )) {
4776 let tgt: ReprColumnType = src.clone().into();
4777 let datum = Datum::from(&datum);
4778 assert_eq!(datum.is_instance_of_sql(&src), datum.is_instance_of(&tgt), "translated to repr type {tgt:#?}");
4779 }
4780 }
4781
4782 proptest! {
4783 #![proptest_config(ProptestConfig::with_cases(10000))]
4786 #[mz_ore::test]
4787 #[cfg_attr(miri, ignore)]
4788 fn sql_repr_types_agree_on_random_data(src in any::<SqlColumnType>(), datum in arb_datum()) {
4789 let tgt: ReprColumnType = src.clone().into();
4790 let datum = Datum::from(&datum);
4791
4792 assert_eq!(datum.is_instance_of_sql(&src), datum.is_instance_of(&tgt), "translated to repr type {tgt:#?}");
4793 }
4794 }
4795
4796 proptest! {
4797 #[mz_ore::test]
4798 #[cfg_attr(miri, ignore)] fn array_packing_unpacks_correctly(array in arb_array(arb_datum())) {
4800 let PropArray(row, elts) = array;
4801 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
4802 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_array().elements().iter().collect();
4803 assert_eq!(unpacked_datums, datums);
4804 }
4805
4806 #[mz_ore::test]
4807 #[cfg_attr(miri, ignore)] fn list_packing_unpacks_correctly(array in arb_list(arb_datum())) {
4809 let PropList(row, elts) = array;
4810 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
4811 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_list().iter().collect();
4812 assert_eq!(unpacked_datums, datums);
4813 }
4814
4815 #[mz_ore::test]
4816 #[cfg_attr(miri, ignore)] fn dict_packing_unpacks_correctly(array in arb_dict(arb_datum())) {
4818 let PropDict(row, elts) = array;
4819 let datums: Vec<(&str, Datum<'_>)> = elts.iter().map(|(k, e)| (k.as_str(), e.into())).collect();
4820 let unpacked_datums: Vec<(&str, Datum<'_>)> = row.unpack_first().unwrap_map().iter().collect();
4821 assert_eq!(unpacked_datums, datums);
4822 }
4823
4824 #[mz_ore::test]
4825 #[cfg_attr(miri, ignore)] fn row_packing_roundtrips_single_valued(prop_datums in prop::collection::vec(arb_datum(), 1..100)) {
4827 let datums: Vec<Datum<'_>> = prop_datums.iter().map(|pd| pd.into()).collect();
4828 let row = Row::pack(&datums);
4829 let unpacked = row.unpack();
4830 assert_eq!(datums, unpacked);
4831 }
4832
4833 #[mz_ore::test]
4834 #[cfg_attr(miri, ignore)] fn range_packing_unpacks_correctly(range in arb_range(arb_range_data())) {
4836 let PropRange(row, prop_range) = range;
4837 let row = row.unpack_first();
4838 let d = row.unwrap_range();
4839
4840 let (((prop_lower, prop_lower_inc), (prop_upper, prop_upper_inc)), crate::adt::range::RangeInner {lower, upper}) = match (prop_range, d.inner) {
4841 (Some(prop_values), Some(inner_range)) => (prop_values, inner_range),
4842 (None, None) => return Ok(()),
4843 _ => panic!("inequivalent row packing"),
4844 };
4845
4846 for (prop_bound, prop_bound_inc, inner_bound, inner_bound_inc) in [
4847 (prop_lower, prop_lower_inc, lower.bound, lower.inclusive),
4848 (prop_upper, prop_upper_inc, upper.bound, upper.inclusive),
4849 ] {
4850 assert_eq!(prop_bound_inc, inner_bound_inc);
4851 match (prop_bound, inner_bound) {
4852 (None, None) => continue,
4853 (Some(p), Some(b)) => {
4854 assert_eq!(Datum::from(&*p), b);
4855 }
4856 _ => panic!("inequivalent row packing"),
4857 }
4858 }
4859 }
4860 }
4861}