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