1#![allow(dead_code)]
2
3use std::{
4 borrow::{Borrow, Cow},
5 fmt::Debug,
6 ops::Bound,
7};
8
9use itertools::Itertools;
10use serde::{Deserialize, Serialize};
11
12use crate::ir::FieldValue;
13
14#[non_exhaustive]
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
17pub enum CandidateValue<T> {
18 Impossible,
20
21 Single(T),
23
24 Multiple(Vec<T>),
26
27 Range(Range<T>),
31
32 All,
34}
35
36impl<T: Clone> CandidateValue<&T> {
37 pub(crate) fn cloned(&self) -> CandidateValue<T> {
39 match self {
40 CandidateValue::Impossible => CandidateValue::Impossible,
41 CandidateValue::Single(s) => CandidateValue::Single((*s).clone()),
42 CandidateValue::Multiple(m) => {
43 CandidateValue::Multiple(m.iter().copied().cloned().collect())
44 }
45 CandidateValue::Range(r) => CandidateValue::Range(r.cloned()),
46 CandidateValue::All => CandidateValue::All,
47 }
48 }
49}
50
51impl<T: Clone> CandidateValue<T> {
52 pub(crate) fn as_ref(&self) -> CandidateValue<&T> {
54 match self {
55 CandidateValue::Impossible => CandidateValue::Impossible,
56 CandidateValue::Single(s) => CandidateValue::Single(s),
57 CandidateValue::Multiple(m) => CandidateValue::Multiple(m.iter().collect()),
58 CandidateValue::Range(r) => CandidateValue::Range(r.as_ref()),
59 CandidateValue::All => CandidateValue::All,
60 }
61 }
62}
63
64impl<T: Clone> CandidateValue<Cow<'_, T>> {
65 pub(super) fn into_owned(self) -> CandidateValue<T> {
66 match self {
67 CandidateValue::Impossible => CandidateValue::Impossible,
68 CandidateValue::Single(s) => CandidateValue::Single(s.into_owned()),
69 CandidateValue::Multiple(mult) => {
70 CandidateValue::Multiple(mult.into_iter().map(|x| x.into_owned()).collect())
71 }
72 CandidateValue::Range(range) => CandidateValue::Range(range.into_owned()),
73 CandidateValue::All => CandidateValue::All,
74 }
75 }
76
77 pub(super) fn as_deref(&self) -> CandidateValue<&T> {
78 match self {
79 CandidateValue::Impossible => CandidateValue::Impossible,
80 CandidateValue::Single(s) => CandidateValue::Single(s.as_ref()),
81 CandidateValue::Multiple(mult) => {
82 CandidateValue::Multiple(mult.iter().map(|x| x.as_ref()).collect())
83 }
84 CandidateValue::Range(range) => CandidateValue::Range(range.as_deref()),
85 CandidateValue::All => CandidateValue::All,
86 }
87 }
88}
89
90impl<T: Clone + PartialEq> PartialEq<CandidateValue<&T>> for CandidateValue<Cow<'_, T>> {
91 fn eq(&self, other: &CandidateValue<&T>) -> bool {
92 match (self, other) {
93 (CandidateValue::Impossible, CandidateValue::Impossible) => true,
94 (CandidateValue::Single(l), CandidateValue::Single(r)) => l.as_ref() == *r,
95 (CandidateValue::Multiple(mult_l), CandidateValue::Multiple(mult_r)) => {
96 mult_l.len() == mult_r.len() && mult_l.iter().zip(mult_r.iter()).all_equal()
97 }
98 (CandidateValue::Range(l), CandidateValue::Range(r)) => l.as_deref() == *r,
99 (CandidateValue::All, CandidateValue::All) => true,
100 _ => false,
101 }
102 }
103}
104
105impl<T: Clone + PartialEq> PartialEq<CandidateValue<T>> for CandidateValue<Cow<'_, T>> {
106 fn eq(&self, other: &CandidateValue<T>) -> bool {
107 match (self, other) {
108 (CandidateValue::Impossible, CandidateValue::Impossible) => true,
109 (CandidateValue::Single(l), CandidateValue::Single(r)) => l.as_ref() == r,
110 (CandidateValue::Multiple(mult_l), CandidateValue::Multiple(mult_r)) => {
111 mult_l.len() == mult_r.len() && mult_l.iter().zip(mult_r.iter()).all_equal()
112 }
113 (CandidateValue::Range(l), CandidateValue::Range(r)) => l.as_deref() == r.as_ref(),
114 (CandidateValue::All, CandidateValue::All) => true,
115 _ => false,
116 }
117 }
118}
119
120impl<T: Debug + Clone + PartialEq + Eq + PartialOrd + NullableValue + Default> CandidateValue<T> {
121 pub(super) fn intersect(&mut self, mut other: CandidateValue<T>) {
122 match self {
123 Self::Impossible => {} Self::Single(val) => {
125 match other {
128 Self::Impossible => *self = CandidateValue::Impossible,
129 Self::Single(other) => {
130 if val != &other {
131 *self = CandidateValue::Impossible;
132 }
133 }
134 Self::Multiple(others) => {
135 if !others.contains(val) {
136 *self = CandidateValue::Impossible;
137 }
138 }
139 Self::Range(others) => {
140 if !others.contains(val) {
141 *self = CandidateValue::Impossible;
142 }
143 }
144 Self::All => {} }
146 }
147 Self::Multiple(multiple) => {
148 match other {
149 Self::Impossible => *self = CandidateValue::Impossible,
150 Self::Single(other) => {
151 if multiple.contains(&other) {
155 *self = Self::Single(other);
156 } else {
157 *self = Self::Impossible;
158 }
159 }
160 Self::Multiple(_) | Self::Range(_) => {
161 if let Self::Multiple(others) = &other {
164 multiple.retain(|value| others.contains(value));
165 } else if let Self::Range(others) = &other {
166 multiple.retain(|value| others.contains(value));
167 } else {
168 unreachable!("expected only Multiple or Range in this branch, but got: {other:?}");
169 }
170 }
171 Self::All => {} }
173 }
174 Self::Range(range) => {
175 if let CandidateValue::Range(other) = other {
176 range.intersect(other)
177 } else {
178 let mut placeholder = CandidateValue::All;
180 std::mem::swap(self, &mut placeholder);
181 other.intersect(placeholder);
182 *self = other;
183 }
184 }
185 Self::All => {
186 *self = other;
188 }
189 }
190
191 self.normalize();
192 }
193
194 pub(super) fn exclude_single_value<U: PartialEq + Eq + PartialOrd + NullableValue>(
195 &mut self,
196 value: &U,
197 ) where
198 T: Borrow<U>,
199 {
200 match self {
201 CandidateValue::Impossible => {} CandidateValue::Single(s) => {
203 if <T as Borrow<U>>::borrow(s) == value {
204 *self = CandidateValue::Impossible;
205 }
206 }
207 CandidateValue::Multiple(multiple) => {
208 multiple.retain(|v| v.borrow() != value);
209 self.normalize();
210 }
211 CandidateValue::Range(range) => {
212 if value.is_null() {
213 range.null_included = false;
214 } else {
215 if let Bound::Included(incl) = range.start_bound() {
219 if incl.borrow() == value {
220 range.start = Bound::Excluded(incl.clone());
221 }
222 }
223 if let Bound::Included(incl) = range.end_bound() {
224 if incl.borrow() == value {
225 range.end = Bound::Excluded(incl.clone());
226 }
227 }
228 }
229 self.normalize();
230 }
231 CandidateValue::All => {
232 if value.is_null() {
237 *self = CandidateValue::Range(Range::full_non_null())
238 }
239 }
240 }
241 }
242
243 pub(super) fn normalize(&mut self) {
244 let next_self = if let Self::Range(range) = self {
245 if range.null_only() {
246 Some(Self::Single(T::default()))
247 } else if range.degenerate() {
248 Some(CandidateValue::Impossible)
249 } else if range.start_bound() == range.end_bound() {
250 if *range == Range::full() {
251 Some(CandidateValue::All)
252 } else if let Bound::Included(b) = range.start_bound() {
253 if range.null_included() {
255 Some(Self::Multiple(vec![T::default(), b.clone()]))
256 } else {
257 Some(Self::Single(b.clone()))
258 }
259 } else {
260 None
261 }
262 } else {
263 None
264 }
265 } else if let Self::Multiple(values) = self {
266 if values.is_empty() {
267 Some(Self::Impossible)
268 } else if values.len() == 1 {
269 Some(Self::Single(values.pop().expect("no value present")))
270 } else {
271 None
272 }
273 } else {
274 None
275 };
276
277 if let Some(next_self) = next_self {
278 *self = next_self;
279 }
280 }
281}
282
283pub trait NullableValue {
285 fn is_null(&self) -> bool;
287}
288
289impl NullableValue for FieldValue {
290 fn is_null(&self) -> bool {
291 matches!(self, FieldValue::Null)
292 }
293}
294
295impl NullableValue for &FieldValue {
296 fn is_null(&self) -> bool {
297 matches!(*self, FieldValue::Null)
298 }
299}
300
301impl NullableValue for Cow<'_, FieldValue> {
302 fn is_null(&self) -> bool {
303 match self {
304 Cow::Borrowed(v) => v.is_null(),
305 Cow::Owned(v) => v.is_null(),
306 }
307 }
308}
309
310#[non_exhaustive]
312#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
313pub struct Range<T> {
314 start: Bound<T>,
315 end: Bound<T>,
316 null_included: bool,
317}
318
319impl<T: Clone> Range<&T> {
320 pub fn cloned(&self) -> Range<T> {
322 let start = match self.start {
323 Bound::Unbounded => Bound::Unbounded,
324 Bound::Included(b) => Bound::Included(b.clone()),
325 Bound::Excluded(b) => Bound::Excluded(b.clone()),
326 };
327 let end = match self.end {
328 Bound::Unbounded => Bound::Unbounded,
329 Bound::Included(b) => Bound::Included(b.clone()),
330 Bound::Excluded(b) => Bound::Excluded(b.clone()),
331 };
332 Range { start, end, null_included: self.null_included }
333 }
334}
335
336impl<T: Clone> Range<Cow<'_, T>> {
337 fn into_owned(self) -> Range<T> {
338 let start = self.start.map(|b| b.into_owned());
339 let end = self.end.map(|b| b.into_owned());
340 Range { start, end, null_included: self.null_included }
341 }
342
343 fn as_deref(&self) -> Range<&T> {
344 let start = match &self.start {
345 Bound::Included(incl) => Bound::Included(incl.as_ref()),
346 Bound::Excluded(excl) => Bound::Excluded(excl.as_ref()),
347 Bound::Unbounded => Bound::Unbounded,
348 };
349 let end = match &self.end {
350 Bound::Included(incl) => Bound::Included(incl.as_ref()),
351 Bound::Excluded(excl) => Bound::Excluded(excl.as_ref()),
352 Bound::Unbounded => Bound::Unbounded,
353 };
354 Range { start, end, null_included: self.null_included }
355 }
356}
357
358impl<T> Range<T> {
359 pub const fn full() -> Range<T> {
361 Self { start: Bound::Unbounded, end: Bound::Unbounded, null_included: true }
362 }
363
364 pub const fn full_non_null() -> Range<T> {
366 Self { start: Bound::Unbounded, end: Bound::Unbounded, null_included: false }
367 }
368
369 pub fn as_ref(&self) -> Range<&T> {
371 Range {
372 start: self.start.as_ref(),
373 end: self.end.as_ref(),
374 null_included: self.null_included,
375 }
376 }
377}
378
379impl<T: Debug + Clone + PartialEq + Eq + PartialOrd + NullableValue> Range<T> {
380 pub(super) fn new(start: Bound<T>, end: Bound<T>, null_included: bool) -> Self {
381 match &start {
382 Bound::Included(v) | Bound::Excluded(v) => {
383 assert!(!v.is_null(), "cannot bound range with null value")
384 }
385 Bound::Unbounded => {}
386 }
387 match &end {
388 Bound::Included(v) | Bound::Excluded(v) => {
389 assert!(!v.is_null(), "cannot bound range with null value")
390 }
391 Bound::Unbounded => {}
392 }
393 Self { start, end, null_included }
394 }
395
396 pub(super) fn with_start(start: Bound<T>, null_included: bool) -> Self {
397 match &start {
398 Bound::Included(v) | Bound::Excluded(v) => {
399 assert!(!v.is_null(), "cannot bound range with null value")
400 }
401 Bound::Unbounded => {}
402 }
403 Self { start, end: Bound::Unbounded, null_included }
404 }
405
406 pub(super) fn with_end(end: Bound<T>, null_included: bool) -> Self {
407 match &end {
408 Bound::Included(v) | Bound::Excluded(v) => {
409 assert!(!v.is_null(), "cannot bound range with null value")
410 }
411 Bound::Unbounded => {}
412 }
413 Self { start: Bound::Unbounded, end, null_included }
414 }
415
416 pub(super) fn intersect(&mut self, other: Range<T>) {
417 match &mut self.start {
418 Bound::Included(start) => {
419 debug_assert!(!start.is_null());
420 match &other.start {
421 Bound::Included(other_start) => {
422 debug_assert!(!other_start.is_null());
423 if &*start < other_start {
424 self.start = other.start;
425 }
426 }
427 Bound::Excluded(other_start) => {
428 debug_assert!(!other_start.is_null());
429 if &*start <= other_start {
430 self.start = other.start;
432 }
433 }
434 Bound::Unbounded => {}
435 }
436 }
437 Bound::Excluded(start) => {
438 debug_assert!(!start.is_null());
439 match &other.start {
440 Bound::Included(other_start) | Bound::Excluded(other_start) => {
441 debug_assert!(!other_start.is_null());
442 if &*start < other_start {
443 self.start = other.start;
444 }
445 }
446 Bound::Unbounded => {}
447 }
448 }
449 Bound::Unbounded => self.start = other.start,
450 }
451
452 match &mut self.end {
453 Bound::Included(end) => {
454 debug_assert!(!end.is_null());
455 match &other.end {
456 Bound::Included(other_end) => {
457 debug_assert!(!other_end.is_null());
458 if &*end > other_end {
459 self.end = other.end;
460 }
461 }
462 Bound::Excluded(other_end) => {
463 debug_assert!(!other_end.is_null());
464 if &*end >= other_end {
465 self.end = other.end;
467 }
468 }
469 Bound::Unbounded => {}
470 }
471 }
472 Bound::Excluded(end) => {
473 debug_assert!(!end.is_null());
474 match &other.end {
475 Bound::Included(other_end) | Bound::Excluded(other_end) => {
476 debug_assert!(!other_end.is_null());
477 if &*end > other_end {
478 self.end = other.end;
479 }
480 }
481 Bound::Unbounded => {}
482 }
483 }
484 Bound::Unbounded => self.end = other.end,
485 }
486
487 self.null_included &= other.null_included;
488 }
489
490 #[inline]
492 pub fn start_bound(&self) -> Bound<&T> {
493 self.start.as_ref()
494 }
495
496 #[inline]
498 pub fn end_bound(&self) -> Bound<&T> {
499 self.end.as_ref()
500 }
501
502 #[inline]
504 pub fn null_included(&self) -> bool {
505 self.null_included
506 }
507
508 #[inline]
511 pub fn degenerate(&self) -> bool {
512 match (self.start_bound(), self.end_bound()) {
513 (Bound::Included(l), Bound::Included(r)) => l > r,
514 (Bound::Included(l), Bound::Excluded(r))
515 | (Bound::Excluded(l), Bound::Included(r))
516 | (Bound::Excluded(l), Bound::Excluded(r)) => l >= r,
517 (_, Bound::Unbounded) | (Bound::Unbounded, _) => false,
518 }
519 }
520
521 #[inline]
523 pub fn null_only(&self) -> bool {
524 self.null_included && self.degenerate()
525 }
526
527 pub fn contains(&self, item: &T) -> bool {
529 let is_null = item.is_null();
530 if is_null {
531 self.null_included
532 } else {
533 (match self.start_bound() {
534 Bound::Included(start) => start <= item,
535 Bound::Excluded(start) => start < item,
536 Bound::Unbounded => true,
537 }) && (match self.end_bound() {
538 Bound::Included(end) => item <= end,
539 Bound::Excluded(end) => item < end,
540 Bound::Unbounded => true,
541 })
542 }
543 }
544}
545
546#[cfg(test)]
547mod tests {
548 use std::ops::Bound;
549
550 use itertools::Itertools;
551
552 use crate::ir::FieldValue;
553
554 use super::CandidateValue;
555
556 #[test]
557 fn candidate_intersecting() {
558 use super::Range as R;
559 use CandidateValue::*;
560 let one = FieldValue::Int64(1);
561 let two = FieldValue::Int64(2);
562 let three = FieldValue::Int64(3);
563 let four = FieldValue::Int64(4);
564
565 let test_cases = [
566 (Impossible, Impossible, Impossible),
568 (Impossible, Single(&one), Impossible),
569 (Impossible, Multiple(vec![&one, &two]), Impossible),
570 (Impossible, Range(R::with_start(Bound::Included(&one), true)), Impossible),
571 (Single(&one), Impossible, Impossible),
574 (Multiple(vec![&one, &two]), Impossible, Impossible),
575 (Range(R::with_start(Bound::Included(&one), true)), Impossible, Impossible),
576 (Single(&FieldValue::NULL), Single(&one), Impossible),
579 (Single(&FieldValue::NULL), Multiple(vec![&one, &two]), Impossible),
580 (
581 Single(&FieldValue::NULL),
582 Range(R::with_start(Bound::Included(&one), false)),
583 Impossible,
584 ),
585 (Single(&one), Single(&two), Impossible),
588 (Single(&one), Multiple(vec![&two, &three]), Impossible),
589 (Multiple(vec![&one, &two]), Single(&three), Impossible),
590 (Multiple(vec![&one, &two]), Multiple(vec![&three, &four]), Impossible),
591 (Single(&one), Range(R::with_start(Bound::Excluded(&one), true)), Impossible),
594 (Single(&one), Range(R::with_start(Bound::Included(&two), false)), Impossible),
595 (
596 Multiple(vec![&two, &three]),
597 Range(R::with_end(Bound::Included(&one), true)),
598 Impossible,
599 ),
600 (
601 Multiple(vec![&two, &three]),
602 Range(R::with_end(Bound::Excluded(&two), false)),
603 Impossible,
604 ),
605 (Single(&one), Single(&one), Single(&one)),
609 (Multiple(vec![&one, &two]), Single(&one), Single(&one)),
610 (Single(&one), Multiple(vec![&one, &two]), Single(&one)),
611 (Single(&one), Range(R::with_start(Bound::Included(&one), false)), Single(&one)),
612 (Single(&one), Range(R::with_end(Bound::Excluded(&two), false)), Single(&one)),
613 (
616 Single(&FieldValue::NULL),
617 Multiple(vec![&one, &FieldValue::Null]),
618 Single(&FieldValue::NULL),
619 ),
620 (
621 Single(&FieldValue::NULL),
622 Range(R::with_end(Bound::Excluded(&two), true)),
623 Single(&FieldValue::NULL),
624 ),
625 (
626 Single(&FieldValue::NULL),
627 Range(R::with_start(Bound::Excluded(&two), true)),
628 Single(&FieldValue::NULL),
629 ),
630 (
631 Single(&FieldValue::NULL),
632 Range(R::new(Bound::Unbounded, Bound::Unbounded, true)),
633 Single(&FieldValue::NULL),
634 ),
635 (
636 Single(&FieldValue::NULL),
637 Range(R::new(Bound::Excluded(&one), Bound::Excluded(&one), true)),
638 Single(&FieldValue::NULL),
639 ),
640 (
643 Multiple(vec![&one, &FieldValue::Null, &two, &three]),
644 Multiple(vec![&one, &FieldValue::Null, &four]),
645 Multiple(vec![&one, &FieldValue::Null]),
646 ),
647 (
650 Range(R::new(Bound::Included(&one), Bound::Included(&one), true)),
651 Range(R::new(Bound::Included(&two), Bound::Included(&two), true)),
652 Single(&FieldValue::NULL),
653 ),
654 (
655 Range(R::new(Bound::Included(&one), Bound::Excluded(&two), true)),
656 Range(R::new(Bound::Included(&two), Bound::Excluded(&three), true)),
657 Single(&FieldValue::NULL),
658 ),
659 (
662 Range(R::new(Bound::Included(&one), Bound::Included(&two), false)),
663 Range(R::new(Bound::Included(&two), Bound::Included(&three), true)),
664 Single(&two),
665 ),
666 (
669 Range(R::new(Bound::Included(&one), Bound::Included(&one), true)),
670 Range(R::new(Bound::Included(&two), Bound::Included(&two), false)),
671 Impossible,
672 ),
673 (
674 Range(R::new(Bound::Included(&one), Bound::Excluded(&two), false)),
675 Range(R::new(Bound::Included(&two), Bound::Excluded(&three), true)),
676 Impossible,
677 ),
678 (
682 Range(R::new(Bound::Included(&one), Bound::Included(&two), true)),
683 Range(R::new(Bound::Included(&two), Bound::Included(&three), true)),
684 Multiple(vec![&FieldValue::NULL, &two]),
685 ),
686 (
689 Range(R::new(Bound::Included(&one), Bound::Included(&three), true)),
690 Range(R::new(Bound::Included(&two), Bound::Included(&four), true)),
691 Range(R::new(Bound::Included(&two), Bound::Included(&three), true)),
692 ),
693 (
694 Range(R::new(Bound::Included(&one), Bound::Included(&three), false)),
695 Range(R::new(Bound::Included(&two), Bound::Included(&four), true)),
696 Range(R::new(Bound::Included(&two), Bound::Included(&three), false)),
697 ),
698 (
699 Range(R::new(Bound::Included(&one), Bound::Excluded(&three), true)),
700 Range(R::new(Bound::Included(&two), Bound::Included(&four), true)),
701 Range(R::new(Bound::Included(&two), Bound::Excluded(&three), true)),
702 ),
703 (
704 Range(R::new(Bound::Included(&one), Bound::Included(&three), false)),
705 Range(R::new(Bound::Excluded(&two), Bound::Included(&four), true)),
706 Range(R::new(Bound::Excluded(&two), Bound::Included(&three), false)),
707 ),
708 (Multiple(vec![&one, &two]), Multiple(vec![&two, &three]), Single(&two)),
712 (Multiple(vec![&two, &three]), Multiple(vec![&one, &two]), Single(&two)),
713 (
714 Multiple(vec![&two, &three]),
715 Multiple(vec![&one, &two, &three, &four]),
716 Multiple(vec![&two, &three]),
717 ),
718 (
719 Multiple(vec![&one, &two]),
720 Range(R::new(Bound::Included(&two), Bound::Included(&three), true)),
721 Single(&two),
722 ),
723 (
724 Multiple(vec![&two, &three]),
725 Range(R::new(Bound::Included(&one), Bound::Included(&two), true)),
726 Single(&two),
727 ),
728 (
729 Multiple(vec![&two, &three]),
730 Range(R::new(Bound::Included(&one), Bound::Included(&four), true)),
731 Multiple(vec![&two, &three]),
732 ),
733 (All, Impossible, Impossible),
736 (Impossible, All, Impossible),
737 (All, Single(&one), Single(&one)),
738 (Multiple(vec![&one, &two]), All, Multiple(vec![&one, &two])),
739 (
740 All,
741 Range(R::with_start(Bound::Included(&one), true)),
742 Range(R::with_start(Bound::Included(&one), true)),
743 ),
744 (All, All, All),
745 ];
746
747 for (original, intersected, expected) in test_cases {
748 let mut base = original.clone();
749 base.intersect(intersected.clone());
750 assert_eq!(expected, base, "{original:?} + {intersected:?} = {base:?} != {expected:?}");
751
752 let mut base = intersected.clone();
753 base.intersect(original.clone());
754 assert_eq!(expected, base, "{intersected:?} + {original:?} = {base:?} != {expected:?}");
755 }
756 }
757
758 #[test]
761 fn candidate_intersecting_preserves_overlap() {
762 use CandidateValue::*;
763 let one = FieldValue::Int64(1);
764 let two = FieldValue::Int64(2);
765 let three = FieldValue::Int64(3);
766 let four = FieldValue::Int64(4);
767 use super::Range as R;
768
769 let one_incl = Bound::Included(&one);
770 let one_excl = Bound::Excluded(&one);
771 let four_incl = Bound::Included(&four);
772 let four_excl = Bound::Excluded(&four);
773
774 let mut larger_ranges = vec![];
775 for one in [&one_incl, &one_excl, &Bound::Unbounded] {
776 for four in [&four_incl, &four_excl, &Bound::Unbounded] {
777 for null_included in [true, false] {
778 larger_ranges.push(Range(R::new(*one, *four, null_included)));
779 }
780 }
781 }
782
783 let two_incl = Bound::Included(&two);
784 let two_excl = Bound::Excluded(&two);
785 let three_incl = Bound::Included(&three);
786 let three_excl = Bound::Excluded(&three);
787
788 let mut smaller_ranges = vec![];
789 for two in [&two_incl, &two_excl] {
790 for three in [&three_incl, &three_excl] {
791 for null_included in [true, false] {
792 smaller_ranges.push(Range(R::new(*two, *three, null_included)));
793 }
794 }
795 }
796
797 for (original, intersected) in larger_ranges.into_iter().cartesian_product(smaller_ranges) {
798 let mut expected = intersected.clone();
799 if let Range(r) = &mut expected {
800 if let Range(r2) = &original {
801 r.null_included &= r2.null_included;
802 } else {
803 unreachable!();
804 }
805 } else {
806 unreachable!();
807 }
808
809 let mut base = original.clone();
810 base.intersect(intersected.clone());
811 assert_eq!(expected, base, "{original:?} + {intersected:?} = {base:?} != {expected:?}");
812
813 let mut base = intersected.clone();
814 base.intersect(original.clone());
815 assert_eq!(expected, base, "{intersected:?} + {original:?} = {base:?} != {expected:?}");
816 }
817 }
818
819 #[test]
820 fn candidate_intersecting_preserves_order_in_overlap() {
821 use CandidateValue::*;
822 let one = FieldValue::Int64(1);
823 let two = FieldValue::Int64(2);
824 let three = FieldValue::Int64(3);
825 let four = FieldValue::Int64(4);
826 let test_cases = [
827 (
830 Multiple(vec![&one, &two, &three, &four]),
831 Multiple(vec![&three, &two]),
832 Multiple(vec![&two, &three]),
833 ),
834 (
835 Multiple(vec![&three, &two]),
836 Multiple(vec![&one, &two, &three, &four]),
837 Multiple(vec![&three, &two]),
838 ),
839 ];
840
841 for (original, intersected, expected) in test_cases {
842 let mut base = original.clone();
843 base.intersect(intersected.clone());
844 assert_eq!(expected, base, "{original:?} + {intersected:?} = {base:?} != {expected:?}");
845 }
846 }
847
848 #[test]
849 fn candidate_excluding_value() {
850 use super::super::Range as R;
851 use CandidateValue::*;
852 let one = FieldValue::Int64(1);
853 let two = FieldValue::Int64(2);
854 let three = FieldValue::Int64(3);
855 let test_data = [
856 (Single(&one), &one, CandidateValue::Impossible),
857 (
858 Multiple(vec![&one, &two, &three]),
860 &one,
861 Multiple(vec![&two, &three]),
862 ),
863 (
864 Multiple(vec![&one, &two, &three]),
866 &two,
867 Multiple(vec![&one, &three]),
868 ),
869 (Multiple(vec![&one, &two]), &two, Single(&one)),
870 (Multiple(vec![&one, &FieldValue::NULL]), &one, Single(&FieldValue::NULL)),
871 (Multiple(vec![&one, &FieldValue::NULL]), &FieldValue::NULL, Single(&one)),
872 (Single(&one), &one, Impossible),
873 (Single(&FieldValue::NULL), &FieldValue::NULL, Impossible),
874 (All, &FieldValue::NULL, Range(R::full_non_null())),
875 (
876 Range(R::with_start(Bound::Included(&two), false)),
877 &two,
878 Range(R::with_start(Bound::Excluded(&two), false)),
879 ),
880 (
881 Range(R::with_end(Bound::Included(&two), true)),
882 &two,
883 Range(R::with_end(Bound::Excluded(&two), true)),
884 ),
885 (
886 Range(R::with_end(Bound::Included(&two), true)),
887 &FieldValue::NULL,
888 Range(R::with_end(Bound::Included(&two), false)),
889 ),
890 ];
891
892 for (candidate, excluded, expected) in test_data {
893 let mut base = candidate.clone();
894 base.exclude_single_value(&excluded);
895 assert_eq!(
896 expected, base,
897 "{candidate:?} - {excluded:?} produced {base:?} instead of {expected:?}"
898 );
899 }
900 }
901
902 #[test]
903 fn candidate_excluding_value_no_ops() {
904 use super::super::Range as R;
905 use CandidateValue::*;
906 let one = FieldValue::Int64(1);
907 let two = FieldValue::Int64(2);
908 let three = FieldValue::Int64(3);
909 let test_data = [
910 (Impossible, &one),
911 (Single(&one), &two),
912 (Multiple(vec![&one, &two]), &three),
913 (Range(R::full_non_null()), &FieldValue::NULL),
914 (Range(R::with_start(Bound::Included(&two), false)), &one),
915 (Range(R::with_start(Bound::Excluded(&two), false)), &two),
916 (Range(R::with_end(Bound::Included(&one), false)), &two),
917 (Range(R::with_end(Bound::Excluded(&one), false)), &one),
918 (Range(R::new(Bound::Included(&one), Bound::Included(&three), false)), &two),
919 ];
920
921 for (candidate, excluded) in test_data {
922 let mut base = candidate.clone();
923 base.exclude_single_value(&excluded);
924 assert_eq!(
925 candidate, base,
926 "{candidate:?} - {excluded:?} should have been a no-op but it produced {base:?}"
927 );
928 }
929 }
930
931 #[test]
932 fn candidate_excluding_value_of_different_integer_kind() {
933 use super::super::Range as R;
934 use CandidateValue::*;
935 let signed_one = FieldValue::Int64(1);
936 let signed_two = FieldValue::Int64(2);
937 let unsigned_one = FieldValue::Uint64(1);
938 let unsigned_two = FieldValue::Uint64(2);
939 let test_data = [
940 (Single(&signed_one), &unsigned_one, Impossible),
941 (Multiple(vec![&signed_one, &signed_two]), &unsigned_one, Single(&signed_two)),
942 (
943 Range(R::with_start(Bound::Included(&signed_one), true)),
944 &unsigned_one,
945 Range(R::with_start(Bound::Excluded(&signed_one), true)),
946 ),
947 (
948 Range(R::with_end(Bound::Included(&signed_one), true)),
949 &unsigned_one,
950 Range(R::with_end(Bound::Excluded(&signed_one), true)),
951 ),
952 (Single(&unsigned_one), &signed_one, Impossible),
953 (Multiple(vec![&unsigned_one, &unsigned_two]), &signed_one, Single(&unsigned_two)),
954 (
955 Range(R::with_start(Bound::Included(&unsigned_one), true)),
956 &signed_one,
957 Range(R::with_start(Bound::Excluded(&unsigned_one), true)),
958 ),
959 (
960 Range(R::with_end(Bound::Included(&unsigned_one), true)),
961 &signed_one,
962 Range(R::with_end(Bound::Excluded(&unsigned_one), true)),
963 ),
964 ];
965
966 for (candidate, excluded, expected) in test_data {
967 let mut base = candidate.clone();
968 base.exclude_single_value(&excluded);
969 assert_eq!(
970 expected, base,
971 "{candidate:?} - {excluded:?} produced {base:?} instead of {expected:?}"
972 );
973 }
974 }
975
976 #[test]
977 fn candidate_direct_normalization() {
978 use super::Range as R;
979 use CandidateValue::*;
980 let one = FieldValue::Int64(1);
981 let two = FieldValue::Int64(2);
982 let test_cases = [
983 (Multiple(vec![]), Impossible),
984 (Multiple(vec![&FieldValue::NULL]), Single(&FieldValue::NULL)),
985 (Multiple(vec![&two]), Single(&two)),
986 (Range(R::full()), All),
987 (
988 Range(R::new(Bound::Included(&one), Bound::Included(&one), true)),
989 Multiple(vec![&FieldValue::NULL, &one]),
990 ),
991 (Range(R::new(Bound::Included(&one), Bound::Included(&one), false)), Single(&one)),
992 (
993 Range(R::new(Bound::Included(&one), Bound::Excluded(&one), true)),
994 Single(&FieldValue::NULL),
995 ),
996 (Range(R::new(Bound::Included(&one), Bound::Excluded(&one), false)), Impossible),
997 (
998 Range(R::new(Bound::Included(&two), Bound::Included(&one), true)),
999 Single(&FieldValue::NULL),
1000 ),
1001 (Range(R::new(Bound::Included(&two), Bound::Included(&one), false)), Impossible),
1002 (
1003 Range(R::new(Bound::Excluded(&two), Bound::Included(&one), true)),
1004 Single(&FieldValue::NULL),
1005 ),
1006 (Range(R::new(Bound::Excluded(&two), Bound::Included(&one), false)), Impossible),
1007 (
1008 Range(R::new(Bound::Included(&two), Bound::Excluded(&one), true)),
1009 Single(&FieldValue::NULL),
1010 ),
1011 (Range(R::new(Bound::Included(&two), Bound::Excluded(&one), false)), Impossible),
1012 (
1013 Range(R::new(Bound::Excluded(&two), Bound::Excluded(&one), true)),
1014 Single(&FieldValue::NULL),
1015 ),
1016 (Range(R::new(Bound::Excluded(&two), Bound::Excluded(&one), false)), Impossible),
1017 ];
1018
1019 for (unnormalized, expected) in test_cases {
1020 let mut base = unnormalized.clone();
1021 base.normalize();
1022
1023 assert_eq!(expected, base, "{unnormalized:?}.normalize() = {base:?} != {expected:?}");
1024 }
1025 }
1026
1027 #[test]
1028 fn candidate_normalization() {
1029 use super::Range as R;
1030 use CandidateValue::*;
1031 let one = FieldValue::Int64(1);
1032 let two = FieldValue::Int64(2);
1033 let three = FieldValue::Int64(3);
1034 let four = FieldValue::Int64(4);
1035 let test_cases = [
1036 (Multiple(vec![&one, &two, &three]), Single(&four), Impossible),
1039 (Multiple(vec![&one, &two]), Multiple(vec![&three, &four]), Impossible),
1040 (
1041 Multiple(vec![&one, &two]),
1042 Range(R::with_start(Bound::Included(&three), true)),
1043 Impossible,
1044 ),
1045 (
1046 Multiple(vec![&one, &two]),
1047 Range(R::with_start(Bound::Excluded(&two), true)),
1048 Impossible,
1049 ),
1050 (
1051 Multiple(vec![&one, &two, &FieldValue::NULL]),
1052 Range(R::with_start(Bound::Excluded(&two), false)),
1053 Impossible,
1054 ),
1055 (Multiple(vec![&one, &two, &three]), Single(&two), Single(&two)),
1058 (Multiple(vec![&one, &two, &three]), Multiple(vec![&two, &four]), Single(&two)),
1059 (
1060 Multiple(vec![&two, &three, &FieldValue::NULL]),
1061 Range(R::with_end(Bound::Included(&two), false)),
1062 Single(&two),
1063 ),
1064 (
1065 Multiple(vec![&two, &three, &FieldValue::NULL]),
1066 Range(R::with_end(Bound::Excluded(&two), true)),
1067 Single(&FieldValue::NULL),
1068 ),
1069 ];
1070
1071 for (original, intersected, expected) in test_cases {
1072 let mut base = original.clone();
1073 base.intersect(intersected.clone());
1074 assert_eq!(expected, base, "{original:?} + {intersected:?} = {base:?} != {expected:?}");
1075
1076 let mut base = intersected.clone();
1077 base.intersect(original.clone());
1078 assert_eq!(expected, base, "{intersected:?} + {original:?} = {base:?} != {expected:?}");
1079 }
1080 }
1081
1082 mod future_work {
1086 use std::ops::Bound;
1087
1088 use crate::{interpreter::hints::CandidateValue, ir::FieldValue};
1089
1090 fn range_normalization_does_not_prefer_inclusive_bounds_for_integers() {
1091 use super::super::Range as R;
1092 use CandidateValue::*;
1093 let signed_one = FieldValue::Int64(1);
1094 let signed_three = FieldValue::Int64(3);
1095 let unsigned_one = FieldValue::Uint64(1);
1096 let unsigned_three = FieldValue::Uint64(3);
1097 let test_data = [
1098 Range(R::new(Bound::Excluded(&signed_one), Bound::Excluded(&signed_three), false)),
1099 Range(R::new(
1100 Bound::Excluded(&unsigned_one),
1101 Bound::Excluded(&unsigned_three),
1102 false,
1103 )),
1104 Range(R::with_start(Bound::Excluded(&signed_one), false)),
1105 Range(R::with_start(Bound::Excluded(&unsigned_one), false)),
1106 Range(R::with_end(Bound::Excluded(&signed_three), false)),
1107 Range(R::with_end(Bound::Excluded(&unsigned_three), false)),
1108 ];
1109
1110 for candidate in test_data {
1111 let mut base = candidate.clone();
1112 base.normalize();
1113 assert_eq!(
1114 candidate, base,
1115 "normalization changed this value: {candidate:?} != {base:?}"
1116 );
1117 }
1118 }
1119
1120 fn candidate_value_exclusion_does_not_special_case_integers() {
1121 use super::super::Range as R;
1122 use CandidateValue::*;
1123 let signed_one = FieldValue::Int64(1);
1124 let signed_two = FieldValue::Int64(2);
1125 let signed_three = FieldValue::Int64(3);
1126 let unsigned_one = FieldValue::Uint64(1);
1127 let unsigned_two = FieldValue::Uint64(2);
1128 let unsigned_three = FieldValue::Uint64(3);
1129 let test_data = [
1130 (Range(R::full_non_null()), &FieldValue::Int64(i64::MIN)),
1131 (Range(R::full_non_null()), &FieldValue::Int64(i64::MAX)),
1132 (Range(R::full_non_null()), &FieldValue::Uint64(u64::MIN)),
1133 (Range(R::full_non_null()), &FieldValue::Uint64(u64::MAX)),
1134 (Range(R::with_start(Bound::Excluded(&signed_one), false)), &signed_two),
1135 (Range(R::with_start(Bound::Excluded(&unsigned_one), false)), &unsigned_two),
1136 (Range(R::with_end(Bound::Excluded(&signed_two), false)), &signed_one),
1137 (Range(R::with_end(Bound::Excluded(&unsigned_two), false)), &unsigned_one),
1138 (
1139 Range(R::new(
1140 Bound::Included(&unsigned_one),
1141 Bound::Included(&unsigned_three),
1142 false,
1143 )),
1144 &unsigned_two,
1145 ),
1146 (
1147 Range(R::new(
1148 Bound::Included(&signed_one),
1149 Bound::Included(&signed_three),
1150 false,
1151 )),
1152 &signed_two,
1153 ),
1154 ];
1155
1156 for (candidate, excluded) in test_data {
1157 let mut base = candidate.clone();
1158 base.exclude_single_value(&excluded);
1159 assert_eq!(
1160 candidate, base,
1161 "exclusion changed this value: {candidate:?} - {excluded:?} produced {base:?}"
1162 );
1163 }
1164 }
1165 }
1166}