1use std::borrow::Cow;
72use std::cmp::Ordering;
73
74use rudb_common::{Error, LogicalType, Result, Value, interval_micros};
75use rudb_vector::{
76 Coded, Data, Form, Packed, Selection, StringColumn, StringView, Validity, Vector,
77};
78
79use crate::fallback::{self, Kernel};
80use crate::logic::is_true;
81use crate::number::{approximate, integral};
82use crate::prepare::Held;
83use crate::shape::{first, identity, nulls_of, single};
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
87pub enum Comparison {
88 Equal,
90 NotEqual,
92 Less,
94 LessOrEqual,
96 Greater,
98 GreaterOrEqual,
100 DistinctFrom,
102 NotDistinctFrom,
104}
105
106impl Comparison {
107 #[must_use]
109 pub fn is_total(self) -> bool {
110 matches!(self, Self::DistinctFrom | Self::NotDistinctFrom)
111 }
112
113 #[must_use]
120 pub fn swapped(self) -> Self {
121 match self {
122 Self::Less => Self::Greater,
123 Self::LessOrEqual => Self::GreaterOrEqual,
124 Self::Greater => Self::Less,
125 Self::GreaterOrEqual => Self::LessOrEqual,
126 same => same,
127 }
128 }
129}
130
131pub fn compare(op: Comparison, left: &Vector, right: &Vector) -> Result<Vector> {
137 compare_prepared(op, left, right, None)
138}
139
140pub fn compare_prepared(
150 op: Comparison,
151 left: &Vector,
152 right: &Vector,
153 held: Option<&Held>,
154) -> Result<Vector> {
155 if left.len() != right.len() {
156 return Err(Error::internal(format!(
157 "a comparison of a {} row vector with a {} row one",
158 left.len(),
159 right.len()
160 )));
161 }
162 let len = left.len();
163 if left.form() == Form::Constant && right.form() == Form::Constant && len > 0 {
164 let single = compare_values(op, &left.value_at(0), &right.value_at(0))?;
165 return Ok(Vector::constant(LogicalType::Boolean, single, len));
166 }
167
168 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
169 if !op.is_total()
173 && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
174 && len > 0
175 {
176 return boolean(vec![false; len], Validity::AllInvalid, len);
177 }
178
179 if let Some(answers) =
180 specialized(op, left, right, &left_valid, &right_valid, len, identity, held)
181 {
182 let validity =
183 if op.is_total() { Validity::AllValid } else { left_valid.and(&right_valid, len) };
184 return boolean(blank_the_nulls(answers, &validity), validity, len);
185 }
186
187 fallback::record(Kernel::Compare, left.form(), right.form());
188 let mut values = Vec::with_capacity(len);
189 for index in 0..len {
192 values.push(compare_values(op, &left.value_at(index), &right.value_at(index))?);
193 }
194 Vector::from_values(LogicalType::Boolean, &values)
195}
196
197pub fn refine(
215 op: Comparison,
216 left: &Vector,
217 right: &Vector,
218 kept: &Selection,
219) -> Result<Selection> {
220 refine_prepared(op, left, right, kept, None)
221}
222
223pub fn refine_prepared(
233 op: Comparison,
234 left: &Vector,
235 right: &Vector,
236 kept: &Selection,
237 held: Option<&Held>,
238) -> Result<Selection> {
239 if left.len() != right.len() {
240 return Err(Error::internal(format!(
241 "a comparison of a {} row vector with a {} row one",
242 left.len(),
243 right.len()
244 )));
245 }
246 let len = left.len();
247 if kept.indices().iter().any(|&row| row as usize >= len) {
251 return Err(Error::internal(format!("a selection past the end of a {len} row vector")));
252 }
253 if kept.is_empty() {
254 return Ok(Selection::empty());
255 }
256 if left.form() == Form::Constant && right.form() == Form::Constant {
257 let single = compare_values(op, &left.value_at(0), &right.value_at(0))?;
258 return Ok(if is_true(&single) { kept.clone() } else { Selection::empty() });
259 }
260
261 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
262 if !op.is_total() && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
263 {
264 return Ok(Selection::empty());
265 }
266
267 let rows = kept.indices();
268 let map = |slot: usize| rows[slot] as usize;
269 if let Some(answers) =
270 specialized(op, left, right, &left_valid, &right_valid, kept.len(), map, held)
271 {
272 if op.is_total() || (left_valid == Validity::AllValid && right_valid == Validity::AllValid)
275 {
276 return Ok(narrowed(&answers, rows, |_| true));
277 }
278 return Ok(narrowed(&answers, rows, |slot| {
282 let row = rows[slot] as usize;
283 left_valid.is_valid(row) && right_valid.is_valid(row)
284 }));
285 }
286
287 fallback::record(Kernel::Compare, left.form(), right.form());
288 let mut out = Vec::with_capacity(kept.len());
289 for &row in rows {
292 let index = row as usize;
293 if is_true(&compare_values(op, &left.value_at(index), &right.value_at(index))?) {
294 out.push(row);
295 }
296 }
297 Ok(Selection::from_indices(out))
298}
299
300fn narrowed<L: Fn(usize) -> bool>(answers: &[bool], rows: &[u32], live: L) -> Selection {
307 let mut out = vec![0_u32; answers.len()];
308 let mut count = 0;
309 for (slot, &answer) in answers.iter().enumerate() {
310 out[count] = rows[slot];
311 count += usize::from(answer & live(slot));
313 }
314 out.truncate(count);
315 Selection::from_indices(out)
316}
317
318fn boolean(answers: Vec<bool>, validity: Validity, len: usize) -> Result<Vector> {
320 let validity = if len == 0 { Validity::AllValid } else { validity.normalize(len) };
324 Ok(Vector::flat(LogicalType::Boolean, Data::Bool(answers.into()))?.with_validity(validity))
325}
326
327fn blank_the_nulls(mut answers: Vec<bool>, validity: &Validity) -> Vec<bool> {
335 if let Validity::Mask(mask) = validity {
336 for (index, answer) in answers.iter_mut().enumerate() {
337 if !mask.get(index) {
338 *answer = false;
339 }
340 }
341 }
342 answers
343}
344
345#[expect(
357 clippy::too_many_arguments,
358 reason = "two sides, two validities, the operator, the length, the index mapping and the \
359 literal that was built early, all of which the branches below need"
360)]
361fn specialized<M>(
362 op: Comparison,
363 left: &Vector,
364 right: &Vector,
365 left_valid: &Validity,
366 right_valid: &Validity,
367 len: usize,
368 map: M,
369 held: Option<&Held>,
370) -> Option<Vec<bool>>
371where
372 M: Fn(usize) -> usize + Copy,
373{
374 if left.logical_type() != right.logical_type() {
378 return None;
379 }
380
381 if let (Some(one), Some(other)) = (left.data(), right.data()) {
382 return dispatch(op, len, one, map, other, map, left_valid, right_valid, map);
383 }
384 if !op.is_total() {
390 if let (Some(packed), Some(value)) = (left.packed_parts(), right.constant_value()) {
391 let wanted = exact(held, left.logical_type(), value)?;
392 return Some(packed_against(op, &packed, wanted, len, map));
393 }
394 if let (Some(value), Some(packed)) = (left.constant_value(), right.packed_parts()) {
395 let wanted = exact(held, right.logical_type(), value)?;
396 return Some(packed_against(op.swapped(), &packed, wanted, len, map));
397 }
398 }
399 if let (Some(one), Some(value)) = (left.data(), right.constant_value()) {
400 let column = readied(held, left.logical_type(), value)?;
401 let other = column.data()?;
402 return dispatch(op, len, one, map, other, first, left_valid, right_valid, map);
403 }
404 if let (Some(value), Some(other)) = (left.constant_value(), right.data()) {
405 let column = readied(held, right.logical_type(), value)?;
407 let one = column.data()?;
408 return dispatch(op.swapped(), len, other, map, one, first, right_valid, left_valid, map);
409 }
410 if matches!(op, Comparison::Equal | Comparison::NotEqual) {
415 if let (Some(coded), Some(value)) = (left.coded_parts(), right.constant_value()) {
416 let wanted = encoded(&coded, held, left.logical_type(), value)?;
417 return Some(coded_against(op, &coded, &wanted, len, map));
418 }
419 if let (Some(value), Some(coded)) = (left.constant_value(), right.coded_parts()) {
420 let wanted = encoded(&coded, held, right.logical_type(), value)?;
421 return Some(coded_against(op, &coded, &wanted, len, map));
422 }
423 }
424 if let (Some((one, one_arena)), Some((other, other_arena))) =
430 (left.text_parts(), right.text_parts())
431 {
432 return Some(sweep(
433 op,
434 len,
435 |index| view_order(one.get(map(index)), one_arena, other.get(map(index)), other_arena),
436 left_valid,
437 right_valid,
438 map,
439 ));
440 }
441 if let (Some((one, one_arena)), Some(value)) = (left.text_parts(), right.constant_value()) {
445 let column = readied(held, left.logical_type(), value)?;
446 let (other, other_arena) = column.text_parts()?;
447 let wanted = other.first();
448 return Some(sweep(
449 op,
450 len,
451 |index| view_order(one.get(map(index)), one_arena, wanted, other_arena),
452 left_valid,
453 right_valid,
454 map,
455 ));
456 }
457 if let (Some(value), Some((other, other_arena))) = (left.constant_value(), right.text_parts()) {
458 let column = readied(held, right.logical_type(), value)?;
460 let (one, one_arena) = column.text_parts()?;
461 let wanted = one.first();
462 return Some(sweep(
463 op.swapped(),
464 len,
465 |index| view_order(other.get(map(index)), other_arena, wanted, one_arena),
466 right_valid,
467 left_valid,
468 map,
469 ));
470 }
471 if let (Some((codes, values)), Some(value)) = (left.positions(), right.constant_value()) {
472 let one = values.data()?;
473 let column = readied(held, left.logical_type(), value)?;
474 let other = column.data()?;
475 let at = |index: usize| codes[map(index)] as usize;
476 return dispatch(op, len, one, at, other, first, left_valid, right_valid, map);
477 }
478 if let (Some(value), Some((codes, values))) = (left.constant_value(), right.positions()) {
479 let other = values.data()?;
480 let column = readied(held, right.logical_type(), value)?;
481 let one = column.data()?;
482 let at = |index: usize| codes[map(index)] as usize;
483 return dispatch(op.swapped(), len, other, at, one, first, right_valid, left_valid, map);
484 }
485 if let (Some((codes, values)), Some(other)) = (left.positions(), right.data()) {
491 let one = values.data()?;
492 let at = |index: usize| codes[map(index)] as usize;
493 return dispatch(op, len, one, at, other, map, left_valid, right_valid, map);
494 }
495 if let (Some(one), Some((codes, values))) = (left.data(), right.positions()) {
496 let other = values.data()?;
497 let at = |index: usize| codes[map(index)] as usize;
498 return dispatch(op.swapped(), len, other, at, one, map, right_valid, left_valid, map);
499 }
500 None
501}
502
503fn exact(held: Option<&Held>, ty: &LogicalType, value: &Value) -> Option<i128> {
510 let column = readied(held, ty, value)?;
511 let data = column.data()?;
512 data.signed_at(0).or_else(|| data.unsigned_at(0).and_then(|value| i128::try_from(value).ok()))
513}
514
515fn encoded(
521 coded: &Coded<'_>,
522 held: Option<&Held>,
523 ty: &LogicalType,
524 value: &Value,
525) -> Option<Vec<u8>> {
526 let column = readied(held, ty, value)?;
527 let (views, arena) = column.text_parts()?;
528 Some(coded.encode(views.first()?.bytes_in(arena)?))
529}
530
531fn coded_against<M>(
537 op: Comparison,
538 coded: &Coded<'_>,
539 wanted: &[u8],
540 len: usize,
541 map: M,
542) -> Vec<bool>
543where
544 M: Fn(usize) -> usize + Copy,
545{
546 let same = op == Comparison::Equal;
547 let mut answers = Vec::with_capacity(len);
548 for row in 0..len {
549 answers.push((coded.row(map(row)) == Some(wanted)) == same);
550 }
551 answers
552}
553
554fn packed_against<M>(
560 op: Comparison,
561 packed: &Packed<'_>,
562 wanted: i128,
563 len: usize,
564 map: M,
565) -> Vec<bool>
566where
567 M: Fn(usize) -> usize + Copy,
568{
569 let Some(code) = packed.code_of(wanted) else {
570 let above = wanted > packed.ceiling();
573 let same = match op {
574 Comparison::Equal | Comparison::NotDistinctFrom => false,
575 Comparison::NotEqual | Comparison::DistinctFrom => true,
576 Comparison::Less | Comparison::LessOrEqual => above,
577 Comparison::Greater | Comparison::GreaterOrEqual => !above,
578 };
579 return vec![same; len];
580 };
581 let test: fn(u64, u64) -> bool = match op {
584 Comparison::Equal | Comparison::NotDistinctFrom => |found, want| found == want,
585 Comparison::NotEqual | Comparison::DistinctFrom => |found, want| found != want,
586 Comparison::Less => |found, want| found < want,
587 Comparison::LessOrEqual => |found, want| found <= want,
588 Comparison::Greater => |found, want| found > want,
589 Comparison::GreaterOrEqual => |found, want| found >= want,
590 };
591 let mut answers = Vec::with_capacity(len);
592 for row in 0..len {
593 answers.push(test(packed.code(map(row)), code));
594 }
595 answers
596}
597
598#[expect(
604 clippy::too_many_arguments,
605 reason = "two sides with an index each, the operator, the length and two validities, all of \
606 which the loop needs and none of which is worth a struct that exists for one call"
607)]
608fn dispatch<L, R, V>(
609 op: Comparison,
610 len: usize,
611 left: &Data,
612 at_left: L,
613 right: &Data,
614 at_right: R,
615 left_valid: &Validity,
616 right_valid: &Validity,
617 at_valid: V,
618) -> Option<Vec<bool>>
619where
620 L: Fn(usize) -> usize,
621 R: Fn(usize) -> usize,
622 V: Fn(usize) -> usize,
623{
624 macro_rules! layouts {
625 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
626 match (left, right) {
627 $(
628 (Data::$variant(one), Data::$variant(other)) => Some(sweep(
629 op,
630 len,
631 |index| one[at_left(index)].cmp(&other[at_right(index)]),
632 left_valid,
633 right_valid,
634 &at_valid,
635 )),
636 )+
637 (Data::Float32(one), Data::Float32(other)) => Some(sweep(
640 op,
641 len,
642 |index| {
643 float_order(
644 f64::from(one[at_left(index)]),
645 f64::from(other[at_right(index)]),
646 )
647 },
648 left_valid,
649 right_valid,
650 &at_valid,
651 )),
652 (Data::Float64(one), Data::Float64(other)) => Some(sweep(
653 op,
654 len,
655 |index| float_order(one[at_left(index)], other[at_right(index)]),
656 left_valid,
657 right_valid,
658 &at_valid,
659 )),
660 (Data::Interval(one), Data::Interval(other)) => Some(sweep(
663 op,
664 len,
665 |index| {
666 let (months, days, micros) = one[at_left(index)];
667 let (bm, bd, bu) = other[at_right(index)];
668 interval_micros(months, days, micros).cmp(&interval_micros(bm, bd, bu))
669 },
670 left_valid,
671 right_valid,
672 &at_valid,
673 )),
674 (Data::Varlen(one), Data::Varlen(other)) => Some(sweep(
675 op,
676 len,
677 |index| string_order(one, at_left(index), other, at_right(index)),
678 left_valid,
679 right_valid,
680 &at_valid,
681 )),
682 _ => None,
683 }
684 };
685 }
686 rudb_vector::for_each_layout!(ordered, layouts)
687}
688
689fn readied<'a>(held: Option<&'a Held>, ty: &LogicalType, value: &Value) -> Option<Cow<'a, Vector>> {
695 match held {
696 Some(held) if held.matches(ty, value) => Some(Cow::Borrowed(held.single())),
697 _ => Some(Cow::Owned(single(ty, value)?)),
698 }
699}
700
701fn string_order(
709 left: &StringColumn,
710 at_left: usize,
711 right: &StringColumn,
712 at_right: usize,
713) -> Ordering {
714 view_order(left.views().get(at_left), left.arena(), right.views().get(at_right), right.arena())
715}
716
717fn view_order(
723 one: Option<&StringView>,
724 one_arena: &[u8],
725 other: Option<&StringView>,
726 other_arena: &[u8],
727) -> Ordering {
728 let (Some(one), Some(other)) = (one, other) else {
729 return Ordering::Equal;
730 };
731 let (prefix, against) = (one.prefix(), other.prefix());
732 if prefix != against {
733 return prefix.cmp(&against);
734 }
735 let bytes = one.bytes_in(one_arena).unwrap_or_default();
740 let against_bytes = other.bytes_in(other_arena).unwrap_or_default();
741 bytes.cmp(against_bytes)
742}
743
744fn sweep<O, V>(
750 op: Comparison,
751 len: usize,
752 order_at: O,
753 left_valid: &Validity,
754 right_valid: &Validity,
755 at_valid: V,
756) -> Vec<bool>
757where
758 O: Fn(usize) -> Ordering,
759 V: Fn(usize) -> usize,
760{
761 let mut answers = vec![false; len];
762 match op {
763 Comparison::Equal => fill(&mut answers, order_at, |o| o == Ordering::Equal),
764 Comparison::NotEqual => fill(&mut answers, order_at, |o| o != Ordering::Equal),
765 Comparison::Less => fill(&mut answers, order_at, |o| o == Ordering::Less),
766 Comparison::LessOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Greater),
767 Comparison::Greater => fill(&mut answers, order_at, |o| o == Ordering::Greater),
768 Comparison::GreaterOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Less),
769 Comparison::DistinctFrom => {
770 total(&mut answers, order_at, left_valid, right_valid, at_valid);
771 for answer in &mut answers {
772 *answer = !*answer;
773 }
774 }
775 Comparison::NotDistinctFrom => {
776 total(&mut answers, order_at, left_valid, right_valid, at_valid);
777 }
778 }
779 answers
780}
781
782#[inline]
784fn fill<O, H>(answers: &mut [bool], order_at: O, held: H)
785where
786 O: Fn(usize) -> Ordering,
787 H: Fn(Ordering) -> bool,
788{
789 for (index, answer) in answers.iter_mut().enumerate() {
790 *answer = held(order_at(index));
791 }
792}
793
794fn total<O, V>(
801 answers: &mut [bool],
802 order_at: O,
803 left_valid: &Validity,
804 right_valid: &Validity,
805 at_valid: V,
806) where
807 O: Fn(usize) -> Ordering,
808 V: Fn(usize) -> usize,
809{
810 if *left_valid == Validity::AllValid && *right_valid == Validity::AllValid {
811 fill(answers, order_at, |o| o == Ordering::Equal);
812 return;
813 }
814 for (index, answer) in answers.iter_mut().enumerate() {
815 let row = at_valid(index);
816 *answer = match (left_valid.is_valid(row), right_valid.is_valid(row)) {
817 (true, true) => order_at(index) == Ordering::Equal,
818 (false, false) => true,
819 _ => false,
820 };
821 }
822}
823
824pub fn compare_values(op: Comparison, left: &Value, right: &Value) -> Result<Value> {
830 if op.is_total() {
831 let same = match (left.is_null(), right.is_null()) {
832 (true, true) => true,
833 (true, false) | (false, true) => false,
834 (false, false) => order(left, right)? == Ordering::Equal,
835 };
836 return Ok(Value::Boolean(match op {
837 Comparison::NotDistinctFrom => same,
838 _ => !same,
839 }));
840 }
841 if left.is_null() || right.is_null() {
842 return Ok(Value::Null);
843 }
844 let ordering = order(left, right)?;
845 let held = match op {
846 Comparison::Equal => ordering == Ordering::Equal,
847 Comparison::NotEqual => ordering != Ordering::Equal,
848 Comparison::Less => ordering == Ordering::Less,
849 Comparison::LessOrEqual => ordering != Ordering::Greater,
850 Comparison::Greater => ordering == Ordering::Greater,
851 Comparison::GreaterOrEqual => ordering != Ordering::Less,
852 Comparison::DistinctFrom | Comparison::NotDistinctFrom => {
853 return Err(Error::internal("a total comparison reached the ordered path"));
854 }
855 };
856 Ok(Value::Boolean(held))
857}
858
859pub fn order(left: &Value, right: &Value) -> Result<Ordering> {
870 match (left, right) {
871 (Value::Null, _) | (_, Value::Null) => {
872 Err(Error::internal("a null reached the ordering path"))
873 }
874 (Value::Boolean(a), Value::Boolean(b)) => Ok(a.cmp(b)),
875 (Value::Varchar(a), Value::Varchar(b)) => Ok(a.as_bytes().cmp(b.as_bytes())),
876 (Value::Blob(a), Value::Blob(b)) => Ok(a.cmp(b)),
877 (Value::Date(a), Value::Date(b)) => Ok(a.cmp(b)),
878 (Value::Time(a), Value::Time(b))
881 | (Value::TimeTz(a), Value::TimeTz(b))
882 | (Value::Timestamp(a), Value::Timestamp(b))
883 | (Value::TimestampTz(a), Value::TimestampTz(b)) => Ok(a.cmp(b)),
884 (
885 Value::Interval { months: am, days: ad, micros: au },
886 Value::Interval { months: bm, days: bd, micros: bu },
887 ) => Ok(interval_micros(*am, *ad, *au).cmp(&interval_micros(*bm, *bd, *bu))),
888 _ => numeric_order(left, right),
889 }
890}
891
892fn numeric_order(left: &Value, right: &Value) -> Result<Ordering> {
894 if let (Some(a), Some(b)) = (integral(left), integral(right)) {
895 return Ok(a.cmp(&b));
896 }
897 if let (
898 Value::Decimal { unscaled: a, scale: sa, .. },
899 Value::Decimal { unscaled: b, scale: sb, .. },
900 ) = (left, right)
901 {
902 if sa == sb {
903 return Ok(a.cmp(b));
904 }
905 }
906 match (approximate(left), approximate(right)) {
907 (Some(a), Some(b)) => Ok(float_order(a, b)),
908 _ => Err(Error::not_implemented(format!(
909 "comparing {} with {}",
910 left.logical_type(),
911 right.logical_type()
912 ))),
913 }
914}
915
916fn float_order(left: f64, right: f64) -> Ordering {
918 if left == right {
919 return Ordering::Equal;
920 }
921 match (left.is_nan(), right.is_nan()) {
922 (true, true) => Ordering::Equal,
923 (true, false) => Ordering::Greater,
924 (false, true) => Ordering::Less,
925 (false, false) => left.partial_cmp(&right).unwrap_or(Ordering::Equal),
926 }
927}
928
929pub fn order_with_nulls(left: &Value, right: &Value, nulls_first: bool) -> Result<Ordering> {
938 match (left.is_null(), right.is_null()) {
939 (true, true) => Ok(Ordering::Equal),
940 (true, false) => Ok(if nulls_first { Ordering::Less } else { Ordering::Greater }),
941 (false, true) => Ok(if nulls_first { Ordering::Greater } else { Ordering::Less }),
942 (false, false) => order(left, right),
943 }
944}
945
946#[cfg(test)]
947mod tests {
948 use super::*;
949
950 fn compared(op: Comparison, left: Value, right: Value) -> Value {
951 compare_values(op, &left, &right).expect("these types compare")
952 }
953
954 const EVERY: [Comparison; 8] = [
956 Comparison::Equal,
957 Comparison::NotEqual,
958 Comparison::Less,
959 Comparison::LessOrEqual,
960 Comparison::Greater,
961 Comparison::GreaterOrEqual,
962 Comparison::DistinctFrom,
963 Comparison::NotDistinctFrom,
964 ];
965
966 fn oracle(op: Comparison, left: &Vector, right: &Vector) -> Vector {
972 let values: Vec<Value> = (0..left.len())
973 .map(|index| {
974 compare_values(op, &left.value_at(index), &right.value_at(index))
975 .expect("the oracle is only asked about types that compare")
976 })
977 .collect();
978 Vector::from_values(LogicalType::Boolean, &values).expect("booleans")
979 }
980
981 fn agrees(op: Comparison, left: &Vector, right: &Vector) {
985 let fast = compare(op, left, right).expect("compares");
986 let slow = oracle(op, left, right);
987 assert_eq!(fast, slow, "{op:?} on a {:?} against a {:?}", left.form(), right.form());
988 }
989
990 struct Rng(u64);
993
994 impl Rng {
995 fn next(&mut self) -> u64 {
996 self.0 ^= self.0 << 13;
997 self.0 ^= self.0 >> 7;
998 self.0 ^= self.0 << 17;
999 self.0
1000 }
1001
1002 fn below(&mut self, bound: u64) -> u64 {
1003 self.next() % bound
1004 }
1005 }
1006
1007 #[test]
1008 fn an_ordinary_comparison_is_null_when_either_side_is() {
1009 assert_eq!(compared(Comparison::Equal, Value::Integer(1), Value::Null), Value::Null);
1010 assert_eq!(compared(Comparison::Less, Value::Null, Value::Integer(1)), Value::Null);
1011 }
1012
1013 #[test]
1014 fn a_total_comparison_is_never_null() {
1015 assert_eq!(
1016 compared(Comparison::NotDistinctFrom, Value::Null, Value::Null),
1017 Value::Boolean(true)
1018 );
1019 assert_eq!(
1020 compared(Comparison::NotDistinctFrom, Value::Integer(1), Value::Null),
1021 Value::Boolean(false)
1022 );
1023 assert_eq!(
1024 compared(Comparison::DistinctFrom, Value::Integer(1), Value::Null),
1025 Value::Boolean(true)
1026 );
1027 }
1028
1029 #[test]
1030 fn a_string_compares_by_bytes() {
1031 assert_eq!(
1032 compared(Comparison::Less, Value::Varchar("a".into()), Value::Varchar("b".into())),
1033 Value::Boolean(true)
1034 );
1035 assert_eq!(
1036 compared(Comparison::Less, Value::Varchar("Z".into()), Value::Varchar("a".into())),
1037 Value::Boolean(true)
1038 );
1039 }
1040
1041 #[test]
1044 fn two_nans_are_one_value_and_they_sort_above_the_numbers() {
1045 assert_eq!(
1046 compared(Comparison::Equal, Value::Double(f64::NAN), Value::Double(f64::NAN)),
1047 Value::Boolean(true)
1048 );
1049 assert_eq!(
1050 compared(Comparison::Greater, Value::Double(f64::NAN), Value::Double(1e300)),
1051 Value::Boolean(true)
1052 );
1053 }
1054
1055 #[test]
1056 fn zero_has_one_value_however_it_is_signed() {
1057 assert_eq!(
1058 compared(Comparison::Equal, Value::Double(0.0), Value::Double(-0.0)),
1059 Value::Boolean(true)
1060 );
1061 }
1062
1063 #[test]
1068 fn two_intervals_of_the_same_length_are_one_value() {
1069 let day = Value::Interval { months: 0, days: 1, micros: 0 };
1070 let hours = Value::Interval { months: 0, days: 0, micros: 86_400_000_000 };
1071 let month = Value::Interval { months: 1, days: 0, micros: 0 };
1072 let thirty = Value::Interval { months: 0, days: 30, micros: 0 };
1073 let long_day = Value::Interval { months: 0, days: 0, micros: 90_000_000_000 };
1074 assert_eq!(compared(Comparison::Equal, day.clone(), hours), Value::Boolean(true));
1075 assert_eq!(compared(Comparison::Equal, month, thirty), Value::Boolean(true));
1076 assert_eq!(compared(Comparison::Greater, long_day, day), Value::Boolean(true));
1077 }
1078
1079 #[test]
1080 fn a_number_compares_the_same_however_it_is_stored() {
1081 assert_eq!(
1082 compared(Comparison::Equal, Value::Integer(3), Value::BigInt(3)),
1083 Value::Boolean(true)
1084 );
1085 assert_eq!(
1086 compared(Comparison::Less, Value::Integer(3), Value::Double(3.5)),
1087 Value::Boolean(true)
1088 );
1089 }
1090
1091 #[test]
1092 fn nulls_go_where_the_query_asked_for_them() {
1093 assert_eq!(
1094 order_with_nulls(&Value::Null, &Value::Integer(1), true).expect("orders"),
1095 Ordering::Less
1096 );
1097 assert_eq!(
1098 order_with_nulls(&Value::Null, &Value::Integer(1), false).expect("orders"),
1099 Ordering::Greater
1100 );
1101 }
1102
1103 #[test]
1104 fn two_constant_vectors_cost_one_comparison() {
1105 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 512);
1106 let right = Vector::constant(LogicalType::Integer, Value::Integer(2), 512);
1107 let result = compare(Comparison::Less, &left, &right).expect("compares");
1108 assert_eq!(result.form(), Form::Constant);
1109 assert_eq!(result.value_at(500), Value::Boolean(true));
1110 }
1111
1112 #[test]
1113 fn a_comparison_of_two_vectors_is_one_answer_per_row() {
1114 let left = Vector::from_values(
1115 LogicalType::Integer,
1116 &[Value::Integer(1), Value::Integer(5), Value::Null],
1117 )
1118 .expect("three rows");
1119 let right = Vector::constant(LogicalType::Integer, Value::Integer(3), 3);
1120 let result = compare(Comparison::Greater, &left, &right).expect("compares");
1121 assert_eq!(result.value_at(0), Value::Boolean(false));
1122 assert_eq!(result.value_at(1), Value::Boolean(true));
1123 assert_eq!(result.value_at(2), Value::Null);
1124 }
1125
1126 #[test]
1127 fn two_vectors_of_different_lengths_are_caught() {
1128 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1129 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 5);
1130 let error = compare(Comparison::Equal, &left, &right).expect_err("ragged");
1131 assert!(error.message().contains("4 row vector"), "{error}");
1132 }
1133
1134 #[test]
1135 fn turning_a_comparison_around_is_what_the_other_side_would_have_said() {
1136 for op in EVERY {
1137 let left = Value::Integer(3);
1138 let right = Value::Integer(7);
1139 assert_eq!(
1140 compare_values(op, &left, &right).expect("compares"),
1141 compare_values(op.swapped(), &right, &left).expect("compares"),
1142 "{op:?}"
1143 );
1144 }
1145 }
1146
1147 #[test]
1150 fn every_specialized_path_agrees_with_the_row_at_a_time_path() {
1151 let mut rng = Rng(0x5eed_1234_9876_4321);
1152 let types: [LogicalType; 11] = [
1153 LogicalType::Boolean,
1154 LogicalType::TinyInt,
1155 LogicalType::SmallInt,
1156 LogicalType::Integer,
1157 LogicalType::BigInt,
1158 LogicalType::HugeInt,
1159 LogicalType::UInteger,
1160 LogicalType::Float,
1161 LogicalType::Double,
1162 LogicalType::Varchar,
1163 LogicalType::Interval,
1164 ];
1165 for ty in &types {
1166 for nulls in [0u64, 1, 3] {
1167 let len = 37;
1168 let make = |rng: &mut Rng| {
1169 let values: Vec<Value> = (0..len)
1170 .map(|_| {
1171 if nulls > 0 && rng.below(nulls + 1) == 0 {
1172 Value::Null
1173 } else {
1174 sample(ty, rng)
1175 }
1176 })
1177 .collect();
1178 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1179 };
1180 let left = make(&mut rng);
1181 let right = make(&mut rng);
1182 let literal = sample(ty, &mut rng);
1183 let constant = Vector::constant(ty.clone(), literal, len);
1184 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1185 let codes: Vec<u32> =
1186 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1187 let dictionary =
1188 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1189 let ends: Vec<u32> = (1..=left.len())
1192 .map(|run| ((run * len) / left.len()).max(run) as u32)
1193 .collect();
1194 let runs = Vector::runs(ends, left.clone()).expect("one value for each run");
1195
1196 for op in EVERY {
1197 agrees(op, &left, &right);
1198 agrees(op, &left, &constant);
1199 agrees(op, &constant, &left);
1200 agrees(op, &left, &null_constant);
1201 agrees(op, &null_constant, &left);
1202 agrees(op, &dictionary, &constant);
1203 agrees(op, &constant, &dictionary);
1204 agrees(op, &dictionary, &right);
1208 agrees(op, &right, &dictionary);
1209 agrees(op, &runs, &constant);
1213 agrees(op, &constant, &runs);
1214 agrees(op, &runs, &right);
1215 agrees(op, &right, &runs);
1216 }
1217 }
1218 }
1219 }
1220
1221 fn refined(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) -> Selection {
1223 let mut out = Vec::new();
1224 for &row in kept.indices() {
1225 let index = row as usize;
1226 let answer = compare_values(op, &left.value_at(index), &right.value_at(index))
1227 .expect("the oracle is only asked about types that compare");
1228 if is_true(&answer) {
1229 out.push(row);
1230 }
1231 }
1232 Selection::from_indices(out)
1233 }
1234
1235 fn threads(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) {
1236 let fast = refine(op, left, right, kept).expect("compares");
1237 assert_eq!(
1238 fast,
1239 refined(op, left, right, kept),
1240 "{op:?} on a {:?} against a {:?} over {} rows",
1241 left.form(),
1242 right.form(),
1243 kept.len()
1244 );
1245 }
1246
1247 #[test]
1251 fn a_threaded_comparison_keeps_what_the_row_at_a_time_path_keeps() {
1252 let mut rng = Rng(0x5eed_4321_1234_9876);
1253 let types = [LogicalType::Integer, LogicalType::Double, LogicalType::Varchar];
1254 for ty in &types {
1255 for nulls in [0u64, 1, 3] {
1256 let len = 37;
1257 let make = |rng: &mut Rng| {
1258 let values: Vec<Value> = (0..len)
1259 .map(|_| {
1260 if nulls > 0 && rng.below(nulls + 1) == 0 {
1261 Value::Null
1262 } else {
1263 sample(ty, rng)
1264 }
1265 })
1266 .collect();
1267 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1268 };
1269 let left = make(&mut rng);
1270 let right = make(&mut rng);
1271 let constant = Vector::constant(ty.clone(), sample(ty, &mut rng), len);
1272 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1273 let codes: Vec<u32> =
1274 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1275 let dictionary =
1276 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1277
1278 let selections = [
1282 Selection::identity(len),
1283 Selection::from_indices((0..len as u32).filter(|row| row % 3 == 0).collect()),
1284 Selection::from_indices(vec![2, 5, 6, 17, 36]),
1285 Selection::empty(),
1286 ];
1287 for op in EVERY {
1288 for kept in &selections {
1289 threads(op, &left, &right, kept);
1290 threads(op, &left, &constant, kept);
1291 threads(op, &constant, &left, kept);
1292 threads(op, &left, &null_constant, kept);
1293 threads(op, &null_constant, &left, kept);
1294 threads(op, &constant, &null_constant, kept);
1295 threads(op, &dictionary, &constant, kept);
1296 threads(op, &constant, &dictionary, kept);
1297 threads(op, &dictionary, &right, kept);
1298 threads(op, &right, &dictionary, kept);
1299 }
1300 }
1301 }
1302 }
1303 }
1304
1305 #[test]
1309 fn a_second_conjunct_reads_only_what_the_first_one_left() {
1310 let numbers: Vec<Value> = (0..64).map(|row| Value::Integer(row % 10)).collect();
1311 let column = Vector::from_values(LogicalType::Integer, &numbers).expect("a flat vector");
1312 let three = Vector::constant(LogicalType::Integer, Value::Integer(3), 64);
1313 let seven = Vector::constant(LogicalType::Integer, Value::Integer(7), 64);
1314
1315 let first = refine(Comparison::Greater, &column, &three, &Selection::identity(64))
1316 .expect("compares");
1317 let both = refine(Comparison::Less, &column, &seven, &first).expect("compares");
1318
1319 let expected: Vec<u32> = (0..64)
1320 .filter(|row| {
1321 let value = row % 10;
1322 value > 3 && value < 7
1323 })
1324 .collect();
1325 assert_eq!(both.indices(), expected.as_slice());
1326 assert!(both.len() < first.len(), "the second conjunct narrowed the selection");
1327 }
1328
1329 #[test]
1333 fn a_null_row_is_not_kept_by_an_ordinary_comparison_and_is_by_a_total_one() {
1334 let column = Vector::from_values(
1335 LogicalType::Integer,
1336 &[Value::Integer(1), Value::Null, Value::Integer(3), Value::Null],
1337 )
1338 .expect("four rows");
1339 let cut = Vector::constant(LogicalType::Integer, Value::Integer(2), 4);
1340 let all = Selection::identity(4);
1341 assert_eq!(
1342 refine(Comparison::Less, &column, &cut, &all).expect("compares").indices(),
1343 &[0]
1344 );
1345 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 4);
1347 assert_eq!(
1348 refine(Comparison::NotDistinctFrom, &column, &nulls, &all).expect("compares").indices(),
1349 &[1, 3]
1350 );
1351 }
1352
1353 #[test]
1354 fn a_selection_past_the_end_is_caught() {
1355 let column = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1356 let past = Selection::from_indices(vec![0, 4]);
1357 let error = refine(Comparison::Equal, &column, &column, &past).expect_err("out of range");
1358 assert!(error.message().contains("4 row vector"), "{error}");
1359 }
1360
1361 fn sample(ty: &LogicalType, rng: &mut Rng) -> Value {
1363 match ty {
1364 LogicalType::Boolean => Value::Boolean(rng.below(2) == 1),
1365 LogicalType::TinyInt => Value::TinyInt(rng.below(7) as i8 - 3),
1366 LogicalType::SmallInt => Value::SmallInt(rng.below(11) as i16 - 5),
1367 LogicalType::Integer => Value::Integer(rng.below(9) as i32 - 4),
1368 LogicalType::BigInt => Value::BigInt(rng.below(9) as i64 - 4),
1369 LogicalType::HugeInt => Value::HugeInt(i128::from(rng.below(9)) - 4),
1370 LogicalType::UInteger => Value::UInteger(rng.below(9) as u32),
1371 LogicalType::Float => Value::Float(match rng.below(5) {
1374 0 => f32::NAN,
1375 1 => -0.0,
1376 other => other as f32 - 2.0,
1377 }),
1378 LogicalType::Double => Value::Double(match rng.below(5) {
1379 0 => f64::NAN,
1380 1 => -0.0,
1381 other => other as f64 - 2.0,
1382 }),
1383 LogicalType::Interval => match rng.below(6) {
1387 0 => Value::Interval { months: 0, days: 1, micros: 0 },
1388 1 => Value::Interval { months: 0, days: 0, micros: 86_400_000_000 },
1389 2 => Value::Interval { months: 1, days: -29, micros: 86_400_000_000 },
1390 3 => Value::Interval { months: 1, days: 0, micros: 0 },
1391 4 => Value::Interval { months: 0, days: 0, micros: 90_000_000_000 },
1392 _ => Value::Interval { months: -1, days: 0, micros: 0 },
1393 },
1394 LogicalType::Varchar => Value::Varchar(
1397 match rng.below(6) {
1398 0 => "",
1399 1 => "ab",
1400 2 => "abc",
1401 3 => "abcdefghijkl",
1402 4 => "abcdefghijklm",
1403 _ => "abcdefghijklmnopqrstuvwxyz",
1404 }
1405 .to_owned(),
1406 ),
1407 other => panic!("the generator has no values for {other}"),
1408 }
1409 }
1410
1411 #[test]
1415 fn prefix_order_is_byte_order_whenever_the_prefixes_differ() {
1416 let words =
1417 ["", "a", "ab", "abc", "abcd", "abcde", "b", "abcdefghijklmnop", "abcdefghijklmnoq"];
1418 let mut column = StringColumn::new();
1419 for word in words {
1420 column.push(word);
1421 }
1422 for (i, one) in words.iter().enumerate() {
1423 for (j, other) in words.iter().enumerate() {
1424 assert_eq!(
1425 string_order(&column, i, &column, j),
1426 one.as_bytes().cmp(other.as_bytes()),
1427 "{one:?} against {other:?}"
1428 );
1429 }
1430 }
1431 }
1432
1433 #[test]
1436 fn a_dictionary_against_a_constant_reads_its_nulls_from_the_values() {
1437 let values = Vector::from_values(
1438 LogicalType::Integer,
1439 &[Value::Integer(1), Value::Null, Value::Integer(9)],
1440 )
1441 .expect("three values");
1442 let dictionary =
1443 Vector::dictionary(vec![0, 1, 2, 1, 0], values).expect("codes are in range");
1444 let constant = Vector::constant(LogicalType::Integer, Value::Integer(5), 5);
1445 let result = compare(Comparison::Less, &dictionary, &constant).expect("compares");
1446 assert_eq!(result.value_at(0), Value::Boolean(true));
1447 assert_eq!(result.value_at(1), Value::Null);
1448 assert_eq!(result.value_at(2), Value::Boolean(false));
1449 assert_eq!(result.value_at(3), Value::Null);
1450 assert_eq!(result.value_at(4), Value::Boolean(true));
1451 }
1452
1453 #[test]
1456 fn a_form_pair_with_no_loop_is_still_right_and_says_so() {
1457 let before = fallback::count(Kernel::Compare, Form::Sequence, Form::Flat);
1459 let sequence = Vector::sequence(10, 1, 4);
1460 let flat = Vector::from_values(
1461 LogicalType::BigInt,
1462 &[Value::BigInt(9), Value::BigInt(11), Value::BigInt(12), Value::Null],
1463 )
1464 .expect("four rows");
1465 let result = compare(Comparison::Less, &sequence, &flat).expect("compares");
1466 assert_eq!(result.value_at(0), Value::Boolean(false));
1467 assert_eq!(result.value_at(1), Value::Boolean(false));
1468 assert_eq!(result.value_at(2), Value::Boolean(false));
1469 assert_eq!(result.value_at(3), Value::Null);
1470 assert!(fallback::count(Kernel::Compare, Form::Sequence, Form::Flat) > before);
1471 }
1472
1473 #[test]
1483 fn a_second_level_of_codes_does_not_turn_the_loops_off() {
1484 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
1485 let values = Vector::from_values(
1486 LogicalType::Integer,
1487 &[Value::Integer(1), Value::Integer(5), Value::Integer(9)],
1488 )
1489 .expect("three rows");
1490 let once = Vector::dictionary(vec![2, 1, 0], values).expect("codes are in range");
1491 let twice = Vector::dictionary(vec![1, 2], once).expect("codes are in range");
1492 let cut = Vector::constant(LogicalType::Integer, Value::Integer(4), 2);
1493 let result = compare(Comparison::Greater, &twice, &cut).expect("compares");
1494 assert_eq!(result.value_at(0), Value::Boolean(true));
1495 assert_eq!(result.value_at(1), Value::Boolean(false));
1496 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
1497 }
1498
1499 #[test]
1503 fn a_side_that_is_entirely_null_answers_without_reading_the_other() {
1504 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 6);
1505 let flat = Vector::from_values(
1506 LogicalType::Integer,
1507 &[
1508 Value::Integer(1),
1509 Value::Integer(2),
1510 Value::Integer(3),
1511 Value::Integer(4),
1512 Value::Integer(5),
1513 Value::Integer(6),
1514 ],
1515 )
1516 .expect("six rows");
1517 agrees(Comparison::Less, &nulls, &flat);
1518 agrees(Comparison::Equal, &flat, &nulls);
1519 assert_eq!(
1520 compare(Comparison::Less, &nulls, &flat).expect("compares").validity(),
1521 &Validity::AllInvalid
1522 );
1523 }
1524
1525 #[test]
1528 fn an_empty_comparison_is_an_empty_answer() {
1529 let left = Vector::from_values(LogicalType::Integer, &[]).expect("no rows");
1530 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 0);
1531 let result = compare(Comparison::Equal, &left, &right).expect("compares");
1532 assert_eq!(result.len(), 0);
1533 }
1534
1535 fn words() -> Vector {
1538 Vector::from_values(
1539 LogicalType::Varchar,
1540 &[
1541 Value::Varchar("http://a".into()),
1542 Value::Varchar("http://b".into()),
1543 Value::Null,
1544 Value::Varchar("ab".into()),
1545 Value::Varchar("http://a".into()),
1546 Value::Varchar("z".into()),
1547 ],
1548 )
1549 .expect("six rows")
1550 }
1551
1552 #[test]
1558 fn a_literal_built_early_answers_what_one_built_here_answers() {
1559 let column = words();
1560 let value = Value::Varchar("http://b".into());
1561 let constant = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
1562 let held = Held::of(&LogicalType::Varchar, &value).expect("a varchar has a column");
1563 let kept = Selection::from_indices(vec![0, 1, 3, 5]);
1564 for op in [
1565 Comparison::Equal,
1566 Comparison::NotEqual,
1567 Comparison::Less,
1568 Comparison::LessOrEqual,
1569 Comparison::Greater,
1570 Comparison::GreaterOrEqual,
1571 Comparison::DistinctFrom,
1572 Comparison::NotDistinctFrom,
1573 ] {
1574 let prepared = compare_prepared(op, &column, &constant, Some(&held)).expect("compares");
1575 assert_eq!(prepared, compare(op, &column, &constant).expect("compares"), "{op:?}");
1576 let flipped = compare_prepared(op, &constant, &column, Some(&held)).expect("compares");
1578 assert_eq!(flipped, compare(op, &constant, &column).expect("compares"), "{op:?}");
1579 let refined =
1580 refine_prepared(op, &column, &constant, &kept, Some(&held)).expect("refines");
1581 assert_eq!(refined, refine(op, &column, &constant, &kept).expect("refines"), "{op:?}");
1582 }
1583 }
1584
1585 #[test]
1592 fn a_literal_built_for_another_value_is_ignored() {
1593 let column = words();
1594 let constant = Vector::constant(LogicalType::Varchar, Value::Varchar("z".into()), 6);
1595 let wrong = Held::of(&LogicalType::Varchar, &Value::Varchar("ab".into()))
1596 .expect("a varchar has a column");
1597 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&wrong))
1598 .expect("compares");
1599 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1600 let other = Held::of(&LogicalType::Integer, &Value::Integer(1)).expect("an integer column");
1603 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&other))
1604 .expect("compares");
1605 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1606 }
1607
1608 #[test]
1611 fn a_packed_column_against_a_constant_answers_what_the_oracle_answers() {
1612 let values: Vec<i32> = (0..64).map(|row| 1000 + (row * 37) % 500).collect();
1613 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1614 .expect("integers are an i32 layout");
1615 let packed = flat.bit_packed().expect("a five hundred wide range packs");
1616 assert_eq!(packed.form(), Form::BitPacked);
1617 for literal in [999, 1000, 1200, 1499, 1500, 2000] {
1618 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 64);
1619 for op in EVERY {
1620 agrees(op, &packed, &constant);
1621 agrees(op, &constant, &packed);
1622 }
1623 }
1624 }
1625
1626 #[test]
1630 fn a_packed_column_with_nulls_answers_what_the_oracle_answers() {
1631 let values: Vec<i32> = (0..32).map(|row| 40 + row * 3).collect();
1632 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1633 .expect("integers are an i32 layout")
1634 .with_validity(Validity::from_iter(32, |row| row % 5 != 0));
1635 let packed = flat.bit_packed().expect("packs");
1636 let constant = Vector::constant(LogicalType::Integer, Value::Integer(80), 32);
1637 for op in EVERY {
1638 agrees(op, &packed, &constant);
1639 }
1640 }
1641
1642 #[test]
1645 fn a_literal_outside_the_packed_range_answers_the_whole_vector_at_once() {
1646 let before = fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant);
1647 let values: Vec<i32> = (0..16).map(|row| 500 + row).collect();
1648 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1649 .expect("integers are an i32 layout");
1650 let packed = flat.bit_packed().expect("packs");
1651 let literals = [-1, 0, 499, 516, 100_000];
1652 for literal in literals {
1653 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 16);
1654 for op in EVERY {
1655 agrees(op, &packed, &constant);
1656 }
1657 }
1658 let total = EVERY.iter().filter(|op| op.is_total()).count();
1663 assert_eq!(
1664 fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant) - before,
1665 (literals.len() * total) as u64,
1666 "only the two total comparisons fall through"
1667 );
1668 }
1669
1670 #[test]
1673 fn refining_a_selection_over_a_packed_column_keeps_the_same_rows() {
1674 let values: Vec<i32> = (0..64).map(|row| 200 + (row * 11) % 128).collect();
1675 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.clone().into()))
1676 .expect("integers are an i32 layout");
1677 let packed = flat.bit_packed().expect("packs");
1678 let kept = Selection::from_predicate(64, |row| row % 3 == 0);
1679 let constant = Vector::constant(LogicalType::Integer, Value::Integer(260), 64);
1680 let packed_rows = refine(Comparison::Greater, &packed, &constant, &kept).expect("refines");
1681 let flat_rows = refine(Comparison::Greater, &flat, &constant, &kept).expect("refines");
1682 assert_eq!(packed_rows.indices(), flat_rows.indices());
1683 assert!(!packed_rows.is_empty(), "the literal is inside the range");
1684 }
1685
1686 fn urls(count: usize) -> Vector {
1689 let mut rng = Rng(0x5eed_1234);
1690 let values: Vec<Value> = (0..count)
1691 .map(|_| {
1692 let host = rng.below(6);
1693 let path = rng.below(40);
1694 Value::Varchar(format!("http://example{host}.test/a/rather/long/path/{path}"))
1695 })
1696 .collect();
1697 Vector::from_values(LogicalType::Varchar, &values).expect("strings")
1698 }
1699
1700 #[test]
1701 fn a_string_view_column_against_a_literal_answers_what_the_oracle_answers() {
1702 let before = fallback::count(Kernel::Compare, Form::StringView, Form::Constant);
1703 let shared = urls(64).shared_text().expect("shares");
1704 assert_eq!(shared.form(), Form::StringView);
1705 let literals = ["http://example3.test/a/rather/long/path/7", "a", "zzz", ""];
1706 for literal in literals {
1707 let value = Value::Varchar(literal.to_owned());
1708 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1709 for op in EVERY {
1710 agrees(op, &shared, &constant);
1711 agrees(op, &constant, &shared);
1712 }
1713 }
1714 assert_eq!(
1715 fallback::count(Kernel::Compare, Form::StringView, Form::Constant),
1716 before,
1717 "the form has a loop of its own for every comparison"
1718 );
1719 }
1720
1721 #[test]
1722 fn a_string_view_column_against_another_one_answers_what_the_oracle_answers() {
1723 let shared = urls(48).shared_text().expect("shares");
1724 let other = urls(48).shared_text().expect("shares");
1725 let flat = urls(48);
1726 for op in EVERY {
1727 agrees(op, &shared, &other);
1728 agrees(op, &shared, &flat);
1729 agrees(op, &flat, &shared);
1730 }
1731 }
1732
1733 #[test]
1734 fn the_nulls_of_a_string_view_column_are_the_nulls_the_oracle_sees() {
1735 let shared = urls(32)
1736 .with_validity(Validity::from_iter(32, |row| row % 4 != 1))
1737 .shared_text()
1738 .expect("shares");
1739 let constant =
1740 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 32);
1741 for op in EVERY {
1742 agrees(op, &shared, &constant);
1743 }
1744 }
1745
1746 #[test]
1747 fn a_compressed_column_against_a_literal_answers_what_the_oracle_answers() {
1748 let before = fallback::count(Kernel::Compare, Form::Fsst, Form::Constant);
1749 let flat = urls(64);
1750 let coded = flat.clone().compressed().expect("compresses");
1751 assert_eq!(coded.form(), Form::Fsst);
1752 let present = match coded.value_at(9) {
1753 Value::Varchar(text) => text,
1754 other => panic!("a string column reads back strings, not {other:?}"),
1755 };
1756 for literal in [present.as_str(), "http://example3.test/nothing/like/it", ""] {
1757 let value = Value::Varchar(literal.to_owned());
1758 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1759 for op in EVERY {
1760 agrees(op, &coded, &constant);
1761 agrees(op, &constant, &coded);
1762 }
1763 }
1764 let ordered = EVERY.len() - 2;
1768 assert_eq!(
1769 fallback::count(Kernel::Compare, Form::Fsst, Form::Constant) - before,
1770 (3 * ordered) as u64,
1771 "only the comparisons that need an order fall through"
1772 );
1773 }
1774
1775 #[test]
1778 fn every_row_of_a_compressed_column_matches_itself_and_nothing_else() {
1779 let flat = urls(48);
1780 let coded = flat.clone().compressed().expect("compresses");
1781 for row in 0..48 {
1782 let constant = Vector::constant(LogicalType::Varchar, flat.value_at(row), 48);
1783 let equal = compare(Comparison::Equal, &coded, &constant).expect("compares");
1784 for other in 0..48 {
1785 let want = flat.value_at(other) == flat.value_at(row);
1786 assert_eq!(
1787 equal.value_at(other),
1788 Value::Boolean(want),
1789 "row {row} against {other}"
1790 );
1791 }
1792 }
1793 }
1794
1795 #[test]
1796 fn the_nulls_of_a_compressed_column_are_the_nulls_the_oracle_sees() {
1797 let coded = urls(32)
1798 .with_validity(Validity::from_iter(32, |row| row % 3 != 0))
1799 .compressed()
1800 .expect("compresses");
1801 let value = coded.value_at(1);
1802 let constant = Vector::constant(LogicalType::Varchar, value, 32);
1803 for op in EVERY {
1804 agrees(op, &coded, &constant);
1805 }
1806 }
1807
1808 #[test]
1812 fn a_filter_over_either_string_form_keeps_the_same_rows() {
1813 let flat = urls(96);
1814 let shared = flat.clone().shared_text().expect("shares");
1815 let constant =
1816 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 96);
1817 let kept = Selection::from_predicate(96, |row| row % 5 != 0);
1818 for op in EVERY {
1819 let over_flat = refine(op, &flat, &constant, &kept).expect("refines");
1820 let over_shared = refine(op, &shared, &constant, &kept).expect("refines");
1821 assert_eq!(over_shared.indices(), over_flat.indices(), "{op:?}");
1822 }
1823 }
1824}