1use std::any::type_name;
11use std::cmp::Ordering;
12use std::error::Error;
13use std::fmt::{self, Debug, Display};
14use std::hash::{Hash, Hasher};
15
16use bitflags::bitflags;
17use chrono::{DateTime, NaiveDateTime, Utc};
18use dec::OrderedDecimal;
19use mz_lowertest::MzReflect;
20use mz_proto::{RustType, TryFromProtoError};
21use postgres_protocol::types;
22use proptest_derive::Arbitrary;
23use serde::{Deserialize, Serialize};
24use tokio_postgres::types::{FromSql, Type as PgType};
25
26use crate::Datum;
27use crate::adt::date::Date;
28use crate::adt::numeric::Numeric;
29use crate::adt::timestamp::CheckedTimestamp;
30use crate::scalar::DatumKind;
31
32include!(concat!(env!("OUT_DIR"), "/mz_repr.adt.range.rs"));
33
34bitflags! {
35 pub(crate) struct InternalFlags: u8 {
36 const EMPTY = 1;
37 const LB_INCLUSIVE = 1 << 1;
38 const LB_INFINITE = 1 << 2;
39 const UB_INCLUSIVE = 1 << 3;
40 const UB_INFINITE = 1 << 4;
41 }
42}
43
44bitflags! {
45 pub(crate) struct PgFlags: u8 {
46 const EMPTY = 0b0000_0001;
47 const LB_INCLUSIVE = 0b0000_0010;
48 const UB_INCLUSIVE = 0b0000_0100;
49 const LB_INFINITE = 0b0000_1000;
50 const UB_INFINITE = 0b0001_0000;
51 }
52}
53
54pub struct Range<D> {
64 pub inner: Option<RangeInner<D>>,
66}
67
68impl<D: Display> Display for Range<D> {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 match &self.inner {
71 None => f.write_str("empty"),
72 Some(i) => i.fmt(f),
73 }
74 }
75}
76
77impl<D: Debug> Debug for Range<D> {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 f.debug_struct("Range").field("inner", &self.inner).finish()
80 }
81}
82
83impl<D: Clone> Clone for Range<D> {
84 fn clone(&self) -> Self {
85 Self {
86 inner: self.inner.clone(),
87 }
88 }
89}
90
91impl<D: Copy> Copy for Range<D> {}
92
93impl<D: PartialEq> PartialEq for Range<D> {
94 fn eq(&self, other: &Self) -> bool {
95 self.inner == other.inner
96 }
97}
98
99impl<D: Eq> Eq for Range<D> {}
100
101impl<D: Ord + PartialOrd> PartialOrd for Range<D> {
102 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
103 Some(self.cmp(other))
104 }
105}
106
107impl<D: Ord> Ord for Range<D> {
108 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
109 self.inner.cmp(&other.inner)
110 }
111}
112
113impl<D: Hash> Hash for Range<D> {
114 fn hash<H: Hasher>(&self, hasher: &mut H) {
115 self.inner.hash(hasher)
116 }
117}
118
119pub trait RangeOps<'a>:
121 Debug + Ord + PartialOrd + Eq + PartialEq + TryFrom<Datum<'a>> + Into<Datum<'a>>
122where
123 <Self as TryFrom<Datum<'a>>>::Error: std::fmt::Debug,
124{
125 fn step(self) -> Option<Self> {
128 Some(self)
129 }
130
131 fn unwrap_datum(d: Datum<'a>) -> Self {
132 <Self>::try_from(d)
133 .unwrap_or_else(|_| panic!("cannot take {} to {}", d, type_name::<Self>()))
134 }
135
136 fn err_type_name() -> &'static str;
137}
138
139impl<'a> RangeOps<'a> for i32 {
140 fn step(self) -> Option<i32> {
141 self.checked_add(1)
142 }
143
144 fn err_type_name() -> &'static str {
145 "integer"
146 }
147}
148
149impl<'a> RangeOps<'a> for i64 {
150 fn step(self) -> Option<i64> {
151 self.checked_add(1)
152 }
153
154 fn err_type_name() -> &'static str {
155 "bigint"
156 }
157}
158
159impl<'a> RangeOps<'a> for Date {
160 fn step(self) -> Option<Date> {
161 self.checked_add(1).ok()
162 }
163
164 fn err_type_name() -> &'static str {
165 "date"
166 }
167}
168
169impl<'a> RangeOps<'a> for OrderedDecimal<Numeric> {
170 fn err_type_name() -> &'static str {
171 "numeric"
172 }
173}
174
175impl<'a> RangeOps<'a> for CheckedTimestamp<NaiveDateTime> {
176 fn err_type_name() -> &'static str {
177 "timestamp"
178 }
179}
180
181impl<'a> RangeOps<'a> for CheckedTimestamp<DateTime<Utc>> {
182 fn err_type_name() -> &'static str {
183 "timestamptz"
184 }
185}
186
187impl<D> Range<D> {
189 pub fn new(inner: Option<(RangeLowerBound<D>, RangeUpperBound<D>)>) -> Range<D> {
195 Range {
196 inner: inner.map(|(lower, upper)| RangeInner { lower, upper }),
197 }
198 }
199
200 pub fn internal_flag_bits(&self) -> u8 {
207 let mut flags = InternalFlags::empty();
208
209 match &self.inner {
210 None => {
211 flags.set(InternalFlags::EMPTY, true);
212 }
213 Some(RangeInner { lower, upper }) => {
214 flags.set(InternalFlags::EMPTY, false);
215 flags.set(InternalFlags::LB_INFINITE, lower.bound.is_none());
216 flags.set(InternalFlags::UB_INFINITE, upper.bound.is_none());
217 flags.set(InternalFlags::LB_INCLUSIVE, lower.inclusive);
218 flags.set(InternalFlags::UB_INCLUSIVE, upper.inclusive);
219 }
220 }
221
222 flags.bits()
223 }
224
225 pub fn pg_flag_bits(&self) -> u8 {
232 let mut flags = PgFlags::empty();
233
234 match &self.inner {
235 None => {
236 flags.set(PgFlags::EMPTY, true);
237 }
238 Some(RangeInner { lower, upper }) => {
239 flags.set(PgFlags::EMPTY, false);
240 flags.set(PgFlags::LB_INFINITE, lower.bound.is_none());
241 flags.set(PgFlags::UB_INFINITE, upper.bound.is_none());
242 flags.set(PgFlags::LB_INCLUSIVE, lower.inclusive);
243 flags.set(PgFlags::UB_INCLUSIVE, upper.inclusive);
244 }
245 }
246
247 flags.bits()
248 }
249
250 pub fn into_bounds<F, O>(self, conv: F) -> Range<O>
253 where
254 F: Fn(D) -> O,
255 {
256 Range {
257 inner: self
258 .inner
259 .map(|RangeInner::<D> { lower, upper }| RangeInner::<O> {
260 lower: RangeLowerBound {
261 inclusive: lower.inclusive,
262 bound: lower.bound.map(&conv),
263 },
264 upper: RangeUpperBound {
265 inclusive: upper.inclusive,
266 bound: upper.bound.map(&conv),
267 },
268 }),
269 }
270 }
271}
272
273impl<'a, B: Copy + Ord + PartialOrd + Display + Debug> Range<B>
275where
276 Datum<'a>: From<B>,
277{
278 pub fn contains_elem<T: RangeOps<'a>>(&self, elem: &T) -> bool
279 where
280 <T as TryFrom<Datum<'a>>>::Error: std::fmt::Debug,
281 {
282 match self.inner {
283 None => false,
284 Some(inner) => inner.lower.satisfied_by(elem) && inner.upper.satisfied_by(elem),
285 }
286 }
287
288 pub fn contains_range(&self, other: &Range<B>) -> bool {
289 match (self.inner, other.inner) {
290 (None, None) | (Some(_), None) => true,
291 (None, Some(_)) => false,
292 (Some(i), Some(j)) => i.lower <= j.lower && j.upper <= i.upper,
293 }
294 }
295
296 pub fn overlaps(&self, other: &Range<B>) -> bool {
297 match (self.inner, other.inner) {
298 (Some(s), Some(o)) => {
299 let r = match s.cmp(&o) {
300 Ordering::Equal => Ordering::Equal,
301 Ordering::Less => s.upper.range_bound_cmp(&o.lower),
302 Ordering::Greater => o.upper.range_bound_cmp(&s.lower),
303 };
304
305 matches!(r, Ordering::Greater | Ordering::Equal)
307 }
308 _ => false,
309 }
310 }
311
312 pub fn before(&self, other: &Range<B>) -> bool {
313 match (self.inner, other.inner) {
314 (Some(s), Some(o)) => {
315 matches!(s.upper.range_bound_cmp(&o.lower), Ordering::Less)
316 }
317 _ => false,
318 }
319 }
320
321 pub fn after(&self, other: &Range<B>) -> bool {
322 match (self.inner, other.inner) {
323 (Some(s), Some(o)) => {
324 matches!(s.lower.range_bound_cmp(&o.upper), Ordering::Greater)
325 }
326 _ => false,
327 }
328 }
329
330 pub fn overleft(&self, other: &Range<B>) -> bool {
331 match (self.inner, other.inner) {
332 (Some(s), Some(o)) => {
333 matches!(
334 s.upper.range_bound_cmp(&o.upper),
335 Ordering::Less | Ordering::Equal
336 )
337 }
338 _ => false,
339 }
340 }
341
342 pub fn overright(&self, other: &Range<B>) -> bool {
343 match (self.inner, other.inner) {
344 (Some(s), Some(o)) => {
345 matches!(
346 s.lower.range_bound_cmp(&o.lower),
347 Ordering::Greater | Ordering::Equal
348 )
349 }
350 _ => false,
351 }
352 }
353
354 pub fn adjacent(&self, other: &Range<B>) -> bool {
355 match (self.inner, other.inner) {
356 (Some(s), Some(o)) => {
357 for (lower, upper) in [(s.lower, o.upper), (o.lower, s.upper)] {
359 if let (Some(l), Some(u)) = (lower.bound, upper.bound) {
360 if lower.inclusive ^ upper.inclusive && l == u {
362 return true;
363 }
364 }
365 }
366 false
367 }
368 _ => false,
369 }
370 }
371
372 pub fn union(&self, other: &Range<B>) -> Result<Range<B>, InvalidRangeError> {
373 let (s, o) = match (self.inner, other.inner) {
375 (None, None) => return Ok(Range { inner: None }),
376 (inner @ Some(_), None) | (None, inner @ Some(_)) => return Ok(Range { inner }),
377 (Some(s), Some(o)) => {
378 if !(self.overlaps(other) || self.adjacent(other)) {
380 return Err(InvalidRangeError::DiscontiguousUnion);
381 }
382 (s, o)
383 }
384 };
385
386 let lower = std::cmp::min(s.lower, o.lower);
387 let upper = std::cmp::max(s.upper, o.upper);
388
389 Ok(Range {
390 inner: Some(RangeInner { lower, upper }),
391 })
392 }
393
394 pub fn intersection(&self, other: &Range<B>) -> Range<B> {
395 let (s, o) = match (self.inner, other.inner) {
397 (Some(s), Some(o)) => {
398 if !self.overlaps(other) {
399 return Range { inner: None };
400 }
401
402 (s, o)
403 }
404 _ => return Range { inner: None },
405 };
406
407 let lower = std::cmp::max(s.lower, o.lower);
408 let upper = std::cmp::min(s.upper, o.upper);
409
410 Range {
411 inner: Some(RangeInner { lower, upper }),
412 }
413 }
414
415 pub fn difference(&self, other: &Range<B>) -> Result<Range<Datum<'a>>, InvalidRangeError> {
419 use std::cmp::Ordering::*;
420
421 if !self.overlaps(other) {
423 return Ok(self.into_bounds(Datum::from));
424 }
425
426 let (s, o) = match (self.inner, other.inner) {
427 (None, _) | (_, None) => unreachable!("already returned from overlap check"),
428 (Some(s), Some(o)) => (s, o),
429 };
430
431 let ll = s.lower.cmp(&o.lower);
432 let uu = s.upper.cmp(&o.upper);
433
434 let r = match (ll, uu) {
435 (Less, Greater) => return Err(InvalidRangeError::DiscontiguousDifference),
437 (Greater | Equal, Less | Equal) => Range { inner: None },
439 (Greater | Equal, Greater) => {
440 let lower = RangeBound {
441 inclusive: !o.upper.inclusive,
442 bound: o.upper.bound,
443 };
444 Range {
445 inner: Some(RangeInner {
446 lower,
447 upper: s.upper,
448 }),
449 }
450 }
451 (Less, Less | Equal) => {
452 let upper = RangeBound {
453 inclusive: !o.lower.inclusive,
454 bound: o.lower.bound,
455 };
456 Range {
457 inner: Some(RangeInner {
458 lower: s.lower,
459 upper,
460 }),
461 }
462 }
463 };
464
465 let mut r = r.into_bounds(Datum::from);
466
467 r.canonicalize()?;
468
469 Ok(r)
470 }
471}
472
473impl<'a> Range<Datum<'a>> {
474 pub fn canonicalize(&mut self) -> Result<(), InvalidRangeError> {
485 let (lower, upper) = match &mut self.inner {
486 Some(inner) => (&mut inner.lower, &mut inner.upper),
487 None => return Ok(()),
488 };
489
490 match (lower.bound, upper.bound) {
491 (Some(l), Some(u)) => {
492 assert_eq!(
493 DatumKind::from(l),
494 DatumKind::from(u),
495 "finite bounds must be of same type"
496 );
497 if l > u {
498 return Err(InvalidRangeError::MisorderedRangeBounds);
499 }
500 }
501 _ => {}
502 };
503
504 lower.canonicalize()?;
505 upper.canonicalize()?;
506
507 if !(lower.inclusive && upper.inclusive)
510 && lower.bound >= upper.bound
511 && upper.bound.is_some()
513 {
514 self.inner = None
516 }
517
518 Ok(())
519 }
520}
521
522#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
524pub struct RangeInner<B> {
525 pub lower: RangeLowerBound<B>,
526 pub upper: RangeUpperBound<B>,
527}
528
529impl<B: Display> Display for RangeInner<B> {
530 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531 f.write_str(if self.lower.inclusive { "[" } else { "(" })?;
532 self.lower.fmt(f)?;
533 f.write_str(",")?;
534 Display::fmt(&self.upper, f)?;
535 f.write_str(if self.upper.inclusive { "]" } else { ")" })
536 }
537}
538
539impl<B: Ord> Ord for RangeInner<B> {
540 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
541 self.lower
542 .cmp(&other.lower)
543 .then(self.upper.cmp(&other.upper))
544 }
545}
546
547impl<B: PartialOrd + Ord> PartialOrd for RangeInner<B> {
548 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
549 Some(self.cmp(other))
550 }
551}
552
553#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
555pub struct RangeBound<B, const UPPER: bool = false> {
556 pub inclusive: bool,
557 pub bound: Option<B>,
559}
560
561impl<const UPPER: bool, D: Display> Display for RangeBound<D, UPPER> {
562 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563 match &self.bound {
564 None => Ok(()),
565 Some(bound) => bound.fmt(f),
566 }
567 }
568}
569
570impl<const UPPER: bool, D: Ord> Ord for RangeBound<D, UPPER> {
571 fn cmp(&self, other: &Self) -> Ordering {
572 let mut cmp = self.bound.cmp(&other.bound);
574 if UPPER && other.bound.is_none() ^ self.bound.is_none() {
576 cmp = cmp.reverse();
577 }
578 cmp.then(if self.inclusive == other.inclusive {
581 Ordering::Equal
582 } else if self.inclusive {
583 if UPPER {
584 Ordering::Greater
585 } else {
586 Ordering::Less
587 }
588 } else if UPPER {
589 Ordering::Less
590 } else {
591 Ordering::Greater
592 })
593 }
594}
595
596impl<const UPPER: bool, D: PartialOrd + Ord> PartialOrd for RangeBound<D, UPPER> {
597 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
598 Some(self.cmp(other))
599 }
600}
601
602pub type RangeLowerBound<B> = RangeBound<B, false>;
604
605pub type RangeUpperBound<B> = RangeBound<B, true>;
607
608impl<'a, const UPPER: bool, B: Copy + Ord + PartialOrd + Display + Debug> RangeBound<B, UPPER>
611where
612 Datum<'a>: From<B>,
613{
614 fn elem_cmp<T: RangeOps<'a>>(&self, elem: &T) -> Ordering
619 where
620 <T as TryFrom<Datum<'a>>>::Error: std::fmt::Debug,
621 {
622 match self.bound.map(|bound| <T>::unwrap_datum(bound.into())) {
623 None if UPPER => Ordering::Greater,
624 None => Ordering::Less,
625 Some(bound) => bound.cmp(elem),
626 }
627 }
628
629 fn satisfied_by<T: RangeOps<'a>>(&self, elem: &T) -> bool
631 where
632 <T as TryFrom<Datum<'a>>>::Error: std::fmt::Debug,
633 {
634 match self.elem_cmp(elem) {
635 Ordering::Equal => self.inclusive,
638 Ordering::Greater => UPPER,
640 Ordering::Less => !UPPER,
642 }
643 }
644
645 fn range_bound_cmp<const OTHER_UPPER: bool>(
648 &self,
649 other: &RangeBound<B, OTHER_UPPER>,
650 ) -> Ordering {
651 if UPPER == OTHER_UPPER {
652 return self.cmp(&RangeBound {
653 inclusive: other.inclusive,
654 bound: other.bound,
655 });
656 }
657
658 if self.bound.is_none() || other.bound.is_none() {
661 return if UPPER {
662 Ordering::Greater
663 } else {
664 Ordering::Less
665 };
666 }
667 let cmp = self.bound.cmp(&other.bound);
669 cmp.then(if self.inclusive && other.inclusive {
672 Ordering::Equal
673 } else if UPPER {
674 Ordering::Less
675 } else {
676 Ordering::Greater
677 })
678 }
679}
680
681impl<'a, const UPPER: bool> RangeBound<Datum<'a>, UPPER> {
682 pub fn new(d: Datum<'a>, inclusive: bool) -> RangeBound<Datum<'a>, UPPER> {
688 RangeBound {
689 inclusive,
690 bound: match d {
691 Datum::Null => None,
692 o => Some(o),
693 },
694 }
695 }
696
697 fn canonicalize(&mut self) -> Result<(), InvalidRangeError> {
701 Ok(match self.bound {
702 None => {
703 self.inclusive = false;
704 }
705 Some(value) => match value {
706 d @ Datum::Int32(_) => self.canonicalize_inner::<i32>(d)?,
707 d @ Datum::Int64(_) => self.canonicalize_inner::<i64>(d)?,
708 d @ Datum::Date(_) => self.canonicalize_inner::<Date>(d)?,
709 Datum::Numeric(..) | Datum::Timestamp(..) | Datum::TimestampTz(..) => {}
710 d => unreachable!("{d:?} not yet supported in ranges"),
711 },
712 })
713 }
714
715 fn canonicalize_inner<T: RangeOps<'a>>(&mut self, d: Datum<'a>) -> Result<(), InvalidRangeError>
721 where
722 <T as TryFrom<Datum<'a>>>::Error: std::fmt::Debug,
723 {
724 if UPPER == self.inclusive {
726 let cur = <T>::unwrap_datum(d);
727 self.bound = Some(
728 cur.step()
729 .ok_or_else(|| {
730 InvalidRangeError::CanonicalizationOverflow(T::err_type_name().into())
731 })?
732 .into(),
733 );
734 self.inclusive = !UPPER;
735 }
736
737 Ok(())
738 }
739}
740
741#[derive(
742 Arbitrary, Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect,
743)]
744pub enum InvalidRangeError {
745 MisorderedRangeBounds,
746 CanonicalizationOverflow(Box<str>),
747 InvalidRangeBoundFlags,
748 DiscontiguousUnion,
749 DiscontiguousDifference,
750 NullRangeBoundFlags,
751}
752
753impl Display for InvalidRangeError {
754 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
755 match self {
756 InvalidRangeError::MisorderedRangeBounds => {
757 f.write_str("range lower bound must be less than or equal to range upper bound")
758 }
759 InvalidRangeError::CanonicalizationOverflow(t) => {
760 write!(f, "{} out of range", t)
761 }
762 InvalidRangeError::InvalidRangeBoundFlags => f.write_str("invalid range bound flags"),
763 InvalidRangeError::DiscontiguousUnion => {
764 f.write_str("result of range union would not be contiguous")
765 }
766 InvalidRangeError::DiscontiguousDifference => {
767 f.write_str("result of range difference would not be contiguous")
768 }
769 InvalidRangeError::NullRangeBoundFlags => {
770 f.write_str("range constructor flags argument must not be null")
771 }
772 }
773 }
774}
775
776impl Error for InvalidRangeError {
777 fn source(&self) -> Option<&(dyn Error + 'static)> {
778 None
779 }
780}
781
782impl From<InvalidRangeError> for String {
784 fn from(e: InvalidRangeError) -> Self {
785 e.to_string()
786 }
787}
788
789impl RustType<ProtoInvalidRangeError> for InvalidRangeError {
790 fn into_proto(&self) -> ProtoInvalidRangeError {
791 use Kind::*;
792 use proto_invalid_range_error::*;
793 let kind = match self {
794 InvalidRangeError::MisorderedRangeBounds => MisorderedRangeBounds(()),
795 InvalidRangeError::CanonicalizationOverflow(s) => {
796 CanonicalizationOverflow(s.into_proto())
797 }
798 InvalidRangeError::InvalidRangeBoundFlags => InvalidRangeBoundFlags(()),
799 InvalidRangeError::DiscontiguousUnion => DiscontiguousUnion(()),
800 InvalidRangeError::DiscontiguousDifference => DiscontiguousDifference(()),
801 InvalidRangeError::NullRangeBoundFlags => NullRangeBoundFlags(()),
802 };
803 ProtoInvalidRangeError { kind: Some(kind) }
804 }
805
806 fn from_proto(proto: ProtoInvalidRangeError) -> Result<Self, TryFromProtoError> {
807 use proto_invalid_range_error::Kind::*;
808 match proto.kind {
809 Some(kind) => Ok(match kind {
810 MisorderedRangeBounds(()) => InvalidRangeError::MisorderedRangeBounds,
811 CanonicalizationOverflow(s) => {
812 InvalidRangeError::CanonicalizationOverflow(s.into())
813 }
814 InvalidRangeBoundFlags(()) => InvalidRangeError::InvalidRangeBoundFlags,
815 DiscontiguousUnion(()) => InvalidRangeError::DiscontiguousUnion,
816 DiscontiguousDifference(()) => InvalidRangeError::DiscontiguousDifference,
817 NullRangeBoundFlags(()) => InvalidRangeError::NullRangeBoundFlags,
818 }),
819 None => Err(TryFromProtoError::missing_field(
820 "`ProtoInvalidRangeError::kind`",
821 )),
822 }
823 }
824}
825
826pub fn parse_range_bound_flags<'a>(flags: &'a str) -> Result<(bool, bool), InvalidRangeError> {
827 let mut flags = flags.chars();
828
829 let lower = match flags.next() {
830 Some('(') => false,
831 Some('[') => true,
832 _ => return Err(InvalidRangeError::InvalidRangeBoundFlags),
833 };
834
835 let upper = match flags.next() {
836 Some(')') => false,
837 Some(']') => true,
838 _ => return Err(InvalidRangeError::InvalidRangeBoundFlags),
839 };
840
841 match flags.next() {
842 Some(_) => Err(InvalidRangeError::InvalidRangeBoundFlags),
843 None => Ok((lower, upper)),
844 }
845}
846
847impl<'a, T: FromSql<'a>> FromSql<'a> for Range<T> {
848 fn from_sql(ty: &PgType, raw: &'a [u8]) -> Result<Range<T>, Box<dyn Error + Sync + Send>> {
849 let inner_typ = match ty {
850 &PgType::INT4_RANGE => PgType::INT4,
851 &PgType::INT8_RANGE => PgType::INT8,
852 &PgType::DATE_RANGE => PgType::DATE,
853 &PgType::NUM_RANGE => PgType::NUMERIC,
854 &PgType::TS_RANGE => PgType::TIMESTAMP,
855 &PgType::TSTZ_RANGE => PgType::TIMESTAMPTZ,
856 _ => unreachable!(),
857 };
858
859 let inner = match types::range_from_sql(raw)? {
860 types::Range::Empty => None,
861 types::Range::Nonempty(lower, upper) => {
862 let mut bounds = Vec::with_capacity(2);
863
864 for bound_outer in [lower, upper].into_iter() {
865 let bound = match bound_outer {
866 types::RangeBound::Exclusive(bound)
867 | types::RangeBound::Inclusive(bound) => bound
868 .map(|bound| T::from_sql(&inner_typ, bound))
869 .transpose()?,
870 types::RangeBound::Unbounded => None,
871 };
872 let inclusive = matches!(bound_outer, types::RangeBound::Inclusive(_));
873 bounds.push(RangeBound { bound, inclusive });
874 }
875
876 let lower = bounds.remove(0);
877 let upper = bounds.remove(0);
878 assert!(bounds.is_empty());
879
880 Some(RangeInner {
881 lower,
882 upper: RangeBound {
884 bound: upper.bound,
885 inclusive: upper.inclusive,
886 },
887 })
888 }
889 };
890
891 Ok(Range { inner })
892 }
893
894 fn accepts(ty: &PgType) -> bool {
895 matches!(
896 ty,
897 &PgType::INT4_RANGE
898 | &PgType::INT8_RANGE
899 | &PgType::DATE_RANGE
900 | &PgType::NUM_RANGE
901 | &PgType::TS_RANGE
902 | &PgType::TSTZ_RANGE
903 )
904 }
905}