1use std::cmp::Ordering;
72
73use rudb_common::{Error, LogicalType, Result, Value, interval_micros};
74use rudb_vector::{Data, Form, Selection, StringColumn, Validity, Vector};
75
76use crate::fallback::{self, Kernel};
77use crate::logic::is_true;
78use crate::number::{approximate, integral};
79use crate::shape::{first, identity, nulls_of, single};
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83pub enum Comparison {
84 Equal,
86 NotEqual,
88 Less,
90 LessOrEqual,
92 Greater,
94 GreaterOrEqual,
96 DistinctFrom,
98 NotDistinctFrom,
100}
101
102impl Comparison {
103 #[must_use]
105 pub fn is_total(self) -> bool {
106 matches!(self, Self::DistinctFrom | Self::NotDistinctFrom)
107 }
108
109 #[must_use]
116 pub fn swapped(self) -> Self {
117 match self {
118 Self::Less => Self::Greater,
119 Self::LessOrEqual => Self::GreaterOrEqual,
120 Self::Greater => Self::Less,
121 Self::GreaterOrEqual => Self::LessOrEqual,
122 same => same,
123 }
124 }
125}
126
127pub fn compare(op: Comparison, left: &Vector, right: &Vector) -> Result<Vector> {
133 if left.len() != right.len() {
134 return Err(Error::internal(format!(
135 "a comparison of a {} row vector with a {} row one",
136 left.len(),
137 right.len()
138 )));
139 }
140 let len = left.len();
141 if left.form() == Form::Constant && right.form() == Form::Constant && len > 0 {
142 let single = compare_values(op, &left.value_at(0), &right.value_at(0))?;
143 return Ok(Vector::constant(LogicalType::Boolean, single, len));
144 }
145
146 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
147 if !op.is_total()
151 && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
152 && len > 0
153 {
154 return boolean(vec![false; len], Validity::AllInvalid, len);
155 }
156
157 if let Some(answers) = specialized(op, left, right, &left_valid, &right_valid, len, identity) {
158 let validity =
159 if op.is_total() { Validity::AllValid } else { left_valid.and(&right_valid, len) };
160 return boolean(blank_the_nulls(answers, &validity), validity, len);
161 }
162
163 fallback::record(Kernel::Compare, left.form(), right.form());
164 let mut values = Vec::with_capacity(len);
165 for index in 0..len {
168 values.push(compare_values(op, &left.value_at(index), &right.value_at(index))?);
169 }
170 Vector::from_values(LogicalType::Boolean, &values)
171}
172
173pub fn refine(
191 op: Comparison,
192 left: &Vector,
193 right: &Vector,
194 kept: &Selection,
195) -> Result<Selection> {
196 if left.len() != right.len() {
197 return Err(Error::internal(format!(
198 "a comparison of a {} row vector with a {} row one",
199 left.len(),
200 right.len()
201 )));
202 }
203 let len = left.len();
204 if kept.indices().iter().any(|&row| row as usize >= len) {
208 return Err(Error::internal(format!("a selection past the end of a {len} row vector")));
209 }
210 if kept.is_empty() {
211 return Ok(Selection::empty());
212 }
213 if left.form() == Form::Constant && right.form() == Form::Constant {
214 let single = compare_values(op, &left.value_at(0), &right.value_at(0))?;
215 return Ok(if is_true(&single) { kept.clone() } else { Selection::empty() });
216 }
217
218 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
219 if !op.is_total() && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
220 {
221 return Ok(Selection::empty());
222 }
223
224 let rows = kept.indices();
225 let map = |slot: usize| rows[slot] as usize;
226 if let Some(answers) = specialized(op, left, right, &left_valid, &right_valid, kept.len(), map)
227 {
228 if op.is_total() || (left_valid == Validity::AllValid && right_valid == Validity::AllValid)
231 {
232 return Ok(narrowed(&answers, rows, |_| true));
233 }
234 return Ok(narrowed(&answers, rows, |slot| {
238 let row = rows[slot] as usize;
239 left_valid.is_valid(row) && right_valid.is_valid(row)
240 }));
241 }
242
243 fallback::record(Kernel::Compare, left.form(), right.form());
244 let mut out = Vec::with_capacity(kept.len());
245 for &row in rows {
248 let index = row as usize;
249 if is_true(&compare_values(op, &left.value_at(index), &right.value_at(index))?) {
250 out.push(row);
251 }
252 }
253 Ok(Selection::from_indices(out))
254}
255
256fn narrowed<L: Fn(usize) -> bool>(answers: &[bool], rows: &[u32], live: L) -> Selection {
263 let mut out = vec![0_u32; answers.len()];
264 let mut count = 0;
265 for (slot, &answer) in answers.iter().enumerate() {
266 out[count] = rows[slot];
267 count += usize::from(answer & live(slot));
269 }
270 out.truncate(count);
271 Selection::from_indices(out)
272}
273
274fn boolean(answers: Vec<bool>, validity: Validity, len: usize) -> Result<Vector> {
276 let validity = if len == 0 { Validity::AllValid } else { validity.normalize(len) };
280 Ok(Vector::flat(LogicalType::Boolean, Data::Bool(answers.into()))?.with_validity(validity))
281}
282
283fn blank_the_nulls(mut answers: Vec<bool>, validity: &Validity) -> Vec<bool> {
291 if let Validity::Mask(mask) = validity {
292 for (index, answer) in answers.iter_mut().enumerate() {
293 if !mask.get(index) {
294 *answer = false;
295 }
296 }
297 }
298 answers
299}
300
301fn specialized<M>(
313 op: Comparison,
314 left: &Vector,
315 right: &Vector,
316 left_valid: &Validity,
317 right_valid: &Validity,
318 len: usize,
319 map: M,
320) -> Option<Vec<bool>>
321where
322 M: Fn(usize) -> usize + Copy,
323{
324 if left.logical_type() != right.logical_type() {
328 return None;
329 }
330
331 if let (Some(one), Some(other)) = (left.data(), right.data()) {
332 return dispatch(op, len, one, map, other, map, left_valid, right_valid, map);
333 }
334 if let (Some(one), Some(value)) = (left.data(), right.constant_value()) {
335 let held = single(left.logical_type(), value)?;
336 let other = held.data()?;
337 return dispatch(op, len, one, map, other, first, left_valid, right_valid, map);
338 }
339 if let (Some(value), Some(other)) = (left.constant_value(), right.data()) {
340 let held = single(right.logical_type(), value)?;
342 let one = held.data()?;
343 return dispatch(op.swapped(), len, other, map, one, first, right_valid, left_valid, map);
344 }
345 if let (Some((codes, values)), Some(value)) = (left.dictionary_parts(), right.constant_value())
346 {
347 let one = values.data()?;
348 let held = single(left.logical_type(), value)?;
349 let other = held.data()?;
350 let at = |index: usize| codes[map(index)] as usize;
351 return dispatch(op, len, one, at, other, first, left_valid, right_valid, map);
352 }
353 if let (Some(value), Some((codes, values))) = (left.constant_value(), right.dictionary_parts())
354 {
355 let other = values.data()?;
356 let held = single(right.logical_type(), value)?;
357 let one = held.data()?;
358 let at = |index: usize| codes[map(index)] as usize;
359 return dispatch(op.swapped(), len, other, at, one, first, right_valid, left_valid, map);
360 }
361 if let (Some((codes, values)), Some(other)) = (left.dictionary_parts(), right.data()) {
367 let one = values.data()?;
368 let at = |index: usize| codes[map(index)] as usize;
369 return dispatch(op, len, one, at, other, map, left_valid, right_valid, map);
370 }
371 if let (Some(one), Some((codes, values))) = (left.data(), right.dictionary_parts()) {
372 let other = values.data()?;
373 let at = |index: usize| codes[map(index)] as usize;
374 return dispatch(op.swapped(), len, other, at, one, map, right_valid, left_valid, map);
375 }
376 None
377}
378
379#[expect(
385 clippy::too_many_arguments,
386 reason = "two sides with an index each, the operator, the length and two validities, all of \
387 which the loop needs and none of which is worth a struct that exists for one call"
388)]
389fn dispatch<L, R, V>(
390 op: Comparison,
391 len: usize,
392 left: &Data,
393 at_left: L,
394 right: &Data,
395 at_right: R,
396 left_valid: &Validity,
397 right_valid: &Validity,
398 at_valid: V,
399) -> Option<Vec<bool>>
400where
401 L: Fn(usize) -> usize,
402 R: Fn(usize) -> usize,
403 V: Fn(usize) -> usize,
404{
405 macro_rules! layouts {
406 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
407 match (left, right) {
408 $(
409 (Data::$variant(one), Data::$variant(other)) => Some(sweep(
410 op,
411 len,
412 |index| one[at_left(index)].cmp(&other[at_right(index)]),
413 left_valid,
414 right_valid,
415 &at_valid,
416 )),
417 )+
418 (Data::Float32(one), Data::Float32(other)) => Some(sweep(
421 op,
422 len,
423 |index| {
424 float_order(
425 f64::from(one[at_left(index)]),
426 f64::from(other[at_right(index)]),
427 )
428 },
429 left_valid,
430 right_valid,
431 &at_valid,
432 )),
433 (Data::Float64(one), Data::Float64(other)) => Some(sweep(
434 op,
435 len,
436 |index| float_order(one[at_left(index)], other[at_right(index)]),
437 left_valid,
438 right_valid,
439 &at_valid,
440 )),
441 (Data::Interval(one), Data::Interval(other)) => Some(sweep(
444 op,
445 len,
446 |index| {
447 let (months, days, micros) = one[at_left(index)];
448 let (bm, bd, bu) = other[at_right(index)];
449 interval_micros(months, days, micros).cmp(&interval_micros(bm, bd, bu))
450 },
451 left_valid,
452 right_valid,
453 &at_valid,
454 )),
455 (Data::Varlen(one), Data::Varlen(other)) => Some(sweep(
456 op,
457 len,
458 |index| string_order(one, at_left(index), other, at_right(index)),
459 left_valid,
460 right_valid,
461 &at_valid,
462 )),
463 _ => None,
464 }
465 };
466 }
467 rudb_vector::for_each_layout!(ordered, layouts)
468}
469
470fn string_order(
478 left: &StringColumn,
479 at_left: usize,
480 right: &StringColumn,
481 at_right: usize,
482) -> Ordering {
483 let (Some(one), Some(other)) = (left.views().get(at_left), right.views().get(at_right)) else {
484 return Ordering::Equal;
485 };
486 let (prefix, against) = (one.prefix(), other.prefix());
487 if prefix != against {
488 return prefix.cmp(&against);
489 }
490 let bytes = left.bytes(at_left).unwrap_or_default();
495 let against_bytes = right.bytes(at_right).unwrap_or_default();
496 bytes.cmp(against_bytes)
497}
498
499fn sweep<O, V>(
505 op: Comparison,
506 len: usize,
507 order_at: O,
508 left_valid: &Validity,
509 right_valid: &Validity,
510 at_valid: V,
511) -> Vec<bool>
512where
513 O: Fn(usize) -> Ordering,
514 V: Fn(usize) -> usize,
515{
516 let mut answers = vec![false; len];
517 match op {
518 Comparison::Equal => fill(&mut answers, order_at, |o| o == Ordering::Equal),
519 Comparison::NotEqual => fill(&mut answers, order_at, |o| o != Ordering::Equal),
520 Comparison::Less => fill(&mut answers, order_at, |o| o == Ordering::Less),
521 Comparison::LessOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Greater),
522 Comparison::Greater => fill(&mut answers, order_at, |o| o == Ordering::Greater),
523 Comparison::GreaterOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Less),
524 Comparison::DistinctFrom => {
525 total(&mut answers, order_at, left_valid, right_valid, at_valid);
526 for answer in &mut answers {
527 *answer = !*answer;
528 }
529 }
530 Comparison::NotDistinctFrom => {
531 total(&mut answers, order_at, left_valid, right_valid, at_valid);
532 }
533 }
534 answers
535}
536
537#[inline]
539fn fill<O, H>(answers: &mut [bool], order_at: O, held: H)
540where
541 O: Fn(usize) -> Ordering,
542 H: Fn(Ordering) -> bool,
543{
544 for (index, answer) in answers.iter_mut().enumerate() {
545 *answer = held(order_at(index));
546 }
547}
548
549fn total<O, V>(
556 answers: &mut [bool],
557 order_at: O,
558 left_valid: &Validity,
559 right_valid: &Validity,
560 at_valid: V,
561) where
562 O: Fn(usize) -> Ordering,
563 V: Fn(usize) -> usize,
564{
565 if *left_valid == Validity::AllValid && *right_valid == Validity::AllValid {
566 fill(answers, order_at, |o| o == Ordering::Equal);
567 return;
568 }
569 for (index, answer) in answers.iter_mut().enumerate() {
570 let row = at_valid(index);
571 *answer = match (left_valid.is_valid(row), right_valid.is_valid(row)) {
572 (true, true) => order_at(index) == Ordering::Equal,
573 (false, false) => true,
574 _ => false,
575 };
576 }
577}
578
579pub fn compare_values(op: Comparison, left: &Value, right: &Value) -> Result<Value> {
585 if op.is_total() {
586 let same = match (left.is_null(), right.is_null()) {
587 (true, true) => true,
588 (true, false) | (false, true) => false,
589 (false, false) => order(left, right)? == Ordering::Equal,
590 };
591 return Ok(Value::Boolean(match op {
592 Comparison::NotDistinctFrom => same,
593 _ => !same,
594 }));
595 }
596 if left.is_null() || right.is_null() {
597 return Ok(Value::Null);
598 }
599 let ordering = order(left, right)?;
600 let held = match op {
601 Comparison::Equal => ordering == Ordering::Equal,
602 Comparison::NotEqual => ordering != Ordering::Equal,
603 Comparison::Less => ordering == Ordering::Less,
604 Comparison::LessOrEqual => ordering != Ordering::Greater,
605 Comparison::Greater => ordering == Ordering::Greater,
606 Comparison::GreaterOrEqual => ordering != Ordering::Less,
607 Comparison::DistinctFrom | Comparison::NotDistinctFrom => {
608 return Err(Error::internal("a total comparison reached the ordered path"));
609 }
610 };
611 Ok(Value::Boolean(held))
612}
613
614pub fn order(left: &Value, right: &Value) -> Result<Ordering> {
625 match (left, right) {
626 (Value::Null, _) | (_, Value::Null) => {
627 Err(Error::internal("a null reached the ordering path"))
628 }
629 (Value::Boolean(a), Value::Boolean(b)) => Ok(a.cmp(b)),
630 (Value::Varchar(a), Value::Varchar(b)) => Ok(a.as_bytes().cmp(b.as_bytes())),
631 (Value::Blob(a), Value::Blob(b)) => Ok(a.cmp(b)),
632 (Value::Date(a), Value::Date(b)) => Ok(a.cmp(b)),
633 (Value::Time(a), Value::Time(b)) | (Value::Timestamp(a), Value::Timestamp(b)) => {
634 Ok(a.cmp(b))
635 }
636 (
637 Value::Interval { months: am, days: ad, micros: au },
638 Value::Interval { months: bm, days: bd, micros: bu },
639 ) => Ok(interval_micros(*am, *ad, *au).cmp(&interval_micros(*bm, *bd, *bu))),
640 _ => numeric_order(left, right),
641 }
642}
643
644fn numeric_order(left: &Value, right: &Value) -> Result<Ordering> {
646 if let (Some(a), Some(b)) = (integral(left), integral(right)) {
647 return Ok(a.cmp(&b));
648 }
649 if let (
650 Value::Decimal { unscaled: a, scale: sa, .. },
651 Value::Decimal { unscaled: b, scale: sb, .. },
652 ) = (left, right)
653 {
654 if sa == sb {
655 return Ok(a.cmp(b));
656 }
657 }
658 match (approximate(left), approximate(right)) {
659 (Some(a), Some(b)) => Ok(float_order(a, b)),
660 _ => Err(Error::not_implemented(format!(
661 "comparing {} with {}",
662 left.logical_type(),
663 right.logical_type()
664 ))),
665 }
666}
667
668fn float_order(left: f64, right: f64) -> Ordering {
670 if left == right {
671 return Ordering::Equal;
672 }
673 match (left.is_nan(), right.is_nan()) {
674 (true, true) => Ordering::Equal,
675 (true, false) => Ordering::Greater,
676 (false, true) => Ordering::Less,
677 (false, false) => left.partial_cmp(&right).unwrap_or(Ordering::Equal),
678 }
679}
680
681pub fn order_with_nulls(left: &Value, right: &Value, nulls_first: bool) -> Result<Ordering> {
690 match (left.is_null(), right.is_null()) {
691 (true, true) => Ok(Ordering::Equal),
692 (true, false) => Ok(if nulls_first { Ordering::Less } else { Ordering::Greater }),
693 (false, true) => Ok(if nulls_first { Ordering::Greater } else { Ordering::Less }),
694 (false, false) => order(left, right),
695 }
696}
697
698#[cfg(test)]
699mod tests {
700 use super::*;
701
702 fn compared(op: Comparison, left: Value, right: Value) -> Value {
703 compare_values(op, &left, &right).expect("these types compare")
704 }
705
706 const EVERY: [Comparison; 8] = [
708 Comparison::Equal,
709 Comparison::NotEqual,
710 Comparison::Less,
711 Comparison::LessOrEqual,
712 Comparison::Greater,
713 Comparison::GreaterOrEqual,
714 Comparison::DistinctFrom,
715 Comparison::NotDistinctFrom,
716 ];
717
718 fn oracle(op: Comparison, left: &Vector, right: &Vector) -> Vector {
724 let values: Vec<Value> = (0..left.len())
725 .map(|index| {
726 compare_values(op, &left.value_at(index), &right.value_at(index))
727 .expect("the oracle is only asked about types that compare")
728 })
729 .collect();
730 Vector::from_values(LogicalType::Boolean, &values).expect("booleans")
731 }
732
733 fn agrees(op: Comparison, left: &Vector, right: &Vector) {
737 let fast = compare(op, left, right).expect("compares");
738 let slow = oracle(op, left, right);
739 assert_eq!(fast, slow, "{op:?} on a {:?} against a {:?}", left.form(), right.form());
740 }
741
742 struct Rng(u64);
745
746 impl Rng {
747 fn next(&mut self) -> u64 {
748 self.0 ^= self.0 << 13;
749 self.0 ^= self.0 >> 7;
750 self.0 ^= self.0 << 17;
751 self.0
752 }
753
754 fn below(&mut self, bound: u64) -> u64 {
755 self.next() % bound
756 }
757 }
758
759 #[test]
760 fn an_ordinary_comparison_is_null_when_either_side_is() {
761 assert_eq!(compared(Comparison::Equal, Value::Integer(1), Value::Null), Value::Null);
762 assert_eq!(compared(Comparison::Less, Value::Null, Value::Integer(1)), Value::Null);
763 }
764
765 #[test]
766 fn a_total_comparison_is_never_null() {
767 assert_eq!(
768 compared(Comparison::NotDistinctFrom, Value::Null, Value::Null),
769 Value::Boolean(true)
770 );
771 assert_eq!(
772 compared(Comparison::NotDistinctFrom, Value::Integer(1), Value::Null),
773 Value::Boolean(false)
774 );
775 assert_eq!(
776 compared(Comparison::DistinctFrom, Value::Integer(1), Value::Null),
777 Value::Boolean(true)
778 );
779 }
780
781 #[test]
782 fn a_string_compares_by_bytes() {
783 assert_eq!(
784 compared(Comparison::Less, Value::Varchar("a".into()), Value::Varchar("b".into())),
785 Value::Boolean(true)
786 );
787 assert_eq!(
788 compared(Comparison::Less, Value::Varchar("Z".into()), Value::Varchar("a".into())),
789 Value::Boolean(true)
790 );
791 }
792
793 #[test]
796 fn two_nans_are_one_value_and_they_sort_above_the_numbers() {
797 assert_eq!(
798 compared(Comparison::Equal, Value::Double(f64::NAN), Value::Double(f64::NAN)),
799 Value::Boolean(true)
800 );
801 assert_eq!(
802 compared(Comparison::Greater, Value::Double(f64::NAN), Value::Double(1e300)),
803 Value::Boolean(true)
804 );
805 }
806
807 #[test]
808 fn zero_has_one_value_however_it_is_signed() {
809 assert_eq!(
810 compared(Comparison::Equal, Value::Double(0.0), Value::Double(-0.0)),
811 Value::Boolean(true)
812 );
813 }
814
815 #[test]
820 fn two_intervals_of_the_same_length_are_one_value() {
821 let day = Value::Interval { months: 0, days: 1, micros: 0 };
822 let hours = Value::Interval { months: 0, days: 0, micros: 86_400_000_000 };
823 let month = Value::Interval { months: 1, days: 0, micros: 0 };
824 let thirty = Value::Interval { months: 0, days: 30, micros: 0 };
825 let long_day = Value::Interval { months: 0, days: 0, micros: 90_000_000_000 };
826 assert_eq!(compared(Comparison::Equal, day.clone(), hours), Value::Boolean(true));
827 assert_eq!(compared(Comparison::Equal, month, thirty), Value::Boolean(true));
828 assert_eq!(compared(Comparison::Greater, long_day, day), Value::Boolean(true));
829 }
830
831 #[test]
832 fn a_number_compares_the_same_however_it_is_stored() {
833 assert_eq!(
834 compared(Comparison::Equal, Value::Integer(3), Value::BigInt(3)),
835 Value::Boolean(true)
836 );
837 assert_eq!(
838 compared(Comparison::Less, Value::Integer(3), Value::Double(3.5)),
839 Value::Boolean(true)
840 );
841 }
842
843 #[test]
844 fn nulls_go_where_the_query_asked_for_them() {
845 assert_eq!(
846 order_with_nulls(&Value::Null, &Value::Integer(1), true).expect("orders"),
847 Ordering::Less
848 );
849 assert_eq!(
850 order_with_nulls(&Value::Null, &Value::Integer(1), false).expect("orders"),
851 Ordering::Greater
852 );
853 }
854
855 #[test]
856 fn two_constant_vectors_cost_one_comparison() {
857 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 512);
858 let right = Vector::constant(LogicalType::Integer, Value::Integer(2), 512);
859 let result = compare(Comparison::Less, &left, &right).expect("compares");
860 assert_eq!(result.form(), Form::Constant);
861 assert_eq!(result.value_at(500), Value::Boolean(true));
862 }
863
864 #[test]
865 fn a_comparison_of_two_vectors_is_one_answer_per_row() {
866 let left = Vector::from_values(
867 LogicalType::Integer,
868 &[Value::Integer(1), Value::Integer(5), Value::Null],
869 )
870 .expect("three rows");
871 let right = Vector::constant(LogicalType::Integer, Value::Integer(3), 3);
872 let result = compare(Comparison::Greater, &left, &right).expect("compares");
873 assert_eq!(result.value_at(0), Value::Boolean(false));
874 assert_eq!(result.value_at(1), Value::Boolean(true));
875 assert_eq!(result.value_at(2), Value::Null);
876 }
877
878 #[test]
879 fn two_vectors_of_different_lengths_are_caught() {
880 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
881 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 5);
882 let error = compare(Comparison::Equal, &left, &right).expect_err("ragged");
883 assert!(error.message().contains("4 row vector"), "{error}");
884 }
885
886 #[test]
887 fn turning_a_comparison_around_is_what_the_other_side_would_have_said() {
888 for op in EVERY {
889 let left = Value::Integer(3);
890 let right = Value::Integer(7);
891 assert_eq!(
892 compare_values(op, &left, &right).expect("compares"),
893 compare_values(op.swapped(), &right, &left).expect("compares"),
894 "{op:?}"
895 );
896 }
897 }
898
899 #[test]
902 fn every_specialized_path_agrees_with_the_row_at_a_time_path() {
903 let mut rng = Rng(0x5eed_1234_9876_4321);
904 let types: [LogicalType; 11] = [
905 LogicalType::Boolean,
906 LogicalType::TinyInt,
907 LogicalType::SmallInt,
908 LogicalType::Integer,
909 LogicalType::BigInt,
910 LogicalType::HugeInt,
911 LogicalType::UInteger,
912 LogicalType::Float,
913 LogicalType::Double,
914 LogicalType::Varchar,
915 LogicalType::Interval,
916 ];
917 for ty in &types {
918 for nulls in [0u64, 1, 3] {
919 let len = 37;
920 let make = |rng: &mut Rng| {
921 let values: Vec<Value> = (0..len)
922 .map(|_| {
923 if nulls > 0 && rng.below(nulls + 1) == 0 {
924 Value::Null
925 } else {
926 sample(ty, rng)
927 }
928 })
929 .collect();
930 Vector::from_values(ty.clone(), &values).expect("a flat vector")
931 };
932 let left = make(&mut rng);
933 let right = make(&mut rng);
934 let literal = sample(ty, &mut rng);
935 let constant = Vector::constant(ty.clone(), literal, len);
936 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
937 let codes: Vec<u32> =
938 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
939 let dictionary =
940 Vector::dictionary(codes, left.clone()).expect("codes are in range");
941
942 for op in EVERY {
943 agrees(op, &left, &right);
944 agrees(op, &left, &constant);
945 agrees(op, &constant, &left);
946 agrees(op, &left, &null_constant);
947 agrees(op, &null_constant, &left);
948 agrees(op, &dictionary, &constant);
949 agrees(op, &constant, &dictionary);
950 agrees(op, &dictionary, &right);
954 agrees(op, &right, &dictionary);
955 }
956 }
957 }
958 }
959
960 fn refined(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) -> Selection {
962 let mut out = Vec::new();
963 for &row in kept.indices() {
964 let index = row as usize;
965 let answer = compare_values(op, &left.value_at(index), &right.value_at(index))
966 .expect("the oracle is only asked about types that compare");
967 if is_true(&answer) {
968 out.push(row);
969 }
970 }
971 Selection::from_indices(out)
972 }
973
974 fn threads(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) {
975 let fast = refine(op, left, right, kept).expect("compares");
976 assert_eq!(
977 fast,
978 refined(op, left, right, kept),
979 "{op:?} on a {:?} against a {:?} over {} rows",
980 left.form(),
981 right.form(),
982 kept.len()
983 );
984 }
985
986 #[test]
990 fn a_threaded_comparison_keeps_what_the_row_at_a_time_path_keeps() {
991 let mut rng = Rng(0x5eed_4321_1234_9876);
992 let types = [LogicalType::Integer, LogicalType::Double, LogicalType::Varchar];
993 for ty in &types {
994 for nulls in [0u64, 1, 3] {
995 let len = 37;
996 let make = |rng: &mut Rng| {
997 let values: Vec<Value> = (0..len)
998 .map(|_| {
999 if nulls > 0 && rng.below(nulls + 1) == 0 {
1000 Value::Null
1001 } else {
1002 sample(ty, rng)
1003 }
1004 })
1005 .collect();
1006 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1007 };
1008 let left = make(&mut rng);
1009 let right = make(&mut rng);
1010 let constant = Vector::constant(ty.clone(), sample(ty, &mut rng), len);
1011 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1012 let codes: Vec<u32> =
1013 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1014 let dictionary =
1015 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1016
1017 let selections = [
1021 Selection::identity(len),
1022 Selection::from_indices((0..len as u32).filter(|row| row % 3 == 0).collect()),
1023 Selection::from_indices(vec![2, 5, 6, 17, 36]),
1024 Selection::empty(),
1025 ];
1026 for op in EVERY {
1027 for kept in &selections {
1028 threads(op, &left, &right, kept);
1029 threads(op, &left, &constant, kept);
1030 threads(op, &constant, &left, kept);
1031 threads(op, &left, &null_constant, kept);
1032 threads(op, &null_constant, &left, kept);
1033 threads(op, &constant, &null_constant, kept);
1034 threads(op, &dictionary, &constant, kept);
1035 threads(op, &constant, &dictionary, kept);
1036 threads(op, &dictionary, &right, kept);
1037 threads(op, &right, &dictionary, kept);
1038 }
1039 }
1040 }
1041 }
1042 }
1043
1044 #[test]
1048 fn a_second_conjunct_reads_only_what_the_first_one_left() {
1049 let numbers: Vec<Value> = (0..64).map(|row| Value::Integer(row % 10)).collect();
1050 let column = Vector::from_values(LogicalType::Integer, &numbers).expect("a flat vector");
1051 let three = Vector::constant(LogicalType::Integer, Value::Integer(3), 64);
1052 let seven = Vector::constant(LogicalType::Integer, Value::Integer(7), 64);
1053
1054 let first = refine(Comparison::Greater, &column, &three, &Selection::identity(64))
1055 .expect("compares");
1056 let both = refine(Comparison::Less, &column, &seven, &first).expect("compares");
1057
1058 let expected: Vec<u32> = (0..64)
1059 .filter(|row| {
1060 let value = row % 10;
1061 value > 3 && value < 7
1062 })
1063 .collect();
1064 assert_eq!(both.indices(), expected.as_slice());
1065 assert!(both.len() < first.len(), "the second conjunct narrowed the selection");
1066 }
1067
1068 #[test]
1072 fn a_null_row_is_not_kept_by_an_ordinary_comparison_and_is_by_a_total_one() {
1073 let column = Vector::from_values(
1074 LogicalType::Integer,
1075 &[Value::Integer(1), Value::Null, Value::Integer(3), Value::Null],
1076 )
1077 .expect("four rows");
1078 let cut = Vector::constant(LogicalType::Integer, Value::Integer(2), 4);
1079 let all = Selection::identity(4);
1080 assert_eq!(
1081 refine(Comparison::Less, &column, &cut, &all).expect("compares").indices(),
1082 &[0]
1083 );
1084 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 4);
1086 assert_eq!(
1087 refine(Comparison::NotDistinctFrom, &column, &nulls, &all).expect("compares").indices(),
1088 &[1, 3]
1089 );
1090 }
1091
1092 #[test]
1093 fn a_selection_past_the_end_is_caught() {
1094 let column = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1095 let past = Selection::from_indices(vec![0, 4]);
1096 let error = refine(Comparison::Equal, &column, &column, &past).expect_err("out of range");
1097 assert!(error.message().contains("4 row vector"), "{error}");
1098 }
1099
1100 fn sample(ty: &LogicalType, rng: &mut Rng) -> Value {
1102 match ty {
1103 LogicalType::Boolean => Value::Boolean(rng.below(2) == 1),
1104 LogicalType::TinyInt => Value::TinyInt(rng.below(7) as i8 - 3),
1105 LogicalType::SmallInt => Value::SmallInt(rng.below(11) as i16 - 5),
1106 LogicalType::Integer => Value::Integer(rng.below(9) as i32 - 4),
1107 LogicalType::BigInt => Value::BigInt(rng.below(9) as i64 - 4),
1108 LogicalType::HugeInt => Value::HugeInt(i128::from(rng.below(9)) - 4),
1109 LogicalType::UInteger => Value::UInteger(rng.below(9) as u32),
1110 LogicalType::Float => Value::Float(match rng.below(5) {
1113 0 => f32::NAN,
1114 1 => -0.0,
1115 other => other as f32 - 2.0,
1116 }),
1117 LogicalType::Double => Value::Double(match rng.below(5) {
1118 0 => f64::NAN,
1119 1 => -0.0,
1120 other => other as f64 - 2.0,
1121 }),
1122 LogicalType::Interval => match rng.below(6) {
1126 0 => Value::Interval { months: 0, days: 1, micros: 0 },
1127 1 => Value::Interval { months: 0, days: 0, micros: 86_400_000_000 },
1128 2 => Value::Interval { months: 1, days: -29, micros: 86_400_000_000 },
1129 3 => Value::Interval { months: 1, days: 0, micros: 0 },
1130 4 => Value::Interval { months: 0, days: 0, micros: 90_000_000_000 },
1131 _ => Value::Interval { months: -1, days: 0, micros: 0 },
1132 },
1133 LogicalType::Varchar => Value::Varchar(
1136 match rng.below(6) {
1137 0 => "",
1138 1 => "ab",
1139 2 => "abc",
1140 3 => "abcdefghijkl",
1141 4 => "abcdefghijklm",
1142 _ => "abcdefghijklmnopqrstuvwxyz",
1143 }
1144 .to_owned(),
1145 ),
1146 other => panic!("the generator has no values for {other}"),
1147 }
1148 }
1149
1150 #[test]
1154 fn prefix_order_is_byte_order_whenever_the_prefixes_differ() {
1155 let words =
1156 ["", "a", "ab", "abc", "abcd", "abcde", "b", "abcdefghijklmnop", "abcdefghijklmnoq"];
1157 let mut column = StringColumn::new();
1158 for word in words {
1159 column.push(word);
1160 }
1161 for (i, one) in words.iter().enumerate() {
1162 for (j, other) in words.iter().enumerate() {
1163 assert_eq!(
1164 string_order(&column, i, &column, j),
1165 one.as_bytes().cmp(other.as_bytes()),
1166 "{one:?} against {other:?}"
1167 );
1168 }
1169 }
1170 }
1171
1172 #[test]
1175 fn a_dictionary_against_a_constant_reads_its_nulls_from_the_values() {
1176 let values = Vector::from_values(
1177 LogicalType::Integer,
1178 &[Value::Integer(1), Value::Null, Value::Integer(9)],
1179 )
1180 .expect("three values");
1181 let dictionary =
1182 Vector::dictionary(vec![0, 1, 2, 1, 0], values).expect("codes are in range");
1183 let constant = Vector::constant(LogicalType::Integer, Value::Integer(5), 5);
1184 let result = compare(Comparison::Less, &dictionary, &constant).expect("compares");
1185 assert_eq!(result.value_at(0), Value::Boolean(true));
1186 assert_eq!(result.value_at(1), Value::Null);
1187 assert_eq!(result.value_at(2), Value::Boolean(false));
1188 assert_eq!(result.value_at(3), Value::Null);
1189 assert_eq!(result.value_at(4), Value::Boolean(true));
1190 }
1191
1192 #[test]
1195 fn a_form_pair_with_no_loop_is_still_right_and_says_so() {
1196 let before = fallback::count(Kernel::Compare, Form::Sequence, Form::Flat);
1198 let sequence = Vector::sequence(10, 1, 4);
1199 let flat = Vector::from_values(
1200 LogicalType::BigInt,
1201 &[Value::BigInt(9), Value::BigInt(11), Value::BigInt(12), Value::Null],
1202 )
1203 .expect("four rows");
1204 let result = compare(Comparison::Less, &sequence, &flat).expect("compares");
1205 assert_eq!(result.value_at(0), Value::Boolean(false));
1206 assert_eq!(result.value_at(1), Value::Boolean(false));
1207 assert_eq!(result.value_at(2), Value::Boolean(false));
1208 assert_eq!(result.value_at(3), Value::Null);
1209 assert!(fallback::count(Kernel::Compare, Form::Sequence, Form::Flat) > before);
1210 }
1211
1212 #[test]
1222 fn a_second_level_of_codes_does_not_turn_the_loops_off() {
1223 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
1224 let values = Vector::from_values(
1225 LogicalType::Integer,
1226 &[Value::Integer(1), Value::Integer(5), Value::Integer(9)],
1227 )
1228 .expect("three rows");
1229 let once = Vector::dictionary(vec![2, 1, 0], values).expect("codes are in range");
1230 let twice = Vector::dictionary(vec![1, 2], once).expect("codes are in range");
1231 let cut = Vector::constant(LogicalType::Integer, Value::Integer(4), 2);
1232 let result = compare(Comparison::Greater, &twice, &cut).expect("compares");
1233 assert_eq!(result.value_at(0), Value::Boolean(true));
1234 assert_eq!(result.value_at(1), Value::Boolean(false));
1235 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
1236 }
1237
1238 #[test]
1242 fn a_side_that_is_entirely_null_answers_without_reading_the_other() {
1243 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 6);
1244 let flat = Vector::from_values(
1245 LogicalType::Integer,
1246 &[
1247 Value::Integer(1),
1248 Value::Integer(2),
1249 Value::Integer(3),
1250 Value::Integer(4),
1251 Value::Integer(5),
1252 Value::Integer(6),
1253 ],
1254 )
1255 .expect("six rows");
1256 agrees(Comparison::Less, &nulls, &flat);
1257 agrees(Comparison::Equal, &flat, &nulls);
1258 assert_eq!(
1259 compare(Comparison::Less, &nulls, &flat).expect("compares").validity(),
1260 &Validity::AllInvalid
1261 );
1262 }
1263
1264 #[test]
1267 fn an_empty_comparison_is_an_empty_answer() {
1268 let left = Vector::from_values(LogicalType::Integer, &[]).expect("no rows");
1269 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 0);
1270 let result = compare(Comparison::Equal, &left, &right).expect("compares");
1271 assert_eq!(result.len(), 0);
1272 }
1273}