mz_repr/adt/
range.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use 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
54/// A range of values along the domain `D`.
55///
56/// `D` is generic to facilitate interoperating over multiple representation,
57/// e.g. `Datum` and `mz_pgrepr::Value`. Because of the latter, we have to
58/// "manually derive" traits over `Range`.
59///
60/// Also notable, is that `Datum`s themselves store ranges as
61/// `Range<DatumNested<'a>>`, which lets us avoid unnecessary boxing of the
62/// range's finite bounds, which are most often expressed as `Datum`.
63pub struct Range<D> {
64    /// None value represents empty range
65    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
119/// Trait alias for traits required for generic range function implementations.
120pub 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    /// Increment `self` one step forward, if applicable. Return `None` if
126    /// overflows.
127    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
187// Totally generic range implementations.
188impl<D> Range<D> {
189    /// Create a new range.
190    ///
191    /// Note that when constructing `Range<Datum<'a>>`, the range must still be
192    /// canonicalized. If this becomes a common operation, we should consider
193    /// addinga `new_canonical` function that performs both steps.
194    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    /// Get the flag bits appropriate to use in our internal (i.e. row) encoding
201    /// of range values.
202    ///
203    /// Note that this differs from the flags appropriate to encode with
204    /// Postgres, which has `UB_INFINITE` and `LB_INCLUSIVE` in the alternate
205    /// position.
206    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    /// Get the flag bits appropriate to use in PG-compatible encodings of range
226    /// values.
227    ///
228    /// Note that this differs from the flags appropriate for our internal
229    /// encoding, which has `UB_INFINITE` and `LB_INCLUSIVE` in the alternate
230    /// position.
231    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    /// Converts `self` from having bounds of type `D` to type `O`, converting
251    /// the current bounds using `conv`.
252    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
273/// Range implementations meant to work with `Range<Datum>` and `Range<DatumNested>`.
274impl<'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                // If smaller upper is >= larger lower, elements overlap.
306                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                // Look at each (lower, upper) pair.
358                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 ..x](x.. or ..x)[x.., adjacent
361                        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        // Handle self or other being empty
374        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 not overlapping or adjacent, then result would not present continuity, so error.
379                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        // Handle self or other being empty
396        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    // Function requires canonicalization so must be taken into `Range<Datum>`,
416    // which can be taken back into `Range<DatumNested>` by the caller if need
417    // be.
418    pub fn difference(&self, other: &Range<B>) -> Result<Range<Datum<'a>>, InvalidRangeError> {
419        use std::cmp::Ordering::*;
420
421        // Difference op does nothing if no overlap.
422        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            // `self` totally contains `other`
436            (Less, Greater) => return Err(InvalidRangeError::DiscontiguousDifference),
437            // `other` totally contains `self`
438            (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    /// Canonicalize the range by PG's heuristics, which are:
475    /// - Infinite bounds are always exclusive
476    /// - If type has step:
477    ///  - Exclusive lower bounds are rewritten as inclusive += step
478    ///  - Inclusive lower bounds are rewritten as exclusive += step
479    /// - Ranges are empty if lower >= upper after prev. step unless range type
480    ///   does not have step and both bounds are inclusive
481    ///
482    /// # Panics
483    /// - If the upper and lower bounds are finite and of different types.
484    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        // The only way that you have two inclusive bounds with equal value are
508        // if type does not have step.
509        if !(lower.inclusive && upper.inclusive)
510            && lower.bound >= upper.bound
511            // None is less than any Some, so only need to check this condition.
512            && upper.bound.is_some()
513        {
514            // emtpy range
515            self.inner = None
516        }
517
518        Ok(())
519    }
520}
521
522/// Holds the upper and lower bounds for non-empty ranges.
523#[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/// Represents a terminal point of a range.
554#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
555pub struct RangeBound<B, const UPPER: bool = false> {
556    pub inclusive: bool,
557    /// None value represents an infinite bound.
558    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        // 1. Sort by bounds
573        let mut cmp = self.bound.cmp(&other.bound);
574        // 2. Infinite bounds vs. finite bounds are reversed for uppers.
575        if UPPER && other.bound.is_none() ^ self.bound.is_none() {
576            cmp = cmp.reverse();
577        }
578        // 3. Tie break by sorting by inclusivity, which is inverted between
579        //    lowers and uppers.
580        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
602/// A `RangeBound` that sorts correctly for use as a lower bound.
603pub type RangeLowerBound<B> = RangeBound<B, false>;
604
605/// A `RangeBound` that sorts correctly for use as an upper bound.
606pub type RangeUpperBound<B> = RangeBound<B, true>;
607
608// Generic RangeBound implementations meant to work over `RangeBound<Datum,..>`
609// and `RangeBound<DatumNested,..>`.
610impl<'a, const UPPER: bool, B: Copy + Ord + PartialOrd + Display + Debug> RangeBound<B, UPPER>
611where
612    Datum<'a>: From<B>,
613{
614    /// Determines where `elem` lies in relation to the range bound.
615    ///
616    /// # Panics
617    /// - If `self.bound.datum()` is not convertible to `T`.
618    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    /// Does `elem` satisfy this bound?
630    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            // Inclusive always satisfied with equality, regardless of upper or
636            // lower.
637            Ordering::Equal => self.inclusive,
638            // Upper satisfied with values less than itself
639            Ordering::Greater => UPPER,
640            // Lower satisfied with values greater than itself
641            Ordering::Less => !UPPER,
642        }
643    }
644
645    // Compares two `RangeBound`, which do not need to both be of the same
646    // `UPPER`.
647    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        // Handle cases where either are infinite bounds, which have special
659        // semantics.
660        if self.bound.is_none() || other.bound.is_none() {
661            return if UPPER {
662                Ordering::Greater
663            } else {
664                Ordering::Less
665            };
666        }
667        // 1. Sort by bounds
668        let cmp = self.bound.cmp(&other.bound);
669        // 2. Tie break by sorting by inclusivity, which is inverted between
670        //    lowers and uppers.
671        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    /// Create a new `RangeBound` whose value is "infinite" (i.e. None) if `d ==
683    /// Datum::Null`, otherwise finite (i.e. Some).
684    ///
685    /// There is not a corresponding generic implementation of this because
686    /// genericizing how to express infinite bounds is less clear.
687    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    /// Rewrite the bounds to the consistent format. This is absolutely
698    /// necessary to perform the correct equality/comparison operations on
699    /// types.
700    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    /// Canonicalize `self`'s representation for types that have discrete steps
716    /// between values.
717    ///
718    /// Continuous values (e.g. timestamps, numeric) must not be
719    /// canonicalized.
720    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        // Upper bounds must be exclusive, lower bounds inclusive
725        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
782// Required due to Proto decoding using string as its error type
783impl 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                    // Rewrite bound in terms of appropriate `UPPER`
883                    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}