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(SqlScalarBaseType, 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
1992#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1999pub struct ExcludeNull<B>(B);
2000
2001impl<B: AsColumnType> AsColumnType for ExcludeNull<B> {
2002 fn as_column_type() -> SqlColumnType {
2003 B::as_column_type().nullable(false)
2004 }
2005}
2006
2007impl<'a, E, B: DatumType<'a, E>> DatumType<'a, E> for ExcludeNull<B> {
2008 fn nullable() -> bool {
2009 false
2010 }
2011 fn fallible() -> bool {
2012 B::fallible()
2013 }
2014 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2015 match res {
2016 Ok(Datum::Null) => Err(Ok(Datum::Null)),
2017 _ => B::try_from_result(res).map(ExcludeNull),
2018 }
2019 }
2020 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2021 self.0.into_result(temp_storage)
2022 }
2023}
2024
2025impl<B> std::ops::Deref for ExcludeNull<B> {
2026 type Target = B;
2027
2028 fn deref(&self) -> &Self::Target {
2029 &self.0
2030 }
2031}
2032
2033macro_rules! impl_datum_type_copy {
2035 ($lt:lifetime, $native:ty, $variant:ident) => {
2036 impl<$lt> AsColumnType for $native {
2037 fn as_column_type() -> SqlColumnType {
2038 SqlScalarType::$variant.nullable(false)
2039 }
2040 }
2041
2042 impl<$lt, E> DatumType<$lt, E> for $native {
2043 fn nullable() -> bool {
2044 false
2045 }
2046
2047 fn fallible() -> bool {
2048 false
2049 }
2050
2051 fn try_from_result(res: Result<Datum<$lt>, E>) -> Result<Self, Result<Datum<$lt>, E>> {
2052 match res {
2053 Ok(Datum::$variant(f)) => Ok(f.into()),
2054 _ => Err(res),
2055 }
2056 }
2057
2058 fn into_result(self, _temp_storage: &$lt RowArena) -> Result<Datum<$lt>, E> {
2059 Ok(Datum::$variant(self.into()))
2060 }
2061 }
2062 };
2063 ($native:ty, $variant:ident) => {
2064 impl_datum_type_copy!('a, $native, $variant);
2065 };
2066}
2067
2068impl_datum_type_copy!(f32, Float32);
2069impl_datum_type_copy!(f64, Float64);
2070impl_datum_type_copy!(i16, Int16);
2071impl_datum_type_copy!(i32, Int32);
2072impl_datum_type_copy!(i64, Int64);
2073impl_datum_type_copy!(u16, UInt16);
2074impl_datum_type_copy!(u32, UInt32);
2075impl_datum_type_copy!(u64, UInt64);
2076impl_datum_type_copy!(Interval, Interval);
2077impl_datum_type_copy!(Date, Date);
2078impl_datum_type_copy!(NaiveTime, Time);
2079impl_datum_type_copy!(Uuid, Uuid);
2080impl_datum_type_copy!('a, &'a str, String);
2081impl_datum_type_copy!('a, &'a [u8], Bytes);
2082impl_datum_type_copy!(crate::Timestamp, MzTimestamp);
2083
2084impl<'a, E> DatumType<'a, E> for Datum<'a> {
2085 fn nullable() -> bool {
2086 true
2087 }
2088
2089 fn fallible() -> bool {
2090 false
2091 }
2092
2093 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2094 match res {
2095 Ok(datum) => Ok(datum),
2096 _ => Err(res),
2097 }
2098 }
2099
2100 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2101 Ok(self)
2102 }
2103}
2104
2105impl<'a, E> DatumType<'a, E> for DatumList<'a> {
2106 fn nullable() -> bool {
2107 false
2108 }
2109
2110 fn fallible() -> bool {
2111 false
2112 }
2113
2114 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2115 match res {
2116 Ok(Datum::List(list)) => Ok(list),
2117 _ => Err(res),
2118 }
2119 }
2120
2121 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2122 Ok(Datum::List(self))
2123 }
2124}
2125
2126impl<'a, E> DatumType<'a, E> for Array<'a> {
2127 fn nullable() -> bool {
2128 false
2129 }
2130
2131 fn fallible() -> bool {
2132 false
2133 }
2134
2135 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2136 match res {
2137 Ok(Datum::Array(array)) => Ok(array),
2138 _ => Err(res),
2139 }
2140 }
2141
2142 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2143 Ok(Datum::Array(self))
2144 }
2145}
2146
2147impl<'a, E> DatumType<'a, E> for DatumMap<'a> {
2148 fn nullable() -> bool {
2149 false
2150 }
2151
2152 fn fallible() -> bool {
2153 false
2154 }
2155
2156 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2157 match res {
2158 Ok(Datum::Map(map)) => Ok(map),
2159 _ => Err(res),
2160 }
2161 }
2162
2163 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2164 Ok(Datum::Map(self))
2165 }
2166}
2167
2168impl<'a, E> DatumType<'a, E> for Range<DatumNested<'a>> {
2169 fn nullable() -> bool {
2170 false
2171 }
2172
2173 fn fallible() -> bool {
2174 false
2175 }
2176
2177 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2178 match res {
2179 Ok(Datum::Range(range)) => Ok(range),
2180 _ => Err(res),
2181 }
2182 }
2183
2184 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2185 Ok(Datum::Range(self))
2186 }
2187}
2188
2189impl<'a, E> DatumType<'a, E> for Range<Datum<'a>> {
2190 fn nullable() -> bool {
2191 false
2192 }
2193
2194 fn fallible() -> bool {
2195 false
2196 }
2197
2198 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2199 match res {
2200 Ok(r @ Datum::Range(..)) => Ok(r.unwrap_range()),
2201 _ => Err(res),
2202 }
2203 }
2204
2205 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2206 let d =
2207 self.into_bounds(|bound| temp_storage.make_datum_nested(|packer| packer.push(bound)));
2208 Ok(Datum::Range(d))
2209 }
2210}
2211
2212impl AsColumnType for bool {
2213 fn as_column_type() -> SqlColumnType {
2214 SqlScalarType::Bool.nullable(false)
2215 }
2216}
2217
2218impl<'a, E> DatumType<'a, E> for bool {
2219 fn nullable() -> bool {
2220 false
2221 }
2222
2223 fn fallible() -> bool {
2224 false
2225 }
2226
2227 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2228 match res {
2229 Ok(Datum::True) => Ok(true),
2230 Ok(Datum::False) => Ok(false),
2231 _ => Err(res),
2232 }
2233 }
2234
2235 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2236 if self {
2237 Ok(Datum::True)
2238 } else {
2239 Ok(Datum::False)
2240 }
2241 }
2242}
2243
2244impl AsColumnType for String {
2245 fn as_column_type() -> SqlColumnType {
2246 SqlScalarType::String.nullable(false)
2247 }
2248}
2249
2250impl<'a, E> DatumType<'a, E> for String {
2251 fn nullable() -> bool {
2252 false
2253 }
2254
2255 fn fallible() -> bool {
2256 false
2257 }
2258
2259 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2260 match res {
2261 Ok(Datum::String(s)) => Ok(s.to_owned()),
2262 _ => Err(res),
2263 }
2264 }
2265
2266 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2267 Ok(Datum::String(temp_storage.push_string(self)))
2268 }
2269}
2270
2271impl AsColumnType for ArrayRustType<String> {
2272 fn as_column_type() -> SqlColumnType {
2273 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false)
2274 }
2275}
2276
2277impl<'a, E> DatumType<'a, E> for ArrayRustType<String> {
2278 fn nullable() -> bool {
2279 false
2280 }
2281
2282 fn fallible() -> bool {
2283 false
2284 }
2285
2286 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2287 match res {
2288 Ok(Datum::Array(arr)) => Ok(ArrayRustType(
2289 arr.elements()
2290 .into_iter()
2291 .map(|d| d.unwrap_str().to_string())
2292 .collect(),
2293 )),
2294 _ => Err(res),
2295 }
2296 }
2297
2298 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2299 Ok(temp_storage.make_datum(|packer| {
2300 packer
2301 .try_push_array(
2302 &[ArrayDimension {
2303 lower_bound: 1,
2304 length: self.0.len(),
2305 }],
2306 self.0.iter().map(|elem| Datum::String(elem.as_str())),
2307 )
2308 .expect("self is 1 dimensional, and its length is used for the array length");
2309 }))
2310 }
2311}
2312
2313impl AsColumnType for Vec<u8> {
2314 fn as_column_type() -> SqlColumnType {
2315 SqlScalarType::Bytes.nullable(false)
2316 }
2317}
2318
2319impl<'a, E> DatumType<'a, E> for Vec<u8> {
2320 fn nullable() -> bool {
2321 false
2322 }
2323
2324 fn fallible() -> bool {
2325 false
2326 }
2327
2328 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2329 match res {
2330 Ok(Datum::Bytes(b)) => Ok(b.to_owned()),
2331 _ => Err(res),
2332 }
2333 }
2334
2335 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2336 Ok(Datum::Bytes(temp_storage.push_bytes(self)))
2337 }
2338}
2339
2340impl AsColumnType for Numeric {
2341 fn as_column_type() -> SqlColumnType {
2342 SqlScalarType::Numeric { max_scale: None }.nullable(false)
2343 }
2344}
2345
2346impl<'a, E> DatumType<'a, E> for Numeric {
2347 fn nullable() -> bool {
2348 false
2349 }
2350
2351 fn fallible() -> bool {
2352 false
2353 }
2354
2355 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2356 match res {
2357 Ok(Datum::Numeric(n)) => Ok(n.into_inner()),
2358 _ => Err(res),
2359 }
2360 }
2361
2362 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2363 Ok(Datum::from(self))
2364 }
2365}
2366
2367impl<'a, E> DatumType<'a, E> for OrderedDecimal<Numeric> {
2368 fn nullable() -> bool {
2369 false
2370 }
2371
2372 fn fallible() -> bool {
2373 false
2374 }
2375
2376 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2377 match res {
2378 Ok(Datum::Numeric(n)) => Ok(n),
2379 _ => Err(res),
2380 }
2381 }
2382
2383 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2384 Ok(Datum::from(self))
2385 }
2386}
2387
2388impl AsColumnType for PgLegacyChar {
2389 fn as_column_type() -> SqlColumnType {
2390 SqlScalarType::PgLegacyChar.nullable(false)
2391 }
2392}
2393
2394impl<'a, E> DatumType<'a, E> for PgLegacyChar {
2395 fn nullable() -> bool {
2396 false
2397 }
2398
2399 fn fallible() -> bool {
2400 false
2401 }
2402
2403 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2404 match res {
2405 Ok(Datum::UInt8(a)) => Ok(PgLegacyChar(a)),
2406 _ => Err(res),
2407 }
2408 }
2409
2410 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2411 Ok(Datum::UInt8(self.0))
2412 }
2413}
2414
2415impl<S> AsColumnType for PgLegacyName<S>
2416where
2417 S: AsRef<str>,
2418{
2419 fn as_column_type() -> SqlColumnType {
2420 SqlScalarType::PgLegacyName.nullable(false)
2421 }
2422}
2423
2424impl<'a, E> DatumType<'a, E> for PgLegacyName<&'a str> {
2425 fn nullable() -> bool {
2426 false
2427 }
2428
2429 fn fallible() -> bool {
2430 false
2431 }
2432
2433 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2434 match res {
2435 Ok(Datum::String(a)) => Ok(PgLegacyName(a)),
2436 _ => Err(res),
2437 }
2438 }
2439
2440 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2441 Ok(Datum::String(self.0))
2442 }
2443}
2444
2445impl<'a, E> DatumType<'a, E> for PgLegacyName<String> {
2446 fn nullable() -> bool {
2447 false
2448 }
2449
2450 fn fallible() -> bool {
2451 false
2452 }
2453
2454 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2455 match res {
2456 Ok(Datum::String(a)) => Ok(PgLegacyName(a.to_owned())),
2457 _ => Err(res),
2458 }
2459 }
2460
2461 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2462 Ok(Datum::String(temp_storage.push_string(self.0)))
2463 }
2464}
2465
2466impl AsColumnType for Oid {
2467 fn as_column_type() -> SqlColumnType {
2468 SqlScalarType::Oid.nullable(false)
2469 }
2470}
2471
2472impl<'a, E> DatumType<'a, E> for Oid {
2473 fn nullable() -> bool {
2474 false
2475 }
2476
2477 fn fallible() -> bool {
2478 false
2479 }
2480
2481 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2482 match res {
2483 Ok(Datum::UInt32(a)) => Ok(Oid(a)),
2484 _ => Err(res),
2485 }
2486 }
2487
2488 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2489 Ok(Datum::UInt32(self.0))
2490 }
2491}
2492
2493impl AsColumnType for RegClass {
2494 fn as_column_type() -> SqlColumnType {
2495 SqlScalarType::RegClass.nullable(false)
2496 }
2497}
2498
2499impl<'a, E> DatumType<'a, E> for RegClass {
2500 fn nullable() -> bool {
2501 false
2502 }
2503
2504 fn fallible() -> bool {
2505 false
2506 }
2507
2508 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2509 match res {
2510 Ok(Datum::UInt32(a)) => Ok(RegClass(a)),
2511 _ => Err(res),
2512 }
2513 }
2514
2515 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2516 Ok(Datum::UInt32(self.0))
2517 }
2518}
2519
2520impl AsColumnType for RegProc {
2521 fn as_column_type() -> SqlColumnType {
2522 SqlScalarType::RegProc.nullable(false)
2523 }
2524}
2525
2526impl<'a, E> DatumType<'a, E> for RegProc {
2527 fn nullable() -> bool {
2528 false
2529 }
2530
2531 fn fallible() -> bool {
2532 false
2533 }
2534
2535 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2536 match res {
2537 Ok(Datum::UInt32(a)) => Ok(RegProc(a)),
2538 _ => Err(res),
2539 }
2540 }
2541
2542 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2543 Ok(Datum::UInt32(self.0))
2544 }
2545}
2546
2547impl AsColumnType for RegType {
2548 fn as_column_type() -> SqlColumnType {
2549 SqlScalarType::RegType.nullable(false)
2550 }
2551}
2552
2553impl<'a, E> DatumType<'a, E> for RegType {
2554 fn nullable() -> bool {
2555 false
2556 }
2557
2558 fn fallible() -> bool {
2559 false
2560 }
2561
2562 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2563 match res {
2564 Ok(Datum::UInt32(a)) => Ok(RegType(a)),
2565 _ => Err(res),
2566 }
2567 }
2568
2569 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2570 Ok(Datum::UInt32(self.0))
2571 }
2572}
2573
2574impl<S> AsColumnType for Char<S>
2575where
2576 S: AsRef<str>,
2577{
2578 fn as_column_type() -> SqlColumnType {
2579 SqlScalarType::Char { length: None }.nullable(false)
2580 }
2581}
2582
2583impl<'a, E> DatumType<'a, E> for Char<&'a str> {
2584 fn nullable() -> bool {
2585 false
2586 }
2587
2588 fn fallible() -> bool {
2589 false
2590 }
2591
2592 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2593 match res {
2594 Ok(Datum::String(a)) => Ok(Char(a)),
2595 _ => Err(res),
2596 }
2597 }
2598
2599 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2600 Ok(Datum::String(self.0))
2601 }
2602}
2603
2604impl<'a, E> DatumType<'a, E> for Char<String> {
2605 fn nullable() -> bool {
2606 false
2607 }
2608
2609 fn fallible() -> bool {
2610 false
2611 }
2612
2613 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2614 match res {
2615 Ok(Datum::String(a)) => Ok(Char(a.to_owned())),
2616 _ => Err(res),
2617 }
2618 }
2619
2620 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2621 Ok(Datum::String(temp_storage.push_string(self.0)))
2622 }
2623}
2624
2625impl<S> AsColumnType for VarChar<S>
2626where
2627 S: AsRef<str>,
2628{
2629 fn as_column_type() -> SqlColumnType {
2630 SqlScalarType::Char { length: None }.nullable(false)
2631 }
2632}
2633
2634impl<'a, E> DatumType<'a, E> for VarChar<&'a str> {
2635 fn nullable() -> bool {
2636 false
2637 }
2638
2639 fn fallible() -> bool {
2640 false
2641 }
2642
2643 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2644 match res {
2645 Ok(Datum::String(a)) => Ok(VarChar(a)),
2646 _ => Err(res),
2647 }
2648 }
2649
2650 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2651 Ok(Datum::String(self.0))
2652 }
2653}
2654
2655impl<'a, E> DatumType<'a, E> for VarChar<String> {
2656 fn nullable() -> bool {
2657 false
2658 }
2659
2660 fn fallible() -> bool {
2661 false
2662 }
2663
2664 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2665 match res {
2666 Ok(Datum::String(a)) => Ok(VarChar(a.to_owned())),
2667 _ => Err(res),
2668 }
2669 }
2670
2671 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2672 Ok(Datum::String(temp_storage.push_string(self.0)))
2673 }
2674}
2675
2676impl<'a, E> DatumType<'a, E> for Jsonb {
2677 fn nullable() -> bool {
2678 false
2679 }
2680
2681 fn fallible() -> bool {
2682 false
2683 }
2684
2685 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2686 Ok(JsonbRef::try_from_result(res)?.to_owned())
2687 }
2688
2689 fn into_result(self, temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2690 Ok(temp_storage.push_unary_row(self.into_row()))
2691 }
2692}
2693
2694impl AsColumnType for Jsonb {
2695 fn as_column_type() -> SqlColumnType {
2696 SqlScalarType::Jsonb.nullable(false)
2697 }
2698}
2699
2700impl<'a, E> DatumType<'a, E> for JsonbRef<'a> {
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(
2712 d @ (Datum::JsonNull
2713 | Datum::True
2714 | Datum::False
2715 | Datum::Numeric(_)
2716 | Datum::String(_)
2717 | Datum::List(_)
2718 | Datum::Map(_)),
2719 ) => Ok(JsonbRef::from_datum(d)),
2720 _ => Err(res),
2721 }
2722 }
2723
2724 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2725 Ok(self.into_datum())
2726 }
2727}
2728
2729impl<'a> AsColumnType for JsonbRef<'a> {
2730 fn as_column_type() -> SqlColumnType {
2731 SqlScalarType::Jsonb.nullable(false)
2732 }
2733}
2734
2735impl AsColumnType for MzAclItem {
2736 fn as_column_type() -> SqlColumnType {
2737 SqlScalarType::MzAclItem.nullable(false)
2738 }
2739}
2740
2741impl<'a, E> DatumType<'a, E> for MzAclItem {
2742 fn nullable() -> bool {
2743 false
2744 }
2745
2746 fn fallible() -> bool {
2747 false
2748 }
2749
2750 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2751 match res {
2752 Ok(Datum::MzAclItem(mz_acl_item)) => Ok(mz_acl_item),
2753 _ => Err(res),
2754 }
2755 }
2756
2757 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2758 Ok(Datum::MzAclItem(self))
2759 }
2760}
2761
2762impl AsColumnType for AclItem {
2763 fn as_column_type() -> SqlColumnType {
2764 SqlScalarType::AclItem.nullable(false)
2765 }
2766}
2767
2768impl<'a, E> DatumType<'a, E> for AclItem {
2769 fn nullable() -> bool {
2770 false
2771 }
2772
2773 fn fallible() -> bool {
2774 false
2775 }
2776
2777 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2778 match res {
2779 Ok(Datum::AclItem(acl_item)) => Ok(acl_item),
2780 _ => Err(res),
2781 }
2782 }
2783
2784 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2785 Ok(Datum::AclItem(self))
2786 }
2787}
2788
2789impl AsColumnType for CheckedTimestamp<NaiveDateTime> {
2790 fn as_column_type() -> SqlColumnType {
2791 SqlScalarType::Timestamp { precision: None }.nullable(false)
2792 }
2793}
2794
2795impl<'a, E> DatumType<'a, E> for CheckedTimestamp<NaiveDateTime> {
2796 fn nullable() -> bool {
2797 false
2798 }
2799
2800 fn fallible() -> bool {
2801 false
2802 }
2803
2804 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2805 match res {
2806 Ok(Datum::Timestamp(a)) => Ok(a),
2807 _ => Err(res),
2808 }
2809 }
2810
2811 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2812 Ok(Datum::Timestamp(self))
2813 }
2814}
2815
2816impl AsColumnType for CheckedTimestamp<DateTime<Utc>> {
2817 fn as_column_type() -> SqlColumnType {
2818 SqlScalarType::TimestampTz { precision: None }.nullable(false)
2819 }
2820}
2821
2822impl<'a, E> DatumType<'a, E> for CheckedTimestamp<DateTime<Utc>> {
2823 fn nullable() -> bool {
2824 false
2825 }
2826
2827 fn fallible() -> bool {
2828 false
2829 }
2830
2831 fn try_from_result(res: Result<Datum<'a>, E>) -> Result<Self, Result<Datum<'a>, E>> {
2832 match res {
2833 Ok(Datum::TimestampTz(a)) => Ok(a),
2834 _ => Err(res),
2835 }
2836 }
2837
2838 fn into_result(self, _temp_storage: &'a RowArena) -> Result<Datum<'a>, E> {
2839 Ok(Datum::TimestampTz(self))
2840 }
2841}
2842
2843impl SqlScalarType {
2844 pub fn unwrap_numeric_max_scale(&self) -> Option<NumericMaxScale> {
2850 match self {
2851 SqlScalarType::Numeric { max_scale } => *max_scale,
2852 _ => panic!("SqlScalarType::unwrap_numeric_scale called on {:?}", self),
2853 }
2854 }
2855
2856 pub fn unwrap_timestamp_precision(&self) -> Option<TimestampPrecision> {
2863 match self {
2864 SqlScalarType::Timestamp { precision } | SqlScalarType::TimestampTz { precision } => {
2865 *precision
2866 }
2867 _ => panic!(
2868 "SqlScalarType::unwrap_timestamp_precision called on {:?}",
2869 self
2870 ),
2871 }
2872 }
2873
2874 pub fn unwrap_list_element_type(&self) -> &SqlScalarType {
2880 match self {
2881 SqlScalarType::List { element_type, .. } => element_type,
2882 _ => panic!(
2883 "SqlScalarType::unwrap_list_element_type called on {:?}",
2884 self
2885 ),
2886 }
2887 }
2888
2889 pub fn unwrap_list_nth_layer_type(&self, layer: usize) -> &SqlScalarType {
2902 if layer == 0 {
2903 return self;
2904 }
2905 match self {
2906 SqlScalarType::List { element_type, .. } => {
2907 element_type.unwrap_list_nth_layer_type(layer - 1)
2908 }
2909 _ => panic!(
2910 "SqlScalarType::unwrap_list_nth_layer_type called on {:?}",
2911 self
2912 ),
2913 }
2914 }
2915
2916 pub fn unwrap_record_element_type(&self) -> Vec<&SqlScalarType> {
2922 match self {
2923 SqlScalarType::Record { fields, .. } => {
2924 fields.iter().map(|(_, t)| &t.scalar_type).collect_vec()
2925 }
2926 _ => panic!(
2927 "SqlScalarType::unwrap_record_element_type called on {:?}",
2928 self
2929 ),
2930 }
2931 }
2932
2933 pub fn unwrap_record_element_column_type(&self) -> Vec<&SqlColumnType> {
2939 match self {
2940 SqlScalarType::Record { fields, .. } => fields.iter().map(|(_, t)| t).collect_vec(),
2941 _ => panic!(
2942 "SqlScalarType::unwrap_record_element_column_type called on {:?}",
2943 self
2944 ),
2945 }
2946 }
2947
2948 pub fn unwrap_list_n_layers(&self) -> usize {
2955 let mut descender = self.unwrap_list_element_type();
2956 let mut layers = 1;
2957
2958 while let SqlScalarType::List { element_type, .. } = descender {
2959 layers += 1;
2960 descender = element_type;
2961 }
2962
2963 layers
2964 }
2965
2966 pub fn without_modifiers(&self) -> SqlScalarType {
2970 use SqlScalarType::*;
2971 match self {
2972 List {
2973 element_type,
2974 custom_id: None,
2975 } => List {
2976 element_type: Box::new(element_type.without_modifiers()),
2977 custom_id: None,
2978 },
2979 Map {
2980 value_type,
2981 custom_id: None,
2982 } => Map {
2983 value_type: Box::new(value_type.without_modifiers()),
2984 custom_id: None,
2985 },
2986 Record {
2987 fields,
2988 custom_id: None,
2989 } => {
2990 let fields = fields
2991 .iter()
2992 .map(|(column_name, column_type)| {
2993 (
2994 column_name.clone(),
2995 SqlColumnType {
2996 scalar_type: column_type.scalar_type.without_modifiers(),
2997 nullable: column_type.nullable,
2998 },
2999 )
3000 })
3001 .collect();
3002 Record {
3003 fields,
3004 custom_id: None,
3005 }
3006 }
3007 Array(a) => Array(Box::new(a.without_modifiers())),
3008 Numeric { .. } => Numeric { max_scale: None },
3009 Char { .. } => Char { length: None },
3012 VarChar { .. } => VarChar { max_length: None },
3013 Range { element_type } => Range {
3014 element_type: Box::new(element_type.without_modifiers()),
3015 },
3016 v => v.clone(),
3017 }
3018 }
3019
3020 pub fn unwrap_array_element_type(&self) -> &SqlScalarType {
3029 match self {
3030 SqlScalarType::Array(s) => &**s,
3031 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3032 _ => panic!(
3033 "SqlScalarType::unwrap_array_element_type called on {:?}",
3034 self
3035 ),
3036 }
3037 }
3038
3039 pub fn unwrap_collection_element_type(&self) -> &SqlScalarType {
3047 match self {
3048 SqlScalarType::Array(element_type) => element_type,
3049 SqlScalarType::Int2Vector => &SqlScalarType::Int16,
3050 SqlScalarType::List { element_type, .. } => element_type,
3051 _ => panic!(
3052 "SqlScalarType::unwrap_collection_element_type called on {:?}",
3053 self
3054 ),
3055 }
3056 }
3057
3058 pub fn unwrap_map_value_type(&self) -> &SqlScalarType {
3064 match self {
3065 SqlScalarType::Map { value_type, .. } => &**value_type,
3066 _ => panic!("SqlScalarType::unwrap_map_value_type called on {:?}", self),
3067 }
3068 }
3069
3070 pub fn unwrap_char_length(&self) -> Option<CharLength> {
3076 match self {
3077 SqlScalarType::Char { length, .. } => *length,
3078 _ => panic!("SqlScalarType::unwrap_char_length called on {:?}", self),
3079 }
3080 }
3081
3082 pub fn unwrap_varchar_max_length(&self) -> Option<VarCharMaxLength> {
3088 match self {
3089 SqlScalarType::VarChar { max_length, .. } => *max_length,
3090 _ => panic!(
3091 "SqlScalarType::unwrap_varchar_max_length called on {:?}",
3092 self
3093 ),
3094 }
3095 }
3096
3097 pub fn unwrap_range_element_type(&self) -> &SqlScalarType {
3103 match self {
3104 SqlScalarType::Range { element_type } => &**element_type,
3105 _ => panic!(
3106 "SqlScalarType::unwrap_range_element_type called on {:?}",
3107 self
3108 ),
3109 }
3110 }
3111
3112 pub fn near_match(&self) -> Option<&'static SqlScalarType> {
3136 match self {
3137 SqlScalarType::UInt16 => Some(&SqlScalarType::Int32),
3138 SqlScalarType::UInt32 => Some(&SqlScalarType::Int64),
3139 SqlScalarType::UInt64 => Some(&SqlScalarType::Numeric { max_scale: None }),
3140 _ => None,
3141 }
3142 }
3143
3144 pub const fn nullable(self, nullable: bool) -> SqlColumnType {
3147 SqlColumnType {
3148 nullable,
3149 scalar_type: self,
3150 }
3151 }
3152
3153 pub fn is_vec(&self) -> bool {
3157 matches!(
3158 self,
3159 SqlScalarType::Array(_) | SqlScalarType::Int2Vector | SqlScalarType::List { .. }
3160 )
3161 }
3162
3163 pub fn is_custom_type(&self) -> bool {
3164 use SqlScalarType::*;
3165 match self {
3166 List {
3167 element_type: t,
3168 custom_id,
3169 }
3170 | Map {
3171 value_type: t,
3172 custom_id,
3173 } => custom_id.is_some() || t.is_custom_type(),
3174 Record {
3175 fields, custom_id, ..
3176 } => {
3177 custom_id.is_some()
3178 || fields
3179 .iter()
3180 .map(|(_, t)| t)
3181 .any(|t| t.scalar_type.is_custom_type())
3182 }
3183 _ => false,
3184 }
3185 }
3186
3187 pub fn base_eq(&self, other: &SqlScalarType) -> bool {
3200 self.eq_inner(other, false)
3201 }
3202
3203 pub fn structural_eq(&self, other: &SqlScalarType) -> bool {
3206 self.eq_inner(other, true)
3207 }
3208
3209 pub fn eq_inner(&self, other: &SqlScalarType, structure_only: bool) -> bool {
3210 use SqlScalarType::*;
3211 match (self, other) {
3212 (
3213 List {
3214 element_type: l,
3215 custom_id: oid_l,
3216 },
3217 List {
3218 element_type: r,
3219 custom_id: oid_r,
3220 },
3221 )
3222 | (
3223 Map {
3224 value_type: l,
3225 custom_id: oid_l,
3226 },
3227 Map {
3228 value_type: r,
3229 custom_id: oid_r,
3230 },
3231 ) => l.eq_inner(r, structure_only) && (oid_l == oid_r || structure_only),
3232 (Array(a), Array(b)) | (Range { element_type: a }, Range { element_type: b }) => {
3233 a.eq_inner(b, structure_only)
3234 }
3235 (
3236 Record {
3237 fields: fields_a,
3238 custom_id: oid_a,
3239 },
3240 Record {
3241 fields: fields_b,
3242 custom_id: oid_b,
3243 },
3244 ) => {
3245 (oid_a == oid_b || structure_only)
3246 && fields_a.len() == fields_b.len()
3247 && fields_a
3248 .iter()
3249 .zip_eq(fields_b)
3250 .all(|(a, b)| {
3252 (a.0 == b.0 || structure_only)
3253 && a.1.scalar_type.eq_inner(&b.1.scalar_type, structure_only)
3254 })
3255 }
3256 (s, o) => SqlScalarBaseType::from(s) == SqlScalarBaseType::from(o),
3257 }
3258 }
3259
3260 pub fn interesting_datums(&self) -> impl Iterator<Item = Datum<'static>> {
3262 static BOOL: LazyLock<Row> =
3268 LazyLock::new(|| Row::pack_slice(&[Datum::True, Datum::False]));
3269 static INT16: LazyLock<Row> = LazyLock::new(|| {
3270 Row::pack_slice(&[
3271 Datum::Int16(0),
3272 Datum::Int16(1),
3273 Datum::Int16(-1),
3274 Datum::Int16(i16::MIN),
3275 Datum::Int16(i16::MIN + 1),
3276 Datum::Int16(i16::MAX),
3277 Datum::Int16(127),
3285 Datum::Int16(128),
3286 ])
3287 });
3288 static INT32: LazyLock<Row> = LazyLock::new(|| {
3289 Row::pack_slice(&[
3290 Datum::Int32(0),
3291 Datum::Int32(1),
3292 Datum::Int32(-1),
3293 Datum::Int32(i32::MIN),
3294 Datum::Int32(i32::MIN + 1),
3295 Datum::Int32(i32::MAX),
3296 Datum::Int32(32767),
3300 Datum::Int32(32768),
3301 ])
3302 });
3303 static INT64: LazyLock<Row> = LazyLock::new(|| {
3304 Row::pack_slice(&[
3305 Datum::Int64(0),
3306 Datum::Int64(1),
3307 Datum::Int64(-1),
3308 Datum::Int64(i64::MIN),
3309 Datum::Int64(i64::MIN + 1),
3310 Datum::Int64(i64::MAX),
3311 Datum::Int64(2147483647),
3315 Datum::Int64(2147483648),
3316 ])
3317 });
3318 static UINT16: LazyLock<Row> = LazyLock::new(|| {
3319 Row::pack_slice(&[
3320 Datum::UInt16(0),
3321 Datum::UInt16(1),
3322 Datum::UInt16(u16::MAX),
3323 Datum::UInt16(255),
3327 Datum::UInt16(256),
3328 ])
3329 });
3330 static UINT32: LazyLock<Row> = LazyLock::new(|| {
3331 Row::pack_slice(&[
3332 Datum::UInt32(0),
3333 Datum::UInt32(1),
3334 Datum::UInt32(u32::MAX),
3335 Datum::UInt32(32767),
3339 Datum::UInt32(32768),
3340 ])
3341 });
3342 static UINT64: LazyLock<Row> = LazyLock::new(|| {
3343 Row::pack_slice(&[
3344 Datum::UInt64(0),
3345 Datum::UInt64(1),
3346 Datum::UInt64(u64::MAX),
3347 Datum::UInt64(2147483647),
3351 Datum::UInt64(2147483648),
3352 ])
3353 });
3354 static FLOAT32: LazyLock<Row> = LazyLock::new(|| {
3355 Row::pack_slice(&[
3356 Datum::Float32(OrderedFloat(0.0)),
3357 Datum::Float32(OrderedFloat(1.0)),
3358 Datum::Float32(OrderedFloat(-1.0)),
3359 Datum::Float32(OrderedFloat(f32::MIN)),
3360 Datum::Float32(OrderedFloat(f32::MIN_POSITIVE)),
3361 Datum::Float32(OrderedFloat(f32::MAX)),
3362 Datum::Float32(OrderedFloat(f32::EPSILON)),
3363 Datum::Float32(OrderedFloat(f32::NAN)),
3364 Datum::Float32(OrderedFloat(f32::INFINITY)),
3365 Datum::Float32(OrderedFloat(f32::NEG_INFINITY)),
3366 ])
3367 });
3368 static FLOAT64: LazyLock<Row> = LazyLock::new(|| {
3369 Row::pack_slice(&[
3370 Datum::Float64(OrderedFloat(0.0)),
3371 Datum::Float64(OrderedFloat(1.0)),
3372 Datum::Float64(OrderedFloat(-1.0)),
3373 Datum::Float64(OrderedFloat(f64::MIN)),
3374 Datum::Float64(OrderedFloat(f64::MIN_POSITIVE)),
3375 Datum::Float64(OrderedFloat(f64::MAX)),
3376 Datum::Float64(OrderedFloat(f64::EPSILON)),
3377 Datum::Float64(OrderedFloat(f64::NAN)),
3378 Datum::Float64(OrderedFloat(f64::INFINITY)),
3379 Datum::Float64(OrderedFloat(f64::NEG_INFINITY)),
3380 ])
3381 });
3382 static NUMERIC: LazyLock<Row> = LazyLock::new(|| {
3383 cfg_if::cfg_if! {
3384 if #[cfg(miri)] {
3386 Row::pack_slice(&[])
3387 } else {
3388 Row::pack_slice(&[
3389 Datum::Numeric(OrderedDecimal(Numeric::from(0.0))),
3390 Datum::Numeric(OrderedDecimal(Numeric::from(1.0))),
3391 Datum::Numeric(OrderedDecimal(Numeric::from(-1.0))),
3392 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN))),
3393 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MIN_POSITIVE))),
3394 Datum::Numeric(OrderedDecimal(Numeric::from(f64::MAX))),
3395 Datum::Numeric(OrderedDecimal(Numeric::from(f64::EPSILON))),
3396 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NAN))),
3397 Datum::Numeric(OrderedDecimal(Numeric::from(f64::INFINITY))),
3398 Datum::Numeric(OrderedDecimal(Numeric::from(f64::NEG_INFINITY))),
3399 ])
3400 }
3401 }
3402 });
3403 static DATE: LazyLock<Row> = LazyLock::new(|| {
3404 Row::pack_slice(&[
3405 Datum::Date(Date::from_pg_epoch(0).unwrap()),
3406 Datum::Date(Date::from_pg_epoch(Date::LOW_DAYS).unwrap()),
3407 Datum::Date(Date::from_pg_epoch(Date::HIGH_DAYS).unwrap()),
3408 ])
3409 });
3410 static TIME: LazyLock<Row> = LazyLock::new(|| {
3411 Row::pack_slice(&[
3412 Datum::Time(NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap()),
3413 Datum::Time(NaiveTime::from_hms_micro_opt(23, 59, 59, 999_999).unwrap()),
3414 ])
3415 });
3416 static TIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3417 Row::pack_slice(&[
3418 Datum::Timestamp(
3419 DateTime::from_timestamp(0, 0)
3420 .unwrap()
3421 .naive_utc()
3422 .try_into()
3423 .unwrap(),
3424 ),
3425 Datum::Timestamp(
3426 crate::adt::timestamp::LOW_DATE
3427 .and_hms_opt(0, 0, 0)
3428 .unwrap()
3429 .try_into()
3430 .unwrap(),
3431 ),
3432 Datum::Timestamp(
3433 crate::adt::timestamp::HIGH_DATE
3434 .and_hms_opt(23, 59, 59)
3435 .unwrap()
3436 .try_into()
3437 .unwrap(),
3438 ),
3439 Datum::Timestamp(
3441 DateTime::from_timestamp(0, 123456789)
3442 .unwrap()
3443 .naive_utc()
3444 .try_into()
3445 .unwrap(),
3446 ),
3447 Datum::Timestamp(
3449 CheckedTimestamp::from_timestamplike(
3450 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
3451 .unwrap()
3452 .and_hms_milli_opt(23, 59, 59, 1234)
3453 .unwrap(),
3454 )
3455 .unwrap(),
3456 ),
3457 ])
3458 });
3459 static TIMESTAMPTZ: LazyLock<Row> = LazyLock::new(|| {
3460 Row::pack_slice(&[
3461 Datum::TimestampTz(DateTime::from_timestamp(0, 0).unwrap().try_into().unwrap()),
3462 Datum::TimestampTz(
3463 DateTime::from_naive_utc_and_offset(
3464 crate::adt::timestamp::LOW_DATE
3465 .and_hms_opt(0, 0, 0)
3466 .unwrap(),
3467 Utc,
3468 )
3469 .try_into()
3470 .unwrap(),
3471 ),
3472 Datum::TimestampTz(
3473 DateTime::from_naive_utc_and_offset(
3474 crate::adt::timestamp::HIGH_DATE
3475 .and_hms_opt(23, 59, 59)
3476 .unwrap(),
3477 Utc,
3478 )
3479 .try_into()
3480 .unwrap(),
3481 ),
3482 Datum::TimestampTz(
3484 DateTime::from_timestamp(0, 123456789)
3485 .unwrap()
3486 .try_into()
3487 .unwrap(),
3488 ),
3489 ])
3490 });
3491 static INTERVAL: LazyLock<Row> = LazyLock::new(|| {
3492 Row::pack_slice(&[
3493 Datum::Interval(Interval::new(0, 0, 0)),
3494 Datum::Interval(Interval::new(1, 1, 1)),
3495 Datum::Interval(Interval::new(-1, -1, -1)),
3496 Datum::Interval(Interval::new(1, 0, 0)),
3497 Datum::Interval(Interval::new(0, 1, 0)),
3498 Datum::Interval(Interval::new(0, 0, 1)),
3499 Datum::Interval(Interval::new(-1, 0, 0)),
3500 Datum::Interval(Interval::new(0, -1, 0)),
3501 Datum::Interval(Interval::new(0, 0, -1)),
3502 Datum::Interval(Interval::new(i32::MIN, i32::MIN, i64::MIN)),
3503 Datum::Interval(Interval::new(i32::MAX, i32::MAX, i64::MAX)),
3504 Datum::Interval(Interval::new(i32::MIN, 0, 0)),
3505 Datum::Interval(Interval::new(i32::MAX, 0, 0)),
3506 Datum::Interval(Interval::new(0, i32::MIN, 0)),
3507 Datum::Interval(Interval::new(0, i32::MAX, 0)),
3508 Datum::Interval(Interval::new(0, 0, i64::MIN)),
3509 Datum::Interval(Interval::new(0, 0, i64::MAX)),
3510 ])
3511 });
3512 static PGLEGACYCHAR: LazyLock<Row> =
3513 LazyLock::new(|| Row::pack_slice(&[Datum::UInt8(u8::MIN), Datum::UInt8(u8::MAX)]));
3514 static PGLEGACYNAME: LazyLock<Row> = LazyLock::new(|| {
3515 Row::pack_slice(&[
3516 Datum::String(""),
3517 Datum::String(" "),
3518 Datum::String("'"),
3519 Datum::String("\""),
3520 Datum::String("."),
3521 Datum::String(&"x".repeat(64)),
3522 ])
3523 });
3524 static BYTES: LazyLock<Row> = LazyLock::new(|| {
3525 Row::pack_slice(&[Datum::Bytes(&[]), Datum::Bytes(&[0]), Datum::Bytes(&[255])])
3526 });
3527 static STRING: LazyLock<Row> = LazyLock::new(|| {
3528 Row::pack_slice(&[
3529 Datum::String(""),
3530 Datum::String(" "),
3531 Datum::String("'"),
3532 Datum::String("\""),
3533 Datum::String("."),
3534 Datum::String("2015-09-18T23:56:04.123Z"),
3535 Datum::String(&"x".repeat(100)),
3536 Datum::String("JAPAN"),
3538 Datum::String("1,2,3"),
3539 Datum::String("\r\n"),
3540 Datum::String("\"\""),
3541 ])
3542 });
3543 static CHAR: LazyLock<Row> = LazyLock::new(|| {
3544 Row::pack_slice(&[
3545 Datum::String(" "),
3546 Datum::String("'"),
3547 Datum::String("\""),
3548 Datum::String("."),
3549 Datum::String(","),
3550 Datum::String("\t"),
3551 Datum::String("\n"),
3552 Datum::String("\r"),
3553 Datum::String("\\"),
3554 Datum::String(std::str::from_utf8(b"\x00").unwrap()),
3556 Datum::String(std::str::from_utf8(b"\x02").unwrap()),
3558 Datum::String(std::str::from_utf8(b"\x03").unwrap()),
3560 Datum::String(std::str::from_utf8(b"\x08").unwrap()),
3562 Datum::String(std::str::from_utf8(b"\x1B").unwrap()),
3564 Datum::String(std::str::from_utf8(b"\x7F").unwrap()),
3566 ])
3567 });
3568 static JSONB: LazyLock<Row> = LazyLock::new(|| {
3569 let mut datums = vec![Datum::True, Datum::False, Datum::JsonNull];
3570 datums.extend(STRING.iter());
3571 datums.extend(NUMERIC.iter().filter(|n| {
3572 let Datum::Numeric(n) = n else {
3573 panic!("expected Numeric, found {n:?}");
3574 };
3575 !(n.0.is_nan() || n.0.is_infinite())
3577 }));
3578 Row::pack_slice(&datums)
3580 });
3581 static UUID: LazyLock<Row> = LazyLock::new(|| {
3582 Row::pack_slice(&[
3583 Datum::Uuid(Uuid::from_u128(u128::MIN)),
3584 Datum::Uuid(Uuid::from_u128(u128::MAX)),
3585 ])
3586 });
3587 static ARRAY: LazyLock<BTreeMap<&'static SqlScalarType, Row>> = LazyLock::new(|| {
3588 let generate_row = |inner_type: &SqlScalarType| {
3589 let datums: Vec<_> = inner_type.interesting_datums().collect();
3590
3591 let mut row = Row::default();
3592 row.packer()
3593 .try_push_array::<_, Datum<'static>>(
3594 &[ArrayDimension {
3595 lower_bound: 1,
3596 length: 0,
3597 }],
3598 [],
3599 )
3600 .expect("failed to push empty array");
3601 row.packer()
3602 .try_push_array(
3603 &[ArrayDimension {
3604 lower_bound: 1,
3605 length: datums.len(),
3606 }],
3607 datums,
3608 )
3609 .expect("failed to push array");
3610
3611 row
3612 };
3613
3614 SqlScalarType::enumerate()
3615 .into_iter()
3616 .filter(|ty| !matches!(ty, SqlScalarType::Array(_)))
3617 .map(|ty| (ty, generate_row(ty)))
3618 .collect()
3619 });
3620 static EMPTY_ARRAY: LazyLock<Row> = LazyLock::new(|| {
3621 let mut row = Row::default();
3622 row.packer()
3623 .try_push_array::<_, Datum<'static>>(
3624 &[ArrayDimension {
3625 lower_bound: 1,
3626 length: 0,
3627 }],
3628 [],
3629 )
3630 .expect("failed to push empty array");
3631 row
3632 });
3633 static LIST: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3634 static RECORD: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3635 static OID: LazyLock<Row> =
3636 LazyLock::new(|| Row::pack_slice(&[Datum::UInt32(u32::MIN), Datum::UInt32(u32::MAX)]));
3637 static MAP: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3638 static INT2VECTOR: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3639 static MZTIMESTAMP: LazyLock<Row> = LazyLock::new(|| {
3640 Row::pack_slice(&[
3641 Datum::MzTimestamp(crate::Timestamp::MIN),
3642 Datum::MzTimestamp(crate::Timestamp::MAX),
3643 ])
3644 });
3645 static RANGE: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3646 static MZACLITEM: LazyLock<Row> = LazyLock::new(|| {
3647 Row::pack_slice(&[
3648 Datum::MzAclItem(MzAclItem {
3649 grantee: RoleId::Public,
3650 grantor: RoleId::Public,
3651 acl_mode: AclMode::empty(),
3652 }),
3653 Datum::MzAclItem(MzAclItem {
3654 grantee: RoleId::Public,
3655 grantor: RoleId::Public,
3656 acl_mode: AclMode::all(),
3657 }),
3658 Datum::MzAclItem(MzAclItem {
3659 grantee: RoleId::User(42),
3660 grantor: RoleId::Public,
3661 acl_mode: AclMode::empty(),
3662 }),
3663 Datum::MzAclItem(MzAclItem {
3664 grantee: RoleId::User(42),
3665 grantor: RoleId::Public,
3666 acl_mode: AclMode::all(),
3667 }),
3668 Datum::MzAclItem(MzAclItem {
3669 grantee: RoleId::Public,
3670 grantor: RoleId::User(42),
3671 acl_mode: AclMode::empty(),
3672 }),
3673 Datum::MzAclItem(MzAclItem {
3674 grantee: RoleId::Public,
3675 grantor: RoleId::User(42),
3676 acl_mode: AclMode::all(),
3677 }),
3678 ])
3679 });
3680 static ACLITEM: LazyLock<Row> = LazyLock::new(|| Row::pack_slice(&[]));
3682
3683 let iter: Box<dyn Iterator<Item = Datum<'static>>> = match self {
3684 SqlScalarType::Bool => Box::new((*BOOL).iter()),
3685 SqlScalarType::Int16 => Box::new((*INT16).iter()),
3686 SqlScalarType::Int32 => Box::new((*INT32).iter()),
3687 SqlScalarType::Int64 => Box::new((*INT64).iter()),
3688 SqlScalarType::UInt16 => Box::new((*UINT16).iter()),
3689 SqlScalarType::UInt32 => Box::new((*UINT32).iter()),
3690 SqlScalarType::UInt64 => Box::new((*UINT64).iter()),
3691 SqlScalarType::Float32 => Box::new((*FLOAT32).iter()),
3692 SqlScalarType::Float64 => Box::new((*FLOAT64).iter()),
3693 SqlScalarType::Numeric { .. } => Box::new((*NUMERIC).iter()),
3694 SqlScalarType::Date => Box::new((*DATE).iter()),
3695 SqlScalarType::Time => Box::new((*TIME).iter()),
3696 SqlScalarType::Timestamp { .. } => Box::new((*TIMESTAMP).iter()),
3697 SqlScalarType::TimestampTz { .. } => Box::new((*TIMESTAMPTZ).iter()),
3698 SqlScalarType::Interval => Box::new((*INTERVAL).iter()),
3699 SqlScalarType::PgLegacyChar => Box::new((*PGLEGACYCHAR).iter()),
3700 SqlScalarType::PgLegacyName => Box::new((*PGLEGACYNAME).iter()),
3701 SqlScalarType::Bytes => Box::new((*BYTES).iter()),
3702 SqlScalarType::String => Box::new((*STRING).iter().chain((*CHAR).iter())),
3703 SqlScalarType::Char { .. } => Box::new((*CHAR).iter()),
3704 SqlScalarType::VarChar { .. } => Box::new((*STRING).iter().chain((*CHAR).iter())),
3705 SqlScalarType::Jsonb => Box::new((*JSONB).iter()),
3706 SqlScalarType::Uuid => Box::new((*UUID).iter()),
3707 SqlScalarType::Array(inner_type) => {
3708 if matches!(inner_type.as_ref(), SqlScalarType::Array(_)) {
3709 panic!("SqlScalarType::Array cannot have a nested Array");
3710 }
3711
3712 Box::new(
3713 (*ARRAY)
3714 .get(inner_type.as_ref())
3715 .unwrap_or(&*EMPTY_ARRAY)
3716 .iter(),
3717 )
3718 }
3719 SqlScalarType::List { .. } => Box::new((*LIST).iter()),
3720 SqlScalarType::Record { .. } => Box::new((*RECORD).iter()),
3721 SqlScalarType::Oid => Box::new((*OID).iter()),
3722 SqlScalarType::Map { .. } => Box::new((*MAP).iter()),
3723 SqlScalarType::RegProc => Box::new((*OID).iter()),
3724 SqlScalarType::RegType => Box::new((*OID).iter()),
3725 SqlScalarType::RegClass => Box::new((*OID).iter()),
3726 SqlScalarType::Int2Vector => Box::new((*INT2VECTOR).iter()),
3727 SqlScalarType::MzTimestamp => Box::new((*MZTIMESTAMP).iter()),
3728 SqlScalarType::Range { .. } => Box::new((*RANGE).iter()),
3729 SqlScalarType::MzAclItem { .. } => Box::new((*MZACLITEM).iter()),
3730 SqlScalarType::AclItem { .. } => Box::new((*ACLITEM).iter()),
3731 };
3732
3733 iter
3734 }
3735
3736 pub fn enumerate() -> &'static [Self] {
3739 &[
3742 SqlScalarType::Bool,
3743 SqlScalarType::Int16,
3744 SqlScalarType::Int32,
3745 SqlScalarType::Int64,
3746 SqlScalarType::UInt16,
3747 SqlScalarType::UInt32,
3748 SqlScalarType::UInt64,
3749 SqlScalarType::Float32,
3750 SqlScalarType::Float64,
3751 SqlScalarType::Numeric {
3752 max_scale: Some(NumericMaxScale(
3753 crate::adt::numeric::NUMERIC_DATUM_MAX_PRECISION,
3754 )),
3755 },
3756 SqlScalarType::Date,
3757 SqlScalarType::Time,
3758 SqlScalarType::Timestamp {
3759 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3760 },
3761 SqlScalarType::Timestamp {
3762 precision: Some(TimestampPrecision(0)),
3763 },
3764 SqlScalarType::Timestamp { precision: None },
3765 SqlScalarType::TimestampTz {
3766 precision: Some(TimestampPrecision(crate::adt::timestamp::MAX_PRECISION)),
3767 },
3768 SqlScalarType::TimestampTz {
3769 precision: Some(TimestampPrecision(0)),
3770 },
3771 SqlScalarType::TimestampTz { precision: None },
3772 SqlScalarType::Interval,
3773 SqlScalarType::PgLegacyChar,
3774 SqlScalarType::Bytes,
3775 SqlScalarType::String,
3776 SqlScalarType::Char {
3777 length: Some(CharLength(1)),
3778 },
3779 SqlScalarType::VarChar { max_length: None },
3780 SqlScalarType::Jsonb,
3781 SqlScalarType::Uuid,
3782 SqlScalarType::Oid,
3783 SqlScalarType::RegProc,
3784 SqlScalarType::RegType,
3785 SqlScalarType::RegClass,
3786 SqlScalarType::Int2Vector,
3787 SqlScalarType::MzTimestamp,
3788 SqlScalarType::MzAclItem,
3789 ]
3810 }
3811
3812 pub fn array_of_self_elem_type(self) -> Result<SqlScalarType, SqlScalarType> {
3817 match self {
3818 t @ (SqlScalarType::AclItem
3819 | SqlScalarType::Bool
3820 | SqlScalarType::Int16
3821 | SqlScalarType::Int32
3822 | SqlScalarType::Int64
3823 | SqlScalarType::UInt16
3824 | SqlScalarType::UInt32
3825 | SqlScalarType::UInt64
3826 | SqlScalarType::Float32
3827 | SqlScalarType::Float64
3828 | SqlScalarType::Numeric { .. }
3829 | SqlScalarType::Date
3830 | SqlScalarType::Time
3831 | SqlScalarType::Timestamp { .. }
3832 | SqlScalarType::TimestampTz { .. }
3833 | SqlScalarType::Interval
3834 | SqlScalarType::PgLegacyChar
3835 | SqlScalarType::PgLegacyName
3836 | SqlScalarType::Bytes
3837 | SqlScalarType::String
3838 | SqlScalarType::VarChar { .. }
3839 | SqlScalarType::Jsonb
3840 | SqlScalarType::Uuid
3841 | SqlScalarType::Record { .. }
3842 | SqlScalarType::Oid
3843 | SqlScalarType::RegProc
3844 | SqlScalarType::RegType
3845 | SqlScalarType::RegClass
3846 | SqlScalarType::Int2Vector
3847 | SqlScalarType::MzTimestamp
3848 | SqlScalarType::Range { .. }
3849 | SqlScalarType::MzAclItem { .. }) => Ok(t),
3850
3851 SqlScalarType::Array(elem) => Ok(elem.array_of_self_elem_type()?),
3852
3853 t @ (SqlScalarType::Char { .. }
3855 | SqlScalarType::Map { .. }
3857 | SqlScalarType::List { .. }) => Err(t),
3858 }
3859 }
3860}
3861
3862impl Arbitrary for SqlScalarType {
3865 type Parameters = ();
3866 type Strategy = BoxedStrategy<SqlScalarType>;
3867
3868 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
3869 let leaf = Union::new(vec![
3871 Just(SqlScalarType::Bool).boxed(),
3872 Just(SqlScalarType::UInt16).boxed(),
3873 Just(SqlScalarType::UInt32).boxed(),
3874 Just(SqlScalarType::UInt64).boxed(),
3875 Just(SqlScalarType::Int16).boxed(),
3876 Just(SqlScalarType::Int32).boxed(),
3877 Just(SqlScalarType::Int64).boxed(),
3878 Just(SqlScalarType::Float32).boxed(),
3879 Just(SqlScalarType::Float64).boxed(),
3880 any::<Option<NumericMaxScale>>()
3881 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
3882 .boxed(),
3883 Just(SqlScalarType::Date).boxed(),
3884 Just(SqlScalarType::Time).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 Just(SqlScalarType::MzTimestamp).boxed(),
3892 Just(SqlScalarType::Interval).boxed(),
3893 Just(SqlScalarType::PgLegacyChar).boxed(),
3894 Just(SqlScalarType::Bytes).boxed(),
3895 Just(SqlScalarType::String).boxed(),
3896 any::<Option<CharLength>>()
3897 .prop_map(|length| SqlScalarType::Char { length })
3898 .boxed(),
3899 any::<Option<VarCharMaxLength>>()
3900 .prop_map(|max_length| SqlScalarType::VarChar { max_length })
3901 .boxed(),
3902 Just(SqlScalarType::PgLegacyName).boxed(),
3903 Just(SqlScalarType::Jsonb).boxed(),
3904 Just(SqlScalarType::Uuid).boxed(),
3905 Just(SqlScalarType::AclItem).boxed(),
3906 Just(SqlScalarType::MzAclItem).boxed(),
3907 Just(SqlScalarType::Oid).boxed(),
3908 Just(SqlScalarType::RegProc).boxed(),
3909 Just(SqlScalarType::RegType).boxed(),
3910 Just(SqlScalarType::RegClass).boxed(),
3911 Just(SqlScalarType::Int2Vector).boxed(),
3912 ])
3913 .no_shrink()
3916 .boxed();
3917
3918 let range_leaf = Union::new(vec![
3920 Just(SqlScalarType::Int32).boxed(),
3921 Just(SqlScalarType::Int64).boxed(),
3922 Just(SqlScalarType::Date).boxed(),
3923 any::<Option<NumericMaxScale>>()
3924 .prop_map(|max_scale| SqlScalarType::Numeric { max_scale })
3925 .boxed(),
3926 any::<Option<TimestampPrecision>>()
3927 .prop_map(|precision| SqlScalarType::Timestamp { precision })
3928 .boxed(),
3929 any::<Option<TimestampPrecision>>()
3930 .prop_map(|precision| SqlScalarType::TimestampTz { precision })
3931 .boxed(),
3932 ]);
3933 let range = range_leaf
3934 .prop_map(|inner_type| SqlScalarType::Range {
3935 element_type: Box::new(inner_type),
3936 })
3937 .boxed();
3938
3939 let array = leaf
3941 .clone()
3942 .prop_map(|inner_type| SqlScalarType::Array(Box::new(inner_type)))
3943 .boxed();
3944
3945 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
3946
3947 leaf.prop_recursive(2, 3, 5, |inner| {
3948 Union::new(vec![
3949 (inner.clone(), any::<Option<CatalogItemId>>())
3951 .prop_map(|(x, id)| SqlScalarType::List {
3952 element_type: Box::new(x),
3953 custom_id: id,
3954 })
3955 .boxed(),
3956 (inner.clone(), any::<Option<CatalogItemId>>())
3958 .prop_map(|(x, id)| SqlScalarType::Map {
3959 value_type: Box::new(x),
3960 custom_id: id,
3961 })
3962 .boxed(),
3963 {
3965 let column_type_strat =
3968 (inner, any::<bool>()).prop_map(|(scalar_type, nullable)| SqlColumnType {
3969 scalar_type,
3970 nullable,
3971 });
3972
3973 let fields_strat =
3976 prop::collection::vec((any::<ColumnName>(), column_type_strat), 0..10);
3977
3978 (fields_strat, any::<Option<CatalogItemId>>())
3980 .prop_map(|(fields, custom_id)| SqlScalarType::Record {
3981 fields: fields.into(),
3982 custom_id,
3983 })
3984 .boxed()
3985 },
3986 ])
3987 })
3988 .boxed()
3989 }
3990}
3991
3992impl Arbitrary for ReprScalarType {
3993 type Parameters = ();
3994 type Strategy = BoxedStrategy<ReprScalarType>;
3995
3996 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
3997 let leaf = Union::new(vec![
3999 Just(ReprScalarType::Bool).boxed(),
4000 Just(ReprScalarType::UInt8).boxed(),
4001 Just(ReprScalarType::UInt16).boxed(),
4002 Just(ReprScalarType::UInt32).boxed(),
4003 Just(ReprScalarType::UInt64).boxed(),
4004 Just(ReprScalarType::Int16).boxed(),
4005 Just(ReprScalarType::Int32).boxed(),
4006 Just(ReprScalarType::Int64).boxed(),
4007 Just(ReprScalarType::Float32).boxed(),
4008 Just(ReprScalarType::Float64).boxed(),
4009 Just(ReprScalarType::Numeric).boxed(),
4010 Just(ReprScalarType::Date).boxed(),
4011 Just(ReprScalarType::Time).boxed(),
4012 Just(ReprScalarType::Timestamp).boxed(),
4013 Just(ReprScalarType::TimestampTz).boxed(),
4014 Just(ReprScalarType::MzTimestamp).boxed(),
4015 Just(ReprScalarType::Interval).boxed(),
4016 Just(ReprScalarType::Bytes).boxed(),
4017 Just(ReprScalarType::String).boxed(),
4018 Just(ReprScalarType::Jsonb).boxed(),
4019 Just(ReprScalarType::Uuid).boxed(),
4020 Just(ReprScalarType::AclItem).boxed(),
4021 Just(ReprScalarType::MzAclItem).boxed(),
4022 Just(ReprScalarType::Int2Vector).boxed(),
4023 ])
4024 .no_shrink()
4027 .boxed();
4028
4029 let range_leaf = Union::new(vec![
4031 Just(ReprScalarType::Int32).boxed(),
4032 Just(ReprScalarType::Int64).boxed(),
4033 Just(ReprScalarType::Date).boxed(),
4034 Just(ReprScalarType::Numeric).boxed(),
4035 Just(ReprScalarType::Timestamp).boxed(),
4036 Just(ReprScalarType::TimestampTz).boxed(),
4037 ]);
4038 let range = range_leaf
4039 .prop_map(|inner_type| ReprScalarType::Range {
4040 element_type: Box::new(inner_type),
4041 })
4042 .boxed();
4043
4044 let array = leaf
4046 .clone()
4047 .prop_map(|inner_type| ReprScalarType::Array(Box::new(inner_type)))
4048 .boxed();
4049
4050 let leaf = Union::new_weighted(vec![(30, leaf), (1, array), (1, range)]);
4051
4052 leaf.prop_recursive(2, 3, 5, |inner| {
4053 Union::new(vec![
4054 inner
4056 .clone()
4057 .prop_map(|x| ReprScalarType::List {
4058 element_type: Box::new(x),
4059 })
4060 .boxed(),
4061 inner
4063 .clone()
4064 .prop_map(|x| ReprScalarType::Map {
4065 value_type: Box::new(x),
4066 })
4067 .boxed(),
4068 {
4070 let column_type_strat =
4073 (inner.clone(), any::<bool>()).prop_map(|(scalar_type, nullable)| {
4074 ReprColumnType {
4075 scalar_type,
4076 nullable,
4077 }
4078 });
4079
4080 let fields_strat = prop::collection::vec(column_type_strat, 0..10);
4083
4084 fields_strat
4086 .prop_map(|fields| ReprScalarType::Record {
4087 fields: fields.into_boxed_slice(),
4088 })
4089 .boxed()
4090 },
4091 ])
4092 })
4093 .boxed()
4094 }
4095}
4096
4097#[derive(
4105 Clone, Debug, EnumKind, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash, MzReflect,
4106)]
4107#[enum_kind(ReprScalarBaseType, derive(PartialOrd, Ord, Hash))]
4108pub enum ReprScalarType {
4109 Bool,
4110 Int16,
4111 Int32,
4112 Int64,
4113 UInt8, UInt16,
4115 UInt32, UInt64,
4117 Float32,
4118 Float64,
4119 Numeric,
4120 Date,
4121 Time,
4122 Timestamp,
4123 TimestampTz,
4124 MzTimestamp,
4125 Interval,
4126 Bytes,
4127 Jsonb,
4128 String, Uuid,
4130 Array(Box<ReprScalarType>),
4131 Int2Vector, List { element_type: Box<ReprScalarType> },
4133 Record { fields: Box<[ReprColumnType]> },
4134 Map { value_type: Box<ReprScalarType> },
4135 Range { element_type: Box<ReprScalarType> },
4136 MzAclItem,
4137 AclItem,
4138}
4139
4140impl From<&SqlScalarType> for ReprScalarType {
4141 fn from(typ: &SqlScalarType) -> Self {
4142 match typ {
4143 SqlScalarType::Bool => ReprScalarType::Bool,
4144 SqlScalarType::Int16 => ReprScalarType::Int16,
4145 SqlScalarType::Int32 => ReprScalarType::Int32,
4146 SqlScalarType::Int64 => ReprScalarType::Int64,
4147 SqlScalarType::UInt16 => ReprScalarType::UInt16,
4148 SqlScalarType::UInt32 => ReprScalarType::UInt32,
4149 SqlScalarType::UInt64 => ReprScalarType::UInt64,
4150 SqlScalarType::Float32 => ReprScalarType::Float32,
4151 SqlScalarType::Float64 => ReprScalarType::Float64,
4152 SqlScalarType::Numeric { max_scale: _ } => ReprScalarType::Numeric,
4153 SqlScalarType::Date => ReprScalarType::Date,
4154 SqlScalarType::Time => ReprScalarType::Time,
4155 SqlScalarType::Timestamp { precision: _ } => ReprScalarType::Timestamp,
4156 SqlScalarType::TimestampTz { precision: _ } => ReprScalarType::TimestampTz,
4157 SqlScalarType::Interval => ReprScalarType::Interval,
4158 SqlScalarType::PgLegacyChar => ReprScalarType::UInt8,
4159 SqlScalarType::PgLegacyName => ReprScalarType::String,
4160 SqlScalarType::Bytes => ReprScalarType::Bytes,
4161 SqlScalarType::String => ReprScalarType::String,
4162 SqlScalarType::Char { length: _ } => ReprScalarType::String,
4163 SqlScalarType::VarChar { max_length: _ } => ReprScalarType::String,
4164 SqlScalarType::Jsonb => ReprScalarType::Jsonb,
4165 SqlScalarType::Uuid => ReprScalarType::Uuid,
4166 SqlScalarType::Array(element_type) => {
4167 ReprScalarType::Array(Box::new(element_type.as_ref().into()))
4168 }
4169 SqlScalarType::List {
4170 element_type,
4171 custom_id: _,
4172 } => ReprScalarType::List {
4173 element_type: Box::new(element_type.as_ref().into()),
4174 },
4175 SqlScalarType::Record {
4176 fields,
4177 custom_id: _,
4178 } => ReprScalarType::Record {
4179 fields: fields.into_iter().map(|(_, typ)| typ.into()).collect(),
4180 },
4181 SqlScalarType::Oid => ReprScalarType::UInt32,
4182 SqlScalarType::Map {
4183 value_type,
4184 custom_id: _,
4185 } => ReprScalarType::Map {
4186 value_type: Box::new(value_type.as_ref().into()),
4187 },
4188 SqlScalarType::RegProc => ReprScalarType::UInt32,
4189 SqlScalarType::RegType => ReprScalarType::UInt32,
4190 SqlScalarType::RegClass => ReprScalarType::UInt32,
4191 SqlScalarType::Int2Vector => ReprScalarType::Int2Vector,
4192 SqlScalarType::MzTimestamp => ReprScalarType::MzTimestamp,
4193 SqlScalarType::Range { element_type } => ReprScalarType::Range {
4194 element_type: Box::new(element_type.as_ref().into()),
4195 },
4196 SqlScalarType::MzAclItem => ReprScalarType::MzAclItem,
4197 SqlScalarType::AclItem => ReprScalarType::AclItem,
4198 }
4199 }
4200}
4201
4202impl SqlScalarType {
4203 pub fn from_repr(repr: &ReprScalarType) -> Self {
4223 match repr {
4224 ReprScalarType::Bool => SqlScalarType::Bool,
4225 ReprScalarType::Int16 => SqlScalarType::Int16,
4226 ReprScalarType::Int32 => SqlScalarType::Int32,
4227 ReprScalarType::Int64 => SqlScalarType::Int64,
4228 ReprScalarType::UInt8 => SqlScalarType::PgLegacyChar,
4229 ReprScalarType::UInt16 => SqlScalarType::UInt16,
4230 ReprScalarType::UInt32 => SqlScalarType::UInt32,
4231 ReprScalarType::UInt64 => SqlScalarType::UInt64,
4232 ReprScalarType::Float32 => SqlScalarType::Float32,
4233 ReprScalarType::Float64 => SqlScalarType::Float64,
4234 ReprScalarType::Numeric => SqlScalarType::Numeric { max_scale: None },
4235 ReprScalarType::Date => SqlScalarType::Date,
4236 ReprScalarType::Time => SqlScalarType::Time,
4237 ReprScalarType::Timestamp => SqlScalarType::Timestamp { precision: None },
4238 ReprScalarType::TimestampTz => SqlScalarType::TimestampTz { precision: None },
4239 ReprScalarType::MzTimestamp => SqlScalarType::MzTimestamp,
4240 ReprScalarType::Interval => SqlScalarType::Interval,
4241 ReprScalarType::Bytes => SqlScalarType::Bytes,
4242 ReprScalarType::Jsonb => SqlScalarType::Jsonb,
4243 ReprScalarType::String => SqlScalarType::String,
4244 ReprScalarType::Uuid => SqlScalarType::Uuid,
4245 ReprScalarType::Array(element_type) => {
4246 SqlScalarType::Array(Box::new(SqlScalarType::from_repr(element_type)))
4247 }
4248 ReprScalarType::Int2Vector => SqlScalarType::Int2Vector,
4249 ReprScalarType::List { element_type } => SqlScalarType::List {
4250 element_type: Box::new(SqlScalarType::from_repr(element_type)),
4251 custom_id: None,
4252 },
4253 ReprScalarType::Record { fields } => SqlScalarType::Record {
4254 fields: fields
4255 .iter()
4256 .enumerate()
4257 .map(|typ| {
4258 (
4259 ColumnName::from(format!("field_{}", typ.0)),
4260 SqlColumnType::from_repr(typ.1),
4261 )
4262 })
4263 .collect::<Vec<_>>()
4264 .into_boxed_slice(),
4265 custom_id: None,
4266 },
4267 ReprScalarType::Map { value_type } => SqlScalarType::Map {
4268 value_type: Box::new(SqlScalarType::from_repr(value_type)),
4269 custom_id: None,
4270 },
4271 ReprScalarType::Range { element_type } => SqlScalarType::Range {
4272 element_type: Box::new(SqlScalarType::from_repr(element_type)),
4273 },
4274 ReprScalarType::MzAclItem => SqlScalarType::MzAclItem,
4275 ReprScalarType::AclItem => SqlScalarType::AclItem,
4276 }
4277 }
4278}
4279
4280static EMPTY_ARRAY_ROW: LazyLock<Row> = LazyLock::new(|| {
4281 let mut row = Row::default();
4282 row.packer()
4283 .try_push_array(&[], iter::empty::<Datum>())
4284 .expect("array known to be valid");
4285 row
4286});
4287
4288static EMPTY_LIST_ROW: LazyLock<Row> = LazyLock::new(|| {
4289 let mut row = Row::default();
4290 row.packer().push_list(iter::empty::<Datum>());
4291 row
4292});
4293
4294static EMPTY_MAP_ROW: LazyLock<Row> = LazyLock::new(|| {
4295 let mut row = Row::default();
4296 row.packer().push_dict(iter::empty::<(_, Datum)>());
4297 row
4298});
4299
4300impl Datum<'_> {
4301 pub fn empty_array() -> Datum<'static> {
4302 EMPTY_ARRAY_ROW.unpack_first()
4303 }
4304
4305 pub fn empty_list() -> Datum<'static> {
4306 EMPTY_LIST_ROW.unpack_first()
4307 }
4308
4309 pub fn empty_map() -> Datum<'static> {
4310 EMPTY_MAP_ROW.unpack_first()
4311 }
4312}
4313
4314#[derive(Debug, PartialEq, Clone)]
4316pub enum PropDatum {
4317 Null,
4318 Bool(bool),
4319 Int16(i16),
4320 Int32(i32),
4321 Int64(i64),
4322 UInt8(u8),
4323 UInt16(u16),
4324 UInt32(u32),
4325 UInt64(u64),
4326 Float32(f32),
4327 Float64(f64),
4328
4329 Date(Date),
4330 Time(chrono::NaiveTime),
4331 Timestamp(CheckedTimestamp<chrono::NaiveDateTime>),
4332 TimestampTz(CheckedTimestamp<chrono::DateTime<chrono::Utc>>),
4333 MzTimestamp(u64),
4334
4335 Interval(Interval),
4336 Numeric(Numeric),
4337
4338 Bytes(Vec<u8>),
4339 String(String),
4340
4341 Array(PropArray),
4342 List(PropList),
4343 Map(PropDict),
4344 Record(PropDict),
4345 Range(PropRange),
4346
4347 AclItem(AclItem),
4348 MzAclItem(MzAclItem),
4349
4350 JsonNull,
4351 Uuid(Uuid),
4352 Dummy,
4353}
4354
4355impl std::cmp::Eq for PropDatum {}
4356
4357impl PartialOrd for PropDatum {
4358 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
4359 Some(self.cmp(other))
4360 }
4361}
4362
4363impl Ord for PropDatum {
4364 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
4365 Datum::from(self).cmp(&Datum::from(other))
4366 }
4367}
4368
4369pub fn arb_datum() -> BoxedStrategy<PropDatum> {
4371 let leaf = Union::new(vec![
4372 Just(PropDatum::Dummy).boxed(),
4373 any::<bool>().prop_map(PropDatum::Bool).boxed(),
4374 any::<i16>().prop_map(PropDatum::Int16).boxed(),
4375 any::<i32>().prop_map(PropDatum::Int32).boxed(),
4376 any::<i64>().prop_map(PropDatum::Int64).boxed(),
4377 any::<u16>().prop_map(PropDatum::UInt16).boxed(),
4378 any::<u32>().prop_map(PropDatum::UInt32).boxed(),
4379 any::<u64>().prop_map(PropDatum::UInt64).boxed(),
4380 any::<f32>().prop_map(PropDatum::Float32).boxed(),
4381 any::<f64>().prop_map(PropDatum::Float64).boxed(),
4382 arb_date().prop_map(PropDatum::Date).boxed(),
4383 add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
4384 .prop_map(PropDatum::Time)
4385 .boxed(),
4386 arb_naive_date_time()
4387 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
4388 .boxed(),
4389 arb_utc_date_time()
4390 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
4391 .boxed(),
4392 any::<Interval>().prop_map(PropDatum::Interval).boxed(),
4393 arb_numeric().prop_map(PropDatum::Numeric).boxed(),
4394 prop::collection::vec(any::<u8>(), 1024)
4395 .prop_map(PropDatum::Bytes)
4396 .boxed(),
4397 ".*".prop_map(PropDatum::String).boxed(),
4398 Just(PropDatum::JsonNull).boxed(),
4399 any::<[u8; 16]>()
4400 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
4401 .boxed(),
4402 arb_range(arb_range_data())
4403 .prop_map(PropDatum::Range)
4404 .boxed(),
4405 Just(PropDatum::Dummy).boxed(),
4406 ]);
4407
4408 leaf.prop_recursive(3, 8, 16, |inner| {
4409 Union::new(vec![
4410 arb_array(inner.clone()).prop_map(PropDatum::Array).boxed(),
4411 arb_list(inner.clone()).prop_map(PropDatum::List).boxed(),
4412 arb_dict(inner).prop_map(PropDatum::Map).boxed(),
4413 ])
4414 })
4415 .boxed()
4416}
4417
4418pub fn arb_datum_for_column(column_type: SqlColumnType) -> impl Strategy<Value = PropDatum> {
4420 let strat = arb_datum_for_scalar(column_type.scalar_type);
4421
4422 if column_type.nullable {
4423 Union::new_weighted(vec![(1, Just(PropDatum::Null).boxed()), (5, strat.boxed())]).boxed()
4424 } else {
4425 strat.boxed()
4426 }
4427}
4428
4429pub fn arb_datum_for_scalar(scalar_type: SqlScalarType) -> impl Strategy<Value = PropDatum> {
4431 match scalar_type {
4432 SqlScalarType::Bool => any::<bool>().prop_map(PropDatum::Bool).boxed(),
4433 SqlScalarType::Int16 => any::<i16>().prop_map(PropDatum::Int16).boxed(),
4434 SqlScalarType::Int32 => any::<i32>().prop_map(PropDatum::Int32).boxed(),
4435 SqlScalarType::Int64 => any::<i64>().prop_map(PropDatum::Int64).boxed(),
4436 SqlScalarType::PgLegacyChar => any::<u8>().prop_map(PropDatum::UInt8).boxed(),
4437 SqlScalarType::UInt16 => any::<u16>().prop_map(PropDatum::UInt16).boxed(),
4438 SqlScalarType::UInt32
4439 | SqlScalarType::Oid
4440 | SqlScalarType::RegClass
4441 | SqlScalarType::RegProc
4442 | SqlScalarType::RegType => any::<u32>().prop_map(PropDatum::UInt32).boxed(),
4443 SqlScalarType::UInt64 => any::<u64>().prop_map(PropDatum::UInt64).boxed(),
4444 SqlScalarType::Float32 => any::<f32>().prop_map(PropDatum::Float32).boxed(),
4445 SqlScalarType::Float64 => any::<f64>().prop_map(PropDatum::Float64).boxed(),
4446 SqlScalarType::Numeric { .. } => arb_numeric().prop_map(PropDatum::Numeric).boxed(),
4447 SqlScalarType::String
4448 | SqlScalarType::PgLegacyName
4449 | SqlScalarType::Char { length: None }
4450 | SqlScalarType::VarChar { max_length: None } => ".*".prop_map(PropDatum::String).boxed(),
4451 SqlScalarType::Char {
4452 length: Some(length),
4453 } => {
4454 let max_len = usize::cast_from(length.into_u32()).max(1);
4455 prop::collection::vec(any::<char>(), 0..max_len)
4456 .prop_map(move |chars| {
4457 let num_blanks = max_len - chars.len();
4459 let s = chars
4460 .into_iter()
4461 .chain(std::iter::repeat(' ').take(num_blanks))
4462 .collect();
4463 PropDatum::String(s)
4464 })
4465 .boxed()
4466 }
4467 SqlScalarType::VarChar {
4468 max_length: Some(length),
4469 } => {
4470 let max_len = usize::cast_from(length.into_u32()).max(1);
4471 prop::collection::vec(any::<char>(), 0..max_len)
4472 .prop_map(|chars| PropDatum::String(chars.into_iter().collect()))
4473 .boxed()
4474 }
4475 SqlScalarType::Bytes => prop::collection::vec(any::<u8>(), 300)
4476 .prop_map(PropDatum::Bytes)
4477 .boxed(),
4478 SqlScalarType::Date => arb_date().prop_map(PropDatum::Date).boxed(),
4479 SqlScalarType::Time => add_arb_duration(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap())
4480 .prop_map(PropDatum::Time)
4481 .boxed(),
4482 SqlScalarType::Timestamp { .. } => arb_naive_date_time()
4483 .prop_map(|t| PropDatum::Timestamp(CheckedTimestamp::from_timestamplike(t).unwrap()))
4484 .boxed(),
4485 SqlScalarType::TimestampTz { .. } => arb_utc_date_time()
4486 .prop_map(|t| PropDatum::TimestampTz(CheckedTimestamp::from_timestamplike(t).unwrap()))
4487 .boxed(),
4488 SqlScalarType::MzTimestamp => any::<u64>().prop_map(PropDatum::MzTimestamp).boxed(),
4489 SqlScalarType::Interval => any::<Interval>().prop_map(PropDatum::Interval).boxed(),
4490 SqlScalarType::Uuid => any::<[u8; 16]>()
4491 .prop_map(|x| PropDatum::Uuid(Uuid::from_bytes(x)))
4492 .boxed(),
4493 SqlScalarType::AclItem => any::<AclItem>().prop_map(PropDatum::AclItem).boxed(),
4494 SqlScalarType::MzAclItem => any::<MzAclItem>().prop_map(PropDatum::MzAclItem).boxed(),
4495 SqlScalarType::Range { element_type } => {
4496 let data_strat = (
4497 arb_datum_for_scalar(*element_type.clone()),
4498 arb_datum_for_scalar(*element_type),
4499 );
4500 arb_range(data_strat).prop_map(PropDatum::Range).boxed()
4501 }
4502 SqlScalarType::List { element_type, .. } => arb_list(arb_datum_for_scalar(*element_type))
4503 .prop_map(PropDatum::List)
4504 .boxed(),
4505 SqlScalarType::Array(element_type) => arb_array(arb_datum_for_scalar(*element_type))
4506 .prop_map(PropDatum::Array)
4507 .boxed(),
4508 SqlScalarType::Int2Vector => arb_array(any::<i16>().prop_map(PropDatum::Int16).boxed())
4509 .prop_map(PropDatum::Array)
4510 .boxed(),
4511 SqlScalarType::Map { value_type, .. } => arb_dict(arb_datum_for_scalar(*value_type))
4512 .prop_map(PropDatum::Map)
4513 .boxed(),
4514 SqlScalarType::Record { fields, .. } => {
4515 let field_strats = fields.iter().map(|(name, ty)| {
4516 (
4517 name.to_string(),
4518 arb_datum_for_scalar(ty.scalar_type.clone()),
4519 )
4520 });
4521 arb_record(field_strats).prop_map(PropDatum::Record).boxed()
4522 }
4523 SqlScalarType::Jsonb => {
4524 let int_value = any::<i128>()
4525 .prop_map(|v| Numeric::try_from(v).unwrap())
4526 .boxed();
4527 let float_value = (1e-39f64..1e39)
4529 .prop_map(|v| Numeric::try_from(v).unwrap())
4530 .boxed();
4531 let json_number = Union::new(vec![int_value, float_value]);
4534
4535 let json_leaf = Union::new(vec![
4536 any::<()>().prop_map(|_| PropDatum::JsonNull).boxed(),
4537 any::<bool>().prop_map(PropDatum::Bool).boxed(),
4538 json_number.prop_map(PropDatum::Numeric).boxed(),
4539 ".*".prop_map(PropDatum::String).boxed(),
4540 ]);
4541 json_leaf
4542 .prop_recursive(4, 32, 8, |element| {
4543 Union::new(vec![
4544 prop::collection::vec(element.clone(), 0..16)
4545 .prop_map(|elements| {
4546 let datums: Vec<_> = elements.iter().map(|pd| pd.into()).collect();
4547 let mut row = Row::default();
4548 row.packer().push_list(datums.iter());
4549 PropDatum::List(PropList(row, elements))
4550 })
4551 .boxed(),
4552 prop::collection::hash_map(".*", element, 0..16)
4553 .prop_map(|elements| {
4554 let mut elements: Vec<_> = elements.into_iter().collect();
4555 elements.sort_by_key(|(k, _)| k.clone());
4556 elements.dedup_by_key(|(k, _)| k.clone());
4557 let mut row = Row::default();
4558 let entry_iter =
4559 elements.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4560 row.packer().push_dict(entry_iter);
4561 PropDatum::Map(PropDict(row, elements))
4562 })
4563 .boxed(),
4564 ])
4565 })
4566 .boxed()
4567 }
4568 }
4569}
4570
4571pub fn arb_naive_date_time() -> impl Strategy<Value = NaiveDateTime> {
4573 add_arb_duration(chrono::DateTime::from_timestamp(0, 0).unwrap().naive_utc())
4574}
4575
4576pub fn arb_utc_date_time() -> impl Strategy<Value = DateTime<Utc>> {
4578 add_arb_duration(chrono::Utc.timestamp_opt(0, 0).unwrap())
4579}
4580
4581fn arb_array_dimension() -> BoxedStrategy<ArrayDimension> {
4582 (1..4_usize)
4583 .prop_map(|length| ArrayDimension {
4584 lower_bound: 1,
4585 length,
4586 })
4587 .boxed()
4588}
4589
4590#[derive(Debug, PartialEq, Clone)]
4591pub struct PropArray(Row, Vec<PropDatum>);
4592
4593fn arb_array(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropArray> {
4594 let element_strategy = Union::new_weighted(vec![
4596 (20, element_strategy),
4597 (1, Just(PropDatum::Null).boxed()),
4598 ]);
4599
4600 prop::collection::vec(
4601 arb_array_dimension(),
4602 1..usize::from(crate::adt::array::MAX_ARRAY_DIMENSIONS),
4603 )
4604 .prop_flat_map(move |dimensions| {
4605 let n_elts: usize = dimensions.iter().map(|d| d.length).product();
4606 (
4607 Just(dimensions),
4608 prop::collection::vec(element_strategy.clone(), n_elts),
4609 )
4610 })
4611 .prop_map(|(dimensions, elements)| {
4612 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4613 let mut row = Row::default();
4614 row.packer()
4615 .try_push_array(&dimensions, element_datums)
4616 .unwrap();
4617 PropArray(row, elements)
4618 })
4619 .boxed()
4620}
4621
4622#[derive(Debug, PartialEq, Clone)]
4623pub struct PropList(Row, Vec<PropDatum>);
4624
4625fn arb_list(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropList> {
4626 let element_strategy = Union::new_weighted(vec![
4628 (20, element_strategy),
4629 (1, Just(PropDatum::Null).boxed()),
4630 ]);
4631
4632 prop::collection::vec(element_strategy, 1..50)
4633 .prop_map(|elements| {
4634 let element_datums: Vec<Datum<'_>> = elements.iter().map(|pd| pd.into()).collect();
4635 let mut row = Row::default();
4636 row.packer().push_list(element_datums.iter());
4637 PropList(row, elements)
4638 })
4639 .boxed()
4640}
4641
4642#[derive(Debug, PartialEq, Clone)]
4643pub struct PropRange(
4644 Row,
4645 Option<(
4646 (Option<Box<PropDatum>>, bool),
4647 (Option<Box<PropDatum>>, bool),
4648 )>,
4649);
4650
4651pub fn arb_range_type() -> Union<BoxedStrategy<SqlScalarType>> {
4652 Union::new(vec![
4653 Just(SqlScalarType::Int32).boxed(),
4654 Just(SqlScalarType::Int64).boxed(),
4655 Just(SqlScalarType::Date).boxed(),
4656 ])
4657}
4658
4659fn arb_range_data() -> Union<BoxedStrategy<(PropDatum, PropDatum)>> {
4660 Union::new(vec![
4661 (
4662 any::<i32>().prop_map(PropDatum::Int32),
4663 any::<i32>().prop_map(PropDatum::Int32),
4664 )
4665 .boxed(),
4666 (
4667 any::<i64>().prop_map(PropDatum::Int64),
4668 any::<i64>().prop_map(PropDatum::Int64),
4669 )
4670 .boxed(),
4671 (
4672 arb_date().prop_map(PropDatum::Date),
4673 arb_date().prop_map(PropDatum::Date),
4674 )
4675 .boxed(),
4676 ])
4677}
4678
4679fn arb_range(
4680 data: impl Strategy<Value = (PropDatum, PropDatum)> + 'static,
4681) -> BoxedStrategy<PropRange> {
4682 (
4683 any::<u16>(),
4684 any::<bool>(),
4685 any::<bool>(),
4686 any::<bool>(),
4687 any::<bool>(),
4688 data,
4689 )
4690 .prop_map(
4691 |(split, lower_inf, lower_inc, upper_inf, upper_inc, (a, b))| {
4692 let mut row = Row::default();
4693 let mut packer = row.packer();
4694 let r = if split % 32 == 0 {
4695 packer
4696 .push_range(Range::new(None))
4697 .expect("pushing empty ranges never fails");
4698 None
4699 } else {
4700 let b_is_lower = Datum::from(&b) < Datum::from(&a);
4701
4702 let (lower, upper) = if b_is_lower { (b, a) } else { (a, b) };
4703 let mut range = Range::new(Some((
4704 RangeLowerBound {
4705 inclusive: lower_inc,
4706 bound: if lower_inf {
4707 None
4708 } else {
4709 Some(Datum::from(&lower))
4710 },
4711 },
4712 RangeUpperBound {
4713 inclusive: upper_inc,
4714 bound: if upper_inf {
4715 None
4716 } else {
4717 Some(Datum::from(&upper))
4718 },
4719 },
4720 )));
4721
4722 range.canonicalize().unwrap();
4723
4724 let (empty, lower_inf, lower_inc, upper_inf, upper_inc) = match range.inner {
4727 None => (true, false, false, false, false),
4728 Some(inner) => (
4729 false
4730 || match inner.lower.bound {
4731 Some(b) => b != Datum::from(&lower),
4732 None => !lower_inf,
4733 }
4734 || match inner.upper.bound {
4735 Some(b) => b != Datum::from(&upper),
4736 None => !upper_inf,
4737 },
4738 inner.lower.bound.is_none(),
4739 inner.lower.inclusive,
4740 inner.upper.bound.is_none(),
4741 inner.upper.inclusive,
4742 ),
4743 };
4744
4745 if empty {
4746 packer.push_range(Range { inner: None }).unwrap();
4747 None
4748 } else {
4749 packer.push_range(range).unwrap();
4750 Some((
4751 (
4752 if lower_inf {
4753 None
4754 } else {
4755 Some(Box::new(lower))
4756 },
4757 lower_inc,
4758 ),
4759 (
4760 if upper_inf {
4761 None
4762 } else {
4763 Some(Box::new(upper))
4764 },
4765 upper_inc,
4766 ),
4767 ))
4768 }
4769 };
4770
4771 PropRange(row, r)
4772 },
4773 )
4774 .boxed()
4775}
4776
4777#[derive(Debug, PartialEq, Clone)]
4778pub struct PropDict(Row, Vec<(String, PropDatum)>);
4779
4780fn arb_dict(element_strategy: BoxedStrategy<PropDatum>) -> BoxedStrategy<PropDict> {
4781 let element_strategy = Union::new_weighted(vec![
4783 (20, element_strategy),
4784 (1, Just(PropDatum::Null).boxed()),
4785 ]);
4786
4787 prop::collection::vec((".*", element_strategy), 1..50)
4788 .prop_map(|mut entries| {
4789 entries.sort_by_key(|(k, _)| k.clone());
4790 entries.dedup_by_key(|(k, _)| k.clone());
4791 let mut row = Row::default();
4792 let entry_iter = entries.iter().map(|(k, v)| (k.as_str(), Datum::from(v)));
4793 row.packer().push_dict(entry_iter);
4794 PropDict(row, entries)
4795 })
4796 .boxed()
4797}
4798
4799fn arb_record(
4800 fields: impl Iterator<Item = (String, BoxedStrategy<PropDatum>)>,
4801) -> BoxedStrategy<PropDict> {
4802 let (names, strategies): (Vec<_>, Vec<_>) = fields.unzip();
4803
4804 strategies
4805 .prop_map(move |x| {
4806 let mut row = Row::default();
4807 row.packer().push_list(x.iter().map(Datum::from));
4808 let entries: Vec<_> = names.clone().into_iter().zip_eq(x).collect();
4809 PropDict(row, entries)
4810 })
4811 .boxed()
4812}
4813
4814fn arb_date() -> BoxedStrategy<Date> {
4815 (Date::LOW_DAYS..Date::HIGH_DAYS)
4816 .prop_map(move |days| Date::from_pg_epoch(days).unwrap())
4817 .boxed()
4818}
4819
4820pub fn add_arb_duration<T: 'static + Copy + Add<chrono::Duration> + std::fmt::Debug>(
4821 to: T,
4822) -> BoxedStrategy<T::Output>
4823where
4824 T::Output: std::fmt::Debug,
4825{
4826 let lower = LOW_DATE
4827 .and_hms_opt(0, 0, 0)
4828 .unwrap()
4829 .and_utc()
4830 .timestamp_micros();
4831 let upper = HIGH_DATE
4832 .and_hms_opt(0, 0, 0)
4833 .unwrap()
4834 .and_utc()
4835 .timestamp_micros();
4836 (lower..upper)
4837 .prop_map(move |v| to + chrono::Duration::microseconds(v))
4838 .boxed()
4839}
4840
4841pub(crate) fn arb_numeric() -> BoxedStrategy<Numeric> {
4842 let int_value = any::<i128>()
4843 .prop_map(|v| Numeric::try_from(v).unwrap())
4844 .boxed();
4845 let float_value = (-1e39f64..1e39)
4846 .prop_map(|v| Numeric::try_from(v).unwrap())
4847 .boxed();
4848
4849 let tiny_floats = ((-10.0..10.0), (1u32..10))
4852 .prop_map(|(v, num_digits)| {
4853 let num_digits: f64 = 10u32.pow(num_digits).try_into().unwrap();
4855 let trunc = f64::trunc(v * num_digits) / num_digits;
4856 Numeric::try_from(trunc).unwrap()
4857 })
4858 .boxed();
4859 let small_ints = (-1_000_000..1_000_000)
4860 .prop_map(|v| Numeric::try_from(v).unwrap())
4861 .boxed();
4862 let small_floats = (-1_000_000.0..1_000_000.0)
4863 .prop_map(|v| Numeric::try_from(v).unwrap())
4864 .boxed();
4865
4866 Union::new_weighted(vec![
4867 (20, tiny_floats),
4868 (20, small_ints),
4869 (20, small_floats),
4870 (10, int_value),
4871 (10, float_value),
4872 (1, Just(Numeric::infinity()).boxed()),
4873 (1, Just(-Numeric::infinity()).boxed()),
4874 (1, Just(Numeric::nan()).boxed()),
4875 (1, Just(Numeric::zero()).boxed()),
4876 ])
4877 .boxed()
4878}
4879
4880impl<'a> From<&'a PropDatum> for Datum<'a> {
4881 #[inline]
4882 fn from(pd: &'a PropDatum) -> Self {
4883 use PropDatum::*;
4884 match pd {
4885 Null => Datum::Null,
4886 Bool(b) => Datum::from(*b),
4887 Int16(i) => Datum::from(*i),
4888 Int32(i) => Datum::from(*i),
4889 Int64(i) => Datum::from(*i),
4890 UInt8(u) => Datum::from(*u),
4891 UInt16(u) => Datum::from(*u),
4892 UInt32(u) => Datum::from(*u),
4893 UInt64(u) => Datum::from(*u),
4894 Float32(f) => Datum::from(*f),
4895 Float64(f) => Datum::from(*f),
4896 Date(d) => Datum::from(*d),
4897 Time(t) => Datum::from(*t),
4898 Timestamp(t) => Datum::from(*t),
4899 TimestampTz(t) => Datum::from(*t),
4900 MzTimestamp(t) => Datum::MzTimestamp((*t).into()),
4901 Interval(i) => Datum::from(*i),
4902 Numeric(s) => Datum::from(*s),
4903 Bytes(b) => Datum::from(&b[..]),
4904 String(s) => Datum::from(s.as_str()),
4905 Array(PropArray(row, _)) => {
4906 let array = row.unpack_first().unwrap_array();
4907 Datum::Array(array)
4908 }
4909 List(PropList(row, _)) => {
4910 let list = row.unpack_first().unwrap_list();
4911 Datum::List(list)
4912 }
4913 Map(PropDict(row, _)) => {
4914 let map = row.unpack_first().unwrap_map();
4915 Datum::Map(map)
4916 }
4917 Record(PropDict(row, _)) => {
4918 let list = row.unpack_first().unwrap_list();
4919 Datum::List(list)
4920 }
4921 Range(PropRange(row, _)) => {
4922 let d = row.unpack_first();
4923 assert!(matches!(d, Datum::Range(_)));
4924 d
4925 }
4926 AclItem(i) => Datum::AclItem(*i),
4927 MzAclItem(i) => Datum::MzAclItem(*i),
4928 JsonNull => Datum::JsonNull,
4929 Uuid(u) => Datum::from(*u),
4930 Dummy => Datum::Dummy,
4931 }
4932 }
4933}
4934
4935#[mz_ore::test]
4936fn verify_base_eq_record_nullability() {
4937 let s1 = SqlScalarType::Record {
4938 fields: [(
4939 "c".into(),
4940 SqlColumnType {
4941 scalar_type: SqlScalarType::Bool,
4942 nullable: true,
4943 },
4944 )]
4945 .into(),
4946 custom_id: None,
4947 };
4948 let s2 = SqlScalarType::Record {
4949 fields: [(
4950 "c".into(),
4951 SqlColumnType {
4952 scalar_type: SqlScalarType::Bool,
4953 nullable: false,
4954 },
4955 )]
4956 .into(),
4957 custom_id: None,
4958 };
4959 let s3 = SqlScalarType::Record {
4960 fields: [].into(),
4961 custom_id: None,
4962 };
4963 assert!(s1.base_eq(&s2));
4964 assert!(!s1.base_eq(&s3));
4965}
4966
4967#[cfg(test)]
4968mod tests {
4969 use mz_ore::assert_ok;
4970 use mz_proto::protobuf_roundtrip;
4971
4972 use super::*;
4973
4974 proptest! {
4975 #[mz_ore::test]
4976 #[cfg_attr(miri, ignore)] fn scalar_type_protobuf_roundtrip(expect in any::<SqlScalarType>() ) {
4978 let actual = protobuf_roundtrip::<_, ProtoScalarType>(&expect);
4979 assert_ok!(actual);
4980 assert_eq!(actual.unwrap(), expect);
4981 }
4982 }
4983
4984 proptest! {
4985 #[mz_ore::test]
4986 #[cfg_attr(miri, ignore)]
4987 fn sql_repr_types_agree_on_valid_data((src, datum) in any::<SqlColumnType>().prop_flat_map(|src| {
4988 let datum = arb_datum_for_column(src.clone());
4989 (Just(src), datum) }
4990 )) {
4991 let tgt = ReprColumnType::from(&src);
4992 let datum = Datum::from(&datum);
4993 assert_eq!(datum.is_instance_of_sql(&src), datum.is_instance_of(&tgt), "translated to repr type {tgt:#?}");
4994 }
4995 }
4996
4997 proptest! {
4998 #![proptest_config(ProptestConfig::with_cases(10000))]
5001 #[mz_ore::test]
5002 #[cfg_attr(miri, ignore)]
5003 fn sql_repr_types_agree_on_random_data(src in any::<SqlColumnType>(), datum in arb_datum()) {
5004 let tgt = ReprColumnType::from(&src);
5005 let datum = Datum::from(&datum);
5006
5007 assert_eq!(datum.is_instance_of_sql(&src), datum.is_instance_of(&tgt), "translated to repr type {tgt:#?}");
5008 }
5009 }
5010
5011 proptest! {
5012 #![proptest_config(ProptestConfig::with_cases(10000))]
5013 #[mz_ore::test]
5014 #[cfg_attr(miri, ignore)]
5015 fn repr_type_to_sql_type_roundtrip(repr_type in any::<ReprScalarType>()) {
5016 let sql_type = SqlScalarType::from_repr(&repr_type);
5021 assert_eq!(repr_type, ReprScalarType::from(&sql_type));
5022 }
5023 }
5024
5025 proptest! {
5026 #![proptest_config(ProptestConfig::with_cases(10000))]
5027 #[mz_ore::test]
5028 #[cfg_attr(miri, ignore)]
5029 fn sql_type_base_eq_implies_repr_type_eq(sql_type1 in any::<SqlScalarType>(), sql_type2 in any::<SqlScalarType>()) {
5030 let repr_type1 = ReprScalarType::from(&sql_type1);
5031 let repr_type2 = ReprScalarType::from(&sql_type2);
5032 if sql_type1.base_eq(&sql_type2) {
5033 assert_eq!(repr_type1, repr_type2);
5034 }
5035 }
5036 }
5037
5038 proptest! {
5039 #[mz_ore::test]
5040 #[cfg_attr(miri, ignore)] fn array_packing_unpacks_correctly(array in arb_array(arb_datum())) {
5042 let PropArray(row, elts) = array;
5043 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
5044 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_array().elements().iter().collect();
5045 assert_eq!(unpacked_datums, datums);
5046 }
5047
5048 #[mz_ore::test]
5049 #[cfg_attr(miri, ignore)] fn list_packing_unpacks_correctly(array in arb_list(arb_datum())) {
5051 let PropList(row, elts) = array;
5052 let datums: Vec<Datum<'_>> = elts.iter().map(|e| e.into()).collect();
5053 let unpacked_datums: Vec<Datum<'_>> = row.unpack_first().unwrap_list().iter().collect();
5054 assert_eq!(unpacked_datums, datums);
5055 }
5056
5057 #[mz_ore::test]
5058 #[cfg_attr(miri, ignore)] fn dict_packing_unpacks_correctly(array in arb_dict(arb_datum())) {
5060 let PropDict(row, elts) = array;
5061 let datums: Vec<(&str, Datum<'_>)> = elts.iter().map(|(k, e)| (k.as_str(), e.into())).collect();
5062 let unpacked_datums: Vec<(&str, Datum<'_>)> = row.unpack_first().unwrap_map().iter().collect();
5063 assert_eq!(unpacked_datums, datums);
5064 }
5065
5066 #[mz_ore::test]
5067 #[cfg_attr(miri, ignore)] fn row_packing_roundtrips_single_valued(prop_datums in prop::collection::vec(arb_datum(), 1..100)) {
5069 let datums: Vec<Datum<'_>> = prop_datums.iter().map(|pd| pd.into()).collect();
5070 let row = Row::pack(&datums);
5071 let unpacked = row.unpack();
5072 assert_eq!(datums, unpacked);
5073 }
5074
5075 #[mz_ore::test]
5076 #[cfg_attr(miri, ignore)] fn range_packing_unpacks_correctly(range in arb_range(arb_range_data())) {
5078 let PropRange(row, prop_range) = range;
5079 let row = row.unpack_first();
5080 let d = row.unwrap_range();
5081
5082 let (((prop_lower, prop_lower_inc), (prop_upper, prop_upper_inc)), crate::adt::range::RangeInner {lower, upper}) = match (prop_range, d.inner) {
5083 (Some(prop_values), Some(inner_range)) => (prop_values, inner_range),
5084 (None, None) => return Ok(()),
5085 _ => panic!("inequivalent row packing"),
5086 };
5087
5088 for (prop_bound, prop_bound_inc, inner_bound, inner_bound_inc) in [
5089 (prop_lower, prop_lower_inc, lower.bound, lower.inclusive),
5090 (prop_upper, prop_upper_inc, upper.bound, upper.inclusive),
5091 ] {
5092 assert_eq!(prop_bound_inc, inner_bound_inc);
5093 match (prop_bound, inner_bound) {
5094 (None, None) => continue,
5095 (Some(p), Some(b)) => {
5096 assert_eq!(Datum::from(&*p), b);
5097 }
5098 _ => panic!("inequivalent row packing"),
5099 }
5100 }
5101 }
5102 }
5103}