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.positions(), right.constant_value()) {
346 let one = values.data()?;
347 let held = single(left.logical_type(), value)?;
348 let other = held.data()?;
349 let at = |index: usize| codes[map(index)] as usize;
350 return dispatch(op, len, one, at, other, first, left_valid, right_valid, map);
351 }
352 if let (Some(value), Some((codes, values))) = (left.constant_value(), right.positions()) {
353 let other = values.data()?;
354 let held = single(right.logical_type(), value)?;
355 let one = held.data()?;
356 let at = |index: usize| codes[map(index)] as usize;
357 return dispatch(op.swapped(), len, other, at, one, first, right_valid, left_valid, map);
358 }
359 if let (Some((codes, values)), Some(other)) = (left.positions(), right.data()) {
365 let one = values.data()?;
366 let at = |index: usize| codes[map(index)] as usize;
367 return dispatch(op, len, one, at, other, map, left_valid, right_valid, map);
368 }
369 if let (Some(one), Some((codes, values))) = (left.data(), right.positions()) {
370 let other = values.data()?;
371 let at = |index: usize| codes[map(index)] as usize;
372 return dispatch(op.swapped(), len, other, at, one, map, right_valid, left_valid, map);
373 }
374 None
375}
376
377#[expect(
383 clippy::too_many_arguments,
384 reason = "two sides with an index each, the operator, the length and two validities, all of \
385 which the loop needs and none of which is worth a struct that exists for one call"
386)]
387fn dispatch<L, R, V>(
388 op: Comparison,
389 len: usize,
390 left: &Data,
391 at_left: L,
392 right: &Data,
393 at_right: R,
394 left_valid: &Validity,
395 right_valid: &Validity,
396 at_valid: V,
397) -> Option<Vec<bool>>
398where
399 L: Fn(usize) -> usize,
400 R: Fn(usize) -> usize,
401 V: Fn(usize) -> usize,
402{
403 macro_rules! layouts {
404 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
405 match (left, right) {
406 $(
407 (Data::$variant(one), Data::$variant(other)) => Some(sweep(
408 op,
409 len,
410 |index| one[at_left(index)].cmp(&other[at_right(index)]),
411 left_valid,
412 right_valid,
413 &at_valid,
414 )),
415 )+
416 (Data::Float32(one), Data::Float32(other)) => Some(sweep(
419 op,
420 len,
421 |index| {
422 float_order(
423 f64::from(one[at_left(index)]),
424 f64::from(other[at_right(index)]),
425 )
426 },
427 left_valid,
428 right_valid,
429 &at_valid,
430 )),
431 (Data::Float64(one), Data::Float64(other)) => Some(sweep(
432 op,
433 len,
434 |index| float_order(one[at_left(index)], other[at_right(index)]),
435 left_valid,
436 right_valid,
437 &at_valid,
438 )),
439 (Data::Interval(one), Data::Interval(other)) => Some(sweep(
442 op,
443 len,
444 |index| {
445 let (months, days, micros) = one[at_left(index)];
446 let (bm, bd, bu) = other[at_right(index)];
447 interval_micros(months, days, micros).cmp(&interval_micros(bm, bd, bu))
448 },
449 left_valid,
450 right_valid,
451 &at_valid,
452 )),
453 (Data::Varlen(one), Data::Varlen(other)) => Some(sweep(
454 op,
455 len,
456 |index| string_order(one, at_left(index), other, at_right(index)),
457 left_valid,
458 right_valid,
459 &at_valid,
460 )),
461 _ => None,
462 }
463 };
464 }
465 rudb_vector::for_each_layout!(ordered, layouts)
466}
467
468fn string_order(
476 left: &StringColumn,
477 at_left: usize,
478 right: &StringColumn,
479 at_right: usize,
480) -> Ordering {
481 let (Some(one), Some(other)) = (left.views().get(at_left), right.views().get(at_right)) else {
482 return Ordering::Equal;
483 };
484 let (prefix, against) = (one.prefix(), other.prefix());
485 if prefix != against {
486 return prefix.cmp(&against);
487 }
488 let bytes = left.bytes(at_left).unwrap_or_default();
493 let against_bytes = right.bytes(at_right).unwrap_or_default();
494 bytes.cmp(against_bytes)
495}
496
497fn sweep<O, V>(
503 op: Comparison,
504 len: usize,
505 order_at: O,
506 left_valid: &Validity,
507 right_valid: &Validity,
508 at_valid: V,
509) -> Vec<bool>
510where
511 O: Fn(usize) -> Ordering,
512 V: Fn(usize) -> usize,
513{
514 let mut answers = vec![false; len];
515 match op {
516 Comparison::Equal => fill(&mut answers, order_at, |o| o == Ordering::Equal),
517 Comparison::NotEqual => fill(&mut answers, order_at, |o| o != Ordering::Equal),
518 Comparison::Less => fill(&mut answers, order_at, |o| o == Ordering::Less),
519 Comparison::LessOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Greater),
520 Comparison::Greater => fill(&mut answers, order_at, |o| o == Ordering::Greater),
521 Comparison::GreaterOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Less),
522 Comparison::DistinctFrom => {
523 total(&mut answers, order_at, left_valid, right_valid, at_valid);
524 for answer in &mut answers {
525 *answer = !*answer;
526 }
527 }
528 Comparison::NotDistinctFrom => {
529 total(&mut answers, order_at, left_valid, right_valid, at_valid);
530 }
531 }
532 answers
533}
534
535#[inline]
537fn fill<O, H>(answers: &mut [bool], order_at: O, held: H)
538where
539 O: Fn(usize) -> Ordering,
540 H: Fn(Ordering) -> bool,
541{
542 for (index, answer) in answers.iter_mut().enumerate() {
543 *answer = held(order_at(index));
544 }
545}
546
547fn total<O, V>(
554 answers: &mut [bool],
555 order_at: O,
556 left_valid: &Validity,
557 right_valid: &Validity,
558 at_valid: V,
559) where
560 O: Fn(usize) -> Ordering,
561 V: Fn(usize) -> usize,
562{
563 if *left_valid == Validity::AllValid && *right_valid == Validity::AllValid {
564 fill(answers, order_at, |o| o == Ordering::Equal);
565 return;
566 }
567 for (index, answer) in answers.iter_mut().enumerate() {
568 let row = at_valid(index);
569 *answer = match (left_valid.is_valid(row), right_valid.is_valid(row)) {
570 (true, true) => order_at(index) == Ordering::Equal,
571 (false, false) => true,
572 _ => false,
573 };
574 }
575}
576
577pub fn compare_values(op: Comparison, left: &Value, right: &Value) -> Result<Value> {
583 if op.is_total() {
584 let same = match (left.is_null(), right.is_null()) {
585 (true, true) => true,
586 (true, false) | (false, true) => false,
587 (false, false) => order(left, right)? == Ordering::Equal,
588 };
589 return Ok(Value::Boolean(match op {
590 Comparison::NotDistinctFrom => same,
591 _ => !same,
592 }));
593 }
594 if left.is_null() || right.is_null() {
595 return Ok(Value::Null);
596 }
597 let ordering = order(left, right)?;
598 let held = match op {
599 Comparison::Equal => ordering == Ordering::Equal,
600 Comparison::NotEqual => ordering != Ordering::Equal,
601 Comparison::Less => ordering == Ordering::Less,
602 Comparison::LessOrEqual => ordering != Ordering::Greater,
603 Comparison::Greater => ordering == Ordering::Greater,
604 Comparison::GreaterOrEqual => ordering != Ordering::Less,
605 Comparison::DistinctFrom | Comparison::NotDistinctFrom => {
606 return Err(Error::internal("a total comparison reached the ordered path"));
607 }
608 };
609 Ok(Value::Boolean(held))
610}
611
612pub fn order(left: &Value, right: &Value) -> Result<Ordering> {
623 match (left, right) {
624 (Value::Null, _) | (_, Value::Null) => {
625 Err(Error::internal("a null reached the ordering path"))
626 }
627 (Value::Boolean(a), Value::Boolean(b)) => Ok(a.cmp(b)),
628 (Value::Varchar(a), Value::Varchar(b)) => Ok(a.as_bytes().cmp(b.as_bytes())),
629 (Value::Blob(a), Value::Blob(b)) => Ok(a.cmp(b)),
630 (Value::Date(a), Value::Date(b)) => Ok(a.cmp(b)),
631 (Value::Time(a), Value::Time(b)) | (Value::Timestamp(a), Value::Timestamp(b)) => {
632 Ok(a.cmp(b))
633 }
634 (
635 Value::Interval { months: am, days: ad, micros: au },
636 Value::Interval { months: bm, days: bd, micros: bu },
637 ) => Ok(interval_micros(*am, *ad, *au).cmp(&interval_micros(*bm, *bd, *bu))),
638 _ => numeric_order(left, right),
639 }
640}
641
642fn numeric_order(left: &Value, right: &Value) -> Result<Ordering> {
644 if let (Some(a), Some(b)) = (integral(left), integral(right)) {
645 return Ok(a.cmp(&b));
646 }
647 if let (
648 Value::Decimal { unscaled: a, scale: sa, .. },
649 Value::Decimal { unscaled: b, scale: sb, .. },
650 ) = (left, right)
651 {
652 if sa == sb {
653 return Ok(a.cmp(b));
654 }
655 }
656 match (approximate(left), approximate(right)) {
657 (Some(a), Some(b)) => Ok(float_order(a, b)),
658 _ => Err(Error::not_implemented(format!(
659 "comparing {} with {}",
660 left.logical_type(),
661 right.logical_type()
662 ))),
663 }
664}
665
666fn float_order(left: f64, right: f64) -> Ordering {
668 if left == right {
669 return Ordering::Equal;
670 }
671 match (left.is_nan(), right.is_nan()) {
672 (true, true) => Ordering::Equal,
673 (true, false) => Ordering::Greater,
674 (false, true) => Ordering::Less,
675 (false, false) => left.partial_cmp(&right).unwrap_or(Ordering::Equal),
676 }
677}
678
679pub fn order_with_nulls(left: &Value, right: &Value, nulls_first: bool) -> Result<Ordering> {
688 match (left.is_null(), right.is_null()) {
689 (true, true) => Ok(Ordering::Equal),
690 (true, false) => Ok(if nulls_first { Ordering::Less } else { Ordering::Greater }),
691 (false, true) => Ok(if nulls_first { Ordering::Greater } else { Ordering::Less }),
692 (false, false) => order(left, right),
693 }
694}
695
696#[cfg(test)]
697mod tests {
698 use super::*;
699
700 fn compared(op: Comparison, left: Value, right: Value) -> Value {
701 compare_values(op, &left, &right).expect("these types compare")
702 }
703
704 const EVERY: [Comparison; 8] = [
706 Comparison::Equal,
707 Comparison::NotEqual,
708 Comparison::Less,
709 Comparison::LessOrEqual,
710 Comparison::Greater,
711 Comparison::GreaterOrEqual,
712 Comparison::DistinctFrom,
713 Comparison::NotDistinctFrom,
714 ];
715
716 fn oracle(op: Comparison, left: &Vector, right: &Vector) -> Vector {
722 let values: Vec<Value> = (0..left.len())
723 .map(|index| {
724 compare_values(op, &left.value_at(index), &right.value_at(index))
725 .expect("the oracle is only asked about types that compare")
726 })
727 .collect();
728 Vector::from_values(LogicalType::Boolean, &values).expect("booleans")
729 }
730
731 fn agrees(op: Comparison, left: &Vector, right: &Vector) {
735 let fast = compare(op, left, right).expect("compares");
736 let slow = oracle(op, left, right);
737 assert_eq!(fast, slow, "{op:?} on a {:?} against a {:?}", left.form(), right.form());
738 }
739
740 struct Rng(u64);
743
744 impl Rng {
745 fn next(&mut self) -> u64 {
746 self.0 ^= self.0 << 13;
747 self.0 ^= self.0 >> 7;
748 self.0 ^= self.0 << 17;
749 self.0
750 }
751
752 fn below(&mut self, bound: u64) -> u64 {
753 self.next() % bound
754 }
755 }
756
757 #[test]
758 fn an_ordinary_comparison_is_null_when_either_side_is() {
759 assert_eq!(compared(Comparison::Equal, Value::Integer(1), Value::Null), Value::Null);
760 assert_eq!(compared(Comparison::Less, Value::Null, Value::Integer(1)), Value::Null);
761 }
762
763 #[test]
764 fn a_total_comparison_is_never_null() {
765 assert_eq!(
766 compared(Comparison::NotDistinctFrom, Value::Null, Value::Null),
767 Value::Boolean(true)
768 );
769 assert_eq!(
770 compared(Comparison::NotDistinctFrom, Value::Integer(1), Value::Null),
771 Value::Boolean(false)
772 );
773 assert_eq!(
774 compared(Comparison::DistinctFrom, Value::Integer(1), Value::Null),
775 Value::Boolean(true)
776 );
777 }
778
779 #[test]
780 fn a_string_compares_by_bytes() {
781 assert_eq!(
782 compared(Comparison::Less, Value::Varchar("a".into()), Value::Varchar("b".into())),
783 Value::Boolean(true)
784 );
785 assert_eq!(
786 compared(Comparison::Less, Value::Varchar("Z".into()), Value::Varchar("a".into())),
787 Value::Boolean(true)
788 );
789 }
790
791 #[test]
794 fn two_nans_are_one_value_and_they_sort_above_the_numbers() {
795 assert_eq!(
796 compared(Comparison::Equal, Value::Double(f64::NAN), Value::Double(f64::NAN)),
797 Value::Boolean(true)
798 );
799 assert_eq!(
800 compared(Comparison::Greater, Value::Double(f64::NAN), Value::Double(1e300)),
801 Value::Boolean(true)
802 );
803 }
804
805 #[test]
806 fn zero_has_one_value_however_it_is_signed() {
807 assert_eq!(
808 compared(Comparison::Equal, Value::Double(0.0), Value::Double(-0.0)),
809 Value::Boolean(true)
810 );
811 }
812
813 #[test]
818 fn two_intervals_of_the_same_length_are_one_value() {
819 let day = Value::Interval { months: 0, days: 1, micros: 0 };
820 let hours = Value::Interval { months: 0, days: 0, micros: 86_400_000_000 };
821 let month = Value::Interval { months: 1, days: 0, micros: 0 };
822 let thirty = Value::Interval { months: 0, days: 30, micros: 0 };
823 let long_day = Value::Interval { months: 0, days: 0, micros: 90_000_000_000 };
824 assert_eq!(compared(Comparison::Equal, day.clone(), hours), Value::Boolean(true));
825 assert_eq!(compared(Comparison::Equal, month, thirty), Value::Boolean(true));
826 assert_eq!(compared(Comparison::Greater, long_day, day), Value::Boolean(true));
827 }
828
829 #[test]
830 fn a_number_compares_the_same_however_it_is_stored() {
831 assert_eq!(
832 compared(Comparison::Equal, Value::Integer(3), Value::BigInt(3)),
833 Value::Boolean(true)
834 );
835 assert_eq!(
836 compared(Comparison::Less, Value::Integer(3), Value::Double(3.5)),
837 Value::Boolean(true)
838 );
839 }
840
841 #[test]
842 fn nulls_go_where_the_query_asked_for_them() {
843 assert_eq!(
844 order_with_nulls(&Value::Null, &Value::Integer(1), true).expect("orders"),
845 Ordering::Less
846 );
847 assert_eq!(
848 order_with_nulls(&Value::Null, &Value::Integer(1), false).expect("orders"),
849 Ordering::Greater
850 );
851 }
852
853 #[test]
854 fn two_constant_vectors_cost_one_comparison() {
855 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 512);
856 let right = Vector::constant(LogicalType::Integer, Value::Integer(2), 512);
857 let result = compare(Comparison::Less, &left, &right).expect("compares");
858 assert_eq!(result.form(), Form::Constant);
859 assert_eq!(result.value_at(500), Value::Boolean(true));
860 }
861
862 #[test]
863 fn a_comparison_of_two_vectors_is_one_answer_per_row() {
864 let left = Vector::from_values(
865 LogicalType::Integer,
866 &[Value::Integer(1), Value::Integer(5), Value::Null],
867 )
868 .expect("three rows");
869 let right = Vector::constant(LogicalType::Integer, Value::Integer(3), 3);
870 let result = compare(Comparison::Greater, &left, &right).expect("compares");
871 assert_eq!(result.value_at(0), Value::Boolean(false));
872 assert_eq!(result.value_at(1), Value::Boolean(true));
873 assert_eq!(result.value_at(2), Value::Null);
874 }
875
876 #[test]
877 fn two_vectors_of_different_lengths_are_caught() {
878 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
879 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 5);
880 let error = compare(Comparison::Equal, &left, &right).expect_err("ragged");
881 assert!(error.message().contains("4 row vector"), "{error}");
882 }
883
884 #[test]
885 fn turning_a_comparison_around_is_what_the_other_side_would_have_said() {
886 for op in EVERY {
887 let left = Value::Integer(3);
888 let right = Value::Integer(7);
889 assert_eq!(
890 compare_values(op, &left, &right).expect("compares"),
891 compare_values(op.swapped(), &right, &left).expect("compares"),
892 "{op:?}"
893 );
894 }
895 }
896
897 #[test]
900 fn every_specialized_path_agrees_with_the_row_at_a_time_path() {
901 let mut rng = Rng(0x5eed_1234_9876_4321);
902 let types: [LogicalType; 11] = [
903 LogicalType::Boolean,
904 LogicalType::TinyInt,
905 LogicalType::SmallInt,
906 LogicalType::Integer,
907 LogicalType::BigInt,
908 LogicalType::HugeInt,
909 LogicalType::UInteger,
910 LogicalType::Float,
911 LogicalType::Double,
912 LogicalType::Varchar,
913 LogicalType::Interval,
914 ];
915 for ty in &types {
916 for nulls in [0u64, 1, 3] {
917 let len = 37;
918 let make = |rng: &mut Rng| {
919 let values: Vec<Value> = (0..len)
920 .map(|_| {
921 if nulls > 0 && rng.below(nulls + 1) == 0 {
922 Value::Null
923 } else {
924 sample(ty, rng)
925 }
926 })
927 .collect();
928 Vector::from_values(ty.clone(), &values).expect("a flat vector")
929 };
930 let left = make(&mut rng);
931 let right = make(&mut rng);
932 let literal = sample(ty, &mut rng);
933 let constant = Vector::constant(ty.clone(), literal, len);
934 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
935 let codes: Vec<u32> =
936 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
937 let dictionary =
938 Vector::dictionary(codes, left.clone()).expect("codes are in range");
939 let ends: Vec<u32> = (1..=left.len())
942 .map(|run| ((run * len) / left.len()).max(run) as u32)
943 .collect();
944 let runs = Vector::runs(ends, left.clone()).expect("one value for each run");
945
946 for op in EVERY {
947 agrees(op, &left, &right);
948 agrees(op, &left, &constant);
949 agrees(op, &constant, &left);
950 agrees(op, &left, &null_constant);
951 agrees(op, &null_constant, &left);
952 agrees(op, &dictionary, &constant);
953 agrees(op, &constant, &dictionary);
954 agrees(op, &dictionary, &right);
958 agrees(op, &right, &dictionary);
959 agrees(op, &runs, &constant);
963 agrees(op, &constant, &runs);
964 agrees(op, &runs, &right);
965 agrees(op, &right, &runs);
966 }
967 }
968 }
969 }
970
971 fn refined(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) -> Selection {
973 let mut out = Vec::new();
974 for &row in kept.indices() {
975 let index = row as usize;
976 let answer = compare_values(op, &left.value_at(index), &right.value_at(index))
977 .expect("the oracle is only asked about types that compare");
978 if is_true(&answer) {
979 out.push(row);
980 }
981 }
982 Selection::from_indices(out)
983 }
984
985 fn threads(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) {
986 let fast = refine(op, left, right, kept).expect("compares");
987 assert_eq!(
988 fast,
989 refined(op, left, right, kept),
990 "{op:?} on a {:?} against a {:?} over {} rows",
991 left.form(),
992 right.form(),
993 kept.len()
994 );
995 }
996
997 #[test]
1001 fn a_threaded_comparison_keeps_what_the_row_at_a_time_path_keeps() {
1002 let mut rng = Rng(0x5eed_4321_1234_9876);
1003 let types = [LogicalType::Integer, LogicalType::Double, LogicalType::Varchar];
1004 for ty in &types {
1005 for nulls in [0u64, 1, 3] {
1006 let len = 37;
1007 let make = |rng: &mut Rng| {
1008 let values: Vec<Value> = (0..len)
1009 .map(|_| {
1010 if nulls > 0 && rng.below(nulls + 1) == 0 {
1011 Value::Null
1012 } else {
1013 sample(ty, rng)
1014 }
1015 })
1016 .collect();
1017 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1018 };
1019 let left = make(&mut rng);
1020 let right = make(&mut rng);
1021 let constant = Vector::constant(ty.clone(), sample(ty, &mut rng), len);
1022 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1023 let codes: Vec<u32> =
1024 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1025 let dictionary =
1026 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1027
1028 let selections = [
1032 Selection::identity(len),
1033 Selection::from_indices((0..len as u32).filter(|row| row % 3 == 0).collect()),
1034 Selection::from_indices(vec![2, 5, 6, 17, 36]),
1035 Selection::empty(),
1036 ];
1037 for op in EVERY {
1038 for kept in &selections {
1039 threads(op, &left, &right, kept);
1040 threads(op, &left, &constant, kept);
1041 threads(op, &constant, &left, kept);
1042 threads(op, &left, &null_constant, kept);
1043 threads(op, &null_constant, &left, kept);
1044 threads(op, &constant, &null_constant, kept);
1045 threads(op, &dictionary, &constant, kept);
1046 threads(op, &constant, &dictionary, kept);
1047 threads(op, &dictionary, &right, kept);
1048 threads(op, &right, &dictionary, kept);
1049 }
1050 }
1051 }
1052 }
1053 }
1054
1055 #[test]
1059 fn a_second_conjunct_reads_only_what_the_first_one_left() {
1060 let numbers: Vec<Value> = (0..64).map(|row| Value::Integer(row % 10)).collect();
1061 let column = Vector::from_values(LogicalType::Integer, &numbers).expect("a flat vector");
1062 let three = Vector::constant(LogicalType::Integer, Value::Integer(3), 64);
1063 let seven = Vector::constant(LogicalType::Integer, Value::Integer(7), 64);
1064
1065 let first = refine(Comparison::Greater, &column, &three, &Selection::identity(64))
1066 .expect("compares");
1067 let both = refine(Comparison::Less, &column, &seven, &first).expect("compares");
1068
1069 let expected: Vec<u32> = (0..64)
1070 .filter(|row| {
1071 let value = row % 10;
1072 value > 3 && value < 7
1073 })
1074 .collect();
1075 assert_eq!(both.indices(), expected.as_slice());
1076 assert!(both.len() < first.len(), "the second conjunct narrowed the selection");
1077 }
1078
1079 #[test]
1083 fn a_null_row_is_not_kept_by_an_ordinary_comparison_and_is_by_a_total_one() {
1084 let column = Vector::from_values(
1085 LogicalType::Integer,
1086 &[Value::Integer(1), Value::Null, Value::Integer(3), Value::Null],
1087 )
1088 .expect("four rows");
1089 let cut = Vector::constant(LogicalType::Integer, Value::Integer(2), 4);
1090 let all = Selection::identity(4);
1091 assert_eq!(
1092 refine(Comparison::Less, &column, &cut, &all).expect("compares").indices(),
1093 &[0]
1094 );
1095 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 4);
1097 assert_eq!(
1098 refine(Comparison::NotDistinctFrom, &column, &nulls, &all).expect("compares").indices(),
1099 &[1, 3]
1100 );
1101 }
1102
1103 #[test]
1104 fn a_selection_past_the_end_is_caught() {
1105 let column = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1106 let past = Selection::from_indices(vec![0, 4]);
1107 let error = refine(Comparison::Equal, &column, &column, &past).expect_err("out of range");
1108 assert!(error.message().contains("4 row vector"), "{error}");
1109 }
1110
1111 fn sample(ty: &LogicalType, rng: &mut Rng) -> Value {
1113 match ty {
1114 LogicalType::Boolean => Value::Boolean(rng.below(2) == 1),
1115 LogicalType::TinyInt => Value::TinyInt(rng.below(7) as i8 - 3),
1116 LogicalType::SmallInt => Value::SmallInt(rng.below(11) as i16 - 5),
1117 LogicalType::Integer => Value::Integer(rng.below(9) as i32 - 4),
1118 LogicalType::BigInt => Value::BigInt(rng.below(9) as i64 - 4),
1119 LogicalType::HugeInt => Value::HugeInt(i128::from(rng.below(9)) - 4),
1120 LogicalType::UInteger => Value::UInteger(rng.below(9) as u32),
1121 LogicalType::Float => Value::Float(match rng.below(5) {
1124 0 => f32::NAN,
1125 1 => -0.0,
1126 other => other as f32 - 2.0,
1127 }),
1128 LogicalType::Double => Value::Double(match rng.below(5) {
1129 0 => f64::NAN,
1130 1 => -0.0,
1131 other => other as f64 - 2.0,
1132 }),
1133 LogicalType::Interval => match rng.below(6) {
1137 0 => Value::Interval { months: 0, days: 1, micros: 0 },
1138 1 => Value::Interval { months: 0, days: 0, micros: 86_400_000_000 },
1139 2 => Value::Interval { months: 1, days: -29, micros: 86_400_000_000 },
1140 3 => Value::Interval { months: 1, days: 0, micros: 0 },
1141 4 => Value::Interval { months: 0, days: 0, micros: 90_000_000_000 },
1142 _ => Value::Interval { months: -1, days: 0, micros: 0 },
1143 },
1144 LogicalType::Varchar => Value::Varchar(
1147 match rng.below(6) {
1148 0 => "",
1149 1 => "ab",
1150 2 => "abc",
1151 3 => "abcdefghijkl",
1152 4 => "abcdefghijklm",
1153 _ => "abcdefghijklmnopqrstuvwxyz",
1154 }
1155 .to_owned(),
1156 ),
1157 other => panic!("the generator has no values for {other}"),
1158 }
1159 }
1160
1161 #[test]
1165 fn prefix_order_is_byte_order_whenever_the_prefixes_differ() {
1166 let words =
1167 ["", "a", "ab", "abc", "abcd", "abcde", "b", "abcdefghijklmnop", "abcdefghijklmnoq"];
1168 let mut column = StringColumn::new();
1169 for word in words {
1170 column.push(word);
1171 }
1172 for (i, one) in words.iter().enumerate() {
1173 for (j, other) in words.iter().enumerate() {
1174 assert_eq!(
1175 string_order(&column, i, &column, j),
1176 one.as_bytes().cmp(other.as_bytes()),
1177 "{one:?} against {other:?}"
1178 );
1179 }
1180 }
1181 }
1182
1183 #[test]
1186 fn a_dictionary_against_a_constant_reads_its_nulls_from_the_values() {
1187 let values = Vector::from_values(
1188 LogicalType::Integer,
1189 &[Value::Integer(1), Value::Null, Value::Integer(9)],
1190 )
1191 .expect("three values");
1192 let dictionary =
1193 Vector::dictionary(vec![0, 1, 2, 1, 0], values).expect("codes are in range");
1194 let constant = Vector::constant(LogicalType::Integer, Value::Integer(5), 5);
1195 let result = compare(Comparison::Less, &dictionary, &constant).expect("compares");
1196 assert_eq!(result.value_at(0), Value::Boolean(true));
1197 assert_eq!(result.value_at(1), Value::Null);
1198 assert_eq!(result.value_at(2), Value::Boolean(false));
1199 assert_eq!(result.value_at(3), Value::Null);
1200 assert_eq!(result.value_at(4), Value::Boolean(true));
1201 }
1202
1203 #[test]
1206 fn a_form_pair_with_no_loop_is_still_right_and_says_so() {
1207 let before = fallback::count(Kernel::Compare, Form::Sequence, Form::Flat);
1209 let sequence = Vector::sequence(10, 1, 4);
1210 let flat = Vector::from_values(
1211 LogicalType::BigInt,
1212 &[Value::BigInt(9), Value::BigInt(11), Value::BigInt(12), Value::Null],
1213 )
1214 .expect("four rows");
1215 let result = compare(Comparison::Less, &sequence, &flat).expect("compares");
1216 assert_eq!(result.value_at(0), Value::Boolean(false));
1217 assert_eq!(result.value_at(1), Value::Boolean(false));
1218 assert_eq!(result.value_at(2), Value::Boolean(false));
1219 assert_eq!(result.value_at(3), Value::Null);
1220 assert!(fallback::count(Kernel::Compare, Form::Sequence, Form::Flat) > before);
1221 }
1222
1223 #[test]
1233 fn a_second_level_of_codes_does_not_turn_the_loops_off() {
1234 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
1235 let values = Vector::from_values(
1236 LogicalType::Integer,
1237 &[Value::Integer(1), Value::Integer(5), Value::Integer(9)],
1238 )
1239 .expect("three rows");
1240 let once = Vector::dictionary(vec![2, 1, 0], values).expect("codes are in range");
1241 let twice = Vector::dictionary(vec![1, 2], once).expect("codes are in range");
1242 let cut = Vector::constant(LogicalType::Integer, Value::Integer(4), 2);
1243 let result = compare(Comparison::Greater, &twice, &cut).expect("compares");
1244 assert_eq!(result.value_at(0), Value::Boolean(true));
1245 assert_eq!(result.value_at(1), Value::Boolean(false));
1246 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
1247 }
1248
1249 #[test]
1253 fn a_side_that_is_entirely_null_answers_without_reading_the_other() {
1254 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 6);
1255 let flat = Vector::from_values(
1256 LogicalType::Integer,
1257 &[
1258 Value::Integer(1),
1259 Value::Integer(2),
1260 Value::Integer(3),
1261 Value::Integer(4),
1262 Value::Integer(5),
1263 Value::Integer(6),
1264 ],
1265 )
1266 .expect("six rows");
1267 agrees(Comparison::Less, &nulls, &flat);
1268 agrees(Comparison::Equal, &flat, &nulls);
1269 assert_eq!(
1270 compare(Comparison::Less, &nulls, &flat).expect("compares").validity(),
1271 &Validity::AllInvalid
1272 );
1273 }
1274
1275 #[test]
1278 fn an_empty_comparison_is_an_empty_answer() {
1279 let left = Vector::from_values(LogicalType::Integer, &[]).expect("no rows");
1280 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 0);
1281 let result = compare(Comparison::Equal, &left, &right).expect("compares");
1282 assert_eq!(result.len(), 0);
1283 }
1284}