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.try_value_at(0)?, &right.try_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) = external_text_literal(op, left, right, len, identity, held)? {
180 let validity = left_valid.and(&right_valid, len);
181 return boolean(blank_the_nulls(answers, &validity), validity, len);
182 }
183 if let Some(answers) =
184 specialized(op, left, right, &left_valid, &right_valid, len, identity, held)
185 {
186 let validity =
187 if op.is_total() { Validity::AllValid } else { left_valid.and(&right_valid, len) };
188 return boolean(blank_the_nulls(answers, &validity), validity, len);
189 }
190
191 fallback::record(Kernel::Compare, left.form(), right.form());
192 let mut values = Vec::with_capacity(len);
193 for index in 0..len {
196 values.push(compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?);
197 }
198 Vector::from_values(LogicalType::Boolean, &values)
199}
200
201pub fn refine(
219 op: Comparison,
220 left: &Vector,
221 right: &Vector,
222 kept: &Selection,
223) -> Result<Selection> {
224 refine_prepared(op, left, right, kept, None)
225}
226
227pub fn refine_prepared(
237 op: Comparison,
238 left: &Vector,
239 right: &Vector,
240 kept: &Selection,
241 held: Option<&Held>,
242) -> Result<Selection> {
243 if left.len() != right.len() {
244 return Err(Error::internal(format!(
245 "a comparison of a {} row vector with a {} row one",
246 left.len(),
247 right.len()
248 )));
249 }
250 let len = left.len();
251 if kept.indices().iter().any(|&row| row as usize >= len) {
255 return Err(Error::internal(format!("a selection past the end of a {len} row vector")));
256 }
257 if kept.is_empty() {
258 return Ok(Selection::empty());
259 }
260 if left.form() == Form::Constant && right.form() == Form::Constant {
261 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
262 return Ok(if is_true(&single) { kept.clone() } else { Selection::empty() });
263 }
264
265 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
266 if !op.is_total() && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
267 {
268 return Ok(Selection::empty());
269 }
270
271 let rows = kept.indices();
272 let map = |slot: usize| rows[slot] as usize;
273 if let Some(answers) = external_text_literal(op, left, right, kept.len(), map, held)? {
274 return Ok(narrowed(&answers, rows, |slot| {
275 let row = rows[slot] as usize;
276 left_valid.is_valid(row) && right_valid.is_valid(row)
277 }));
278 }
279 if let Some(answers) =
280 specialized(op, left, right, &left_valid, &right_valid, kept.len(), map, held)
281 {
282 if op.is_total() || (left_valid == Validity::AllValid && right_valid == Validity::AllValid)
285 {
286 return Ok(narrowed(&answers, rows, |_| true));
287 }
288 return Ok(narrowed(&answers, rows, |slot| {
292 let row = rows[slot] as usize;
293 left_valid.is_valid(row) && right_valid.is_valid(row)
294 }));
295 }
296
297 fallback::record(Kernel::Compare, left.form(), right.form());
298 let mut out = Vec::with_capacity(kept.len());
299 for &row in rows {
302 let index = row as usize;
303 if is_true(&compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?) {
304 out.push(row);
305 }
306 }
307 Ok(Selection::from_indices(out))
308}
309
310fn external_text_literal<M>(
317 op: Comparison,
318 left: &Vector,
319 right: &Vector,
320 len: usize,
321 map: M,
322 held: Option<&Held>,
323) -> Result<Option<Vec<bool>>>
324where
325 M: Fn(usize) -> usize + Copy,
326{
327 if !matches!(op, Comparison::Equal | Comparison::NotEqual)
328 || left.logical_type() != &LogicalType::Varchar
329 || right.logical_type() != &LogicalType::Varchar
330 {
331 return Ok(None);
332 }
333 let (column, literal, swapped) = match (left.constant_value(), right.constant_value()) {
334 (None, Some(Value::Varchar(literal))) if left.positions().is_some() => {
335 (left, literal.as_bytes(), false)
336 }
337 (Some(Value::Varchar(literal)), None) if right.positions().is_some() => {
338 (right, literal.as_bytes(), true)
339 }
340 _ => return Ok(None),
341 };
342 let same = if swapped { op.swapped() } else { op } == Comparison::Equal;
343 if let Some(held) = held.filter(|held| held.text() == Some(literal)) {
347 let decide = |dictionary: &Vector, code: usize| -> Result<bool> {
348 let found = if literal.is_empty() {
349 dictionary.try_bytes_len_at(code)?.is_some_and(|length| length == 0)
350 } else {
351 dictionary.try_bytes_at(code)?.is_some_and(|bytes| bytes == literal)
352 };
353 Ok(found)
354 };
355 if let Some(answers) = held.peel().answer(column, len, map, decide) {
356 let mut answers = answers?;
357 if !same {
358 for answer in &mut answers {
359 *answer = !*answer;
360 }
361 }
362 return Ok(Some(answers));
363 }
364 }
365 let mut answers = Vec::with_capacity(len);
366 for slot in 0..len {
367 let row = map(slot);
368 let equal = if literal.is_empty() {
369 column.try_bytes_len_at(row)?.is_some_and(|length| length == 0)
370 } else {
371 column.try_bytes_at(row)?.is_some_and(|bytes| bytes == literal)
372 };
373 answers.push(equal == same);
374 }
375 Ok(Some(answers))
376}
377
378fn narrowed<L: Fn(usize) -> bool>(answers: &[bool], rows: &[u32], live: L) -> Selection {
385 let mut out = vec![0_u32; answers.len()];
386 let mut count = 0;
387 for (slot, &answer) in answers.iter().enumerate() {
388 out[count] = rows[slot];
389 count += usize::from(answer & live(slot));
391 }
392 out.truncate(count);
393 Selection::from_indices(out)
394}
395
396fn boolean(answers: Vec<bool>, validity: Validity, len: usize) -> Result<Vector> {
398 let validity = if len == 0 { Validity::AllValid } else { validity.normalize(len) };
402 Ok(Vector::flat(LogicalType::Boolean, Data::Bool(answers.into()))?.with_validity(validity))
403}
404
405fn blank_the_nulls(mut answers: Vec<bool>, validity: &Validity) -> Vec<bool> {
413 if let Validity::Mask(mask) = validity {
414 for (index, answer) in answers.iter_mut().enumerate() {
415 if !mask.get(index) {
416 *answer = false;
417 }
418 }
419 }
420 answers
421}
422
423#[expect(
435 clippy::too_many_arguments,
436 reason = "two sides, two validities, the operator, the length, the index mapping and the \
437 literal that was built early, all of which the branches below need"
438)]
439fn specialized<M>(
440 op: Comparison,
441 left: &Vector,
442 right: &Vector,
443 left_valid: &Validity,
444 right_valid: &Validity,
445 len: usize,
446 map: M,
447 held: Option<&Held>,
448) -> Option<Vec<bool>>
449where
450 M: Fn(usize) -> usize + Copy,
451{
452 if left.logical_type() != right.logical_type() {
456 return None;
457 }
458
459 if let (Some(one), Some(other)) = (left.data(), right.data()) {
460 return dispatch(op, len, one, map, other, map, left_valid, right_valid, map);
461 }
462 if !op.is_total() {
468 if let (Some(packed), Some(value)) = (left.packed_parts(), right.constant_value()) {
469 let wanted = exact(held, left.logical_type(), value)?;
470 return Some(packed_against(op, &packed, wanted, len, map));
471 }
472 if let (Some(value), Some(packed)) = (left.constant_value(), right.packed_parts()) {
473 let wanted = exact(held, right.logical_type(), value)?;
474 return Some(packed_against(op.swapped(), &packed, wanted, len, map));
475 }
476 }
477 if let (Some(one), Some(value)) = (left.data(), right.constant_value()) {
478 let column = readied(held, left.logical_type(), value)?;
479 let other = column.data()?;
480 return dispatch(op, len, one, map, other, first, left_valid, right_valid, map);
481 }
482 if let (Some(value), Some(other)) = (left.constant_value(), right.data()) {
483 let column = readied(held, right.logical_type(), value)?;
485 let one = column.data()?;
486 return dispatch(op.swapped(), len, other, map, one, first, right_valid, left_valid, map);
487 }
488 if matches!(op, Comparison::Equal | Comparison::NotEqual) {
493 if let (Some(coded), Some(value)) = (left.coded_parts(), right.constant_value()) {
494 let wanted = encoded(&coded, held, left.logical_type(), value)?;
495 return Some(coded_against(op, &coded, &wanted, len, map));
496 }
497 if let (Some(value), Some(coded)) = (left.constant_value(), right.coded_parts()) {
498 let wanted = encoded(&coded, held, right.logical_type(), value)?;
499 return Some(coded_against(op, &coded, &wanted, len, map));
500 }
501 }
502 if let (Some((one, one_arena)), Some((other, other_arena))) =
508 (left.text_parts(), right.text_parts())
509 {
510 return Some(sweep(
511 op,
512 len,
513 |index| view_order(one.get(map(index)), one_arena, other.get(map(index)), other_arena),
514 left_valid,
515 right_valid,
516 map,
517 ));
518 }
519 if let (Some((one, one_arena)), Some(value)) = (left.text_parts(), right.constant_value()) {
523 let column = readied(held, left.logical_type(), value)?;
524 let (other, other_arena) = column.text_parts()?;
525 let wanted = other.first();
526 return Some(sweep(
527 op,
528 len,
529 |index| view_order(one.get(map(index)), one_arena, wanted, other_arena),
530 left_valid,
531 right_valid,
532 map,
533 ));
534 }
535 if let (Some(value), Some((other, other_arena))) = (left.constant_value(), right.text_parts()) {
536 let column = readied(held, right.logical_type(), value)?;
538 let (one, one_arena) = column.text_parts()?;
539 let wanted = one.first();
540 return Some(sweep(
541 op.swapped(),
542 len,
543 |index| view_order(other.get(map(index)), other_arena, wanted, one_arena),
544 right_valid,
545 left_valid,
546 map,
547 ));
548 }
549 if let (Some((codes, values)), Some(value)) = (left.positions(), right.constant_value()) {
550 let one = values.data()?;
551 let column = readied(held, left.logical_type(), value)?;
552 let other = column.data()?;
553 let at = |index: usize| codes[map(index)] as usize;
554 return dispatch(op, len, one, at, other, first, left_valid, right_valid, map);
555 }
556 if let (Some(value), Some((codes, values))) = (left.constant_value(), right.positions()) {
557 let other = values.data()?;
558 let column = readied(held, right.logical_type(), value)?;
559 let one = column.data()?;
560 let at = |index: usize| codes[map(index)] as usize;
561 return dispatch(op.swapped(), len, other, at, one, first, right_valid, left_valid, map);
562 }
563 if let (Some((codes, values)), Some(other)) = (left.positions(), right.data()) {
569 let one = values.data()?;
570 let at = |index: usize| codes[map(index)] as usize;
571 return dispatch(op, len, one, at, other, map, left_valid, right_valid, map);
572 }
573 if let (Some(one), Some((codes, values))) = (left.data(), right.positions()) {
574 let other = values.data()?;
575 let at = |index: usize| codes[map(index)] as usize;
576 return dispatch(op.swapped(), len, other, at, one, map, right_valid, left_valid, map);
577 }
578 None
579}
580
581fn exact(held: Option<&Held>, ty: &LogicalType, value: &Value) -> Option<i128> {
588 let column = readied(held, ty, value)?;
589 let data = column.data()?;
590 data.signed_at(0).or_else(|| data.unsigned_at(0).and_then(|value| i128::try_from(value).ok()))
591}
592
593fn encoded(
599 coded: &Coded<'_>,
600 held: Option<&Held>,
601 ty: &LogicalType,
602 value: &Value,
603) -> Option<Vec<u8>> {
604 let column = readied(held, ty, value)?;
605 let (views, arena) = column.text_parts()?;
606 Some(coded.encode(views.first()?.bytes_in(arena)?))
607}
608
609fn coded_against<M>(
615 op: Comparison,
616 coded: &Coded<'_>,
617 wanted: &[u8],
618 len: usize,
619 map: M,
620) -> Vec<bool>
621where
622 M: Fn(usize) -> usize + Copy,
623{
624 let same = op == Comparison::Equal;
625 let mut answers = Vec::with_capacity(len);
626 for row in 0..len {
627 answers.push((coded.row(map(row)) == Some(wanted)) == same);
628 }
629 answers
630}
631
632fn packed_against<M>(
638 op: Comparison,
639 packed: &Packed<'_>,
640 wanted: i128,
641 len: usize,
642 map: M,
643) -> Vec<bool>
644where
645 M: Fn(usize) -> usize + Copy,
646{
647 let Some(code) = packed.code_of(wanted) else {
648 let above = wanted > packed.ceiling();
651 let same = match op {
652 Comparison::Equal | Comparison::NotDistinctFrom => false,
653 Comparison::NotEqual | Comparison::DistinctFrom => true,
654 Comparison::Less | Comparison::LessOrEqual => above,
655 Comparison::Greater | Comparison::GreaterOrEqual => !above,
656 };
657 return vec![same; len];
658 };
659 let test: fn(u64, u64) -> bool = match op {
662 Comparison::Equal | Comparison::NotDistinctFrom => |found, want| found == want,
663 Comparison::NotEqual | Comparison::DistinctFrom => |found, want| found != want,
664 Comparison::Less => |found, want| found < want,
665 Comparison::LessOrEqual => |found, want| found <= want,
666 Comparison::Greater => |found, want| found > want,
667 Comparison::GreaterOrEqual => |found, want| found >= want,
668 };
669 let mut answers = Vec::with_capacity(len);
670 for row in 0..len {
671 answers.push(test(packed.code(map(row)), code));
672 }
673 answers
674}
675
676#[expect(
682 clippy::too_many_arguments,
683 reason = "two sides with an index each, the operator, the length and two validities, all of \
684 which the loop needs and none of which is worth a struct that exists for one call"
685)]
686fn dispatch<L, R, V>(
687 op: Comparison,
688 len: usize,
689 left: &Data,
690 at_left: L,
691 right: &Data,
692 at_right: R,
693 left_valid: &Validity,
694 right_valid: &Validity,
695 at_valid: V,
696) -> Option<Vec<bool>>
697where
698 L: Fn(usize) -> usize,
699 R: Fn(usize) -> usize,
700 V: Fn(usize) -> usize,
701{
702 macro_rules! layouts {
703 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
704 match (left, right) {
705 $(
706 (Data::$variant(one), Data::$variant(other)) => Some(sweep(
707 op,
708 len,
709 |index| one[at_left(index)].cmp(&other[at_right(index)]),
710 left_valid,
711 right_valid,
712 &at_valid,
713 )),
714 )+
715 (Data::Float32(one), Data::Float32(other)) => Some(sweep(
718 op,
719 len,
720 |index| {
721 float_order(
722 f64::from(one[at_left(index)]),
723 f64::from(other[at_right(index)]),
724 )
725 },
726 left_valid,
727 right_valid,
728 &at_valid,
729 )),
730 (Data::Float64(one), Data::Float64(other)) => Some(sweep(
731 op,
732 len,
733 |index| float_order(one[at_left(index)], other[at_right(index)]),
734 left_valid,
735 right_valid,
736 &at_valid,
737 )),
738 (Data::Interval(one), Data::Interval(other)) => Some(sweep(
741 op,
742 len,
743 |index| {
744 let (months, days, micros) = one[at_left(index)];
745 let (bm, bd, bu) = other[at_right(index)];
746 interval_micros(months, days, micros).cmp(&interval_micros(bm, bd, bu))
747 },
748 left_valid,
749 right_valid,
750 &at_valid,
751 )),
752 (Data::Varlen(one), Data::Varlen(other)) => Some(sweep(
753 op,
754 len,
755 |index| string_order(one, at_left(index), other, at_right(index)),
756 left_valid,
757 right_valid,
758 &at_valid,
759 )),
760 _ => None,
761 }
762 };
763 }
764 rudb_vector::for_each_layout!(ordered, layouts)
765}
766
767fn readied<'a>(held: Option<&'a Held>, ty: &LogicalType, value: &Value) -> Option<Cow<'a, Vector>> {
773 match held {
774 Some(held) if held.matches(ty, value) => Some(Cow::Borrowed(held.single())),
775 _ => Some(Cow::Owned(single(ty, value)?)),
776 }
777}
778
779fn string_order(
787 left: &StringColumn,
788 at_left: usize,
789 right: &StringColumn,
790 at_right: usize,
791) -> Ordering {
792 view_order(left.views().get(at_left), left.arena(), right.views().get(at_right), right.arena())
793}
794
795fn view_order(
801 one: Option<&StringView>,
802 one_arena: &[u8],
803 other: Option<&StringView>,
804 other_arena: &[u8],
805) -> Ordering {
806 let (Some(one), Some(other)) = (one, other) else {
807 return Ordering::Equal;
808 };
809 let (prefix, against) = (one.prefix(), other.prefix());
810 if prefix != against {
811 return prefix.cmp(&against);
812 }
813 let bytes = one.bytes_in(one_arena).unwrap_or_default();
818 let against_bytes = other.bytes_in(other_arena).unwrap_or_default();
819 bytes.cmp(against_bytes)
820}
821
822fn sweep<O, V>(
828 op: Comparison,
829 len: usize,
830 order_at: O,
831 left_valid: &Validity,
832 right_valid: &Validity,
833 at_valid: V,
834) -> Vec<bool>
835where
836 O: Fn(usize) -> Ordering,
837 V: Fn(usize) -> usize,
838{
839 let mut answers = vec![false; len];
840 match op {
841 Comparison::Equal => fill(&mut answers, order_at, |o| o == Ordering::Equal),
842 Comparison::NotEqual => fill(&mut answers, order_at, |o| o != Ordering::Equal),
843 Comparison::Less => fill(&mut answers, order_at, |o| o == Ordering::Less),
844 Comparison::LessOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Greater),
845 Comparison::Greater => fill(&mut answers, order_at, |o| o == Ordering::Greater),
846 Comparison::GreaterOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Less),
847 Comparison::DistinctFrom => {
848 total(&mut answers, order_at, left_valid, right_valid, at_valid);
849 for answer in &mut answers {
850 *answer = !*answer;
851 }
852 }
853 Comparison::NotDistinctFrom => {
854 total(&mut answers, order_at, left_valid, right_valid, at_valid);
855 }
856 }
857 answers
858}
859
860#[inline]
862fn fill<O, H>(answers: &mut [bool], order_at: O, held: H)
863where
864 O: Fn(usize) -> Ordering,
865 H: Fn(Ordering) -> bool,
866{
867 for (index, answer) in answers.iter_mut().enumerate() {
868 *answer = held(order_at(index));
869 }
870}
871
872fn total<O, V>(
879 answers: &mut [bool],
880 order_at: O,
881 left_valid: &Validity,
882 right_valid: &Validity,
883 at_valid: V,
884) where
885 O: Fn(usize) -> Ordering,
886 V: Fn(usize) -> usize,
887{
888 if *left_valid == Validity::AllValid && *right_valid == Validity::AllValid {
889 fill(answers, order_at, |o| o == Ordering::Equal);
890 return;
891 }
892 for (index, answer) in answers.iter_mut().enumerate() {
893 let row = at_valid(index);
894 *answer = match (left_valid.is_valid(row), right_valid.is_valid(row)) {
895 (true, true) => order_at(index) == Ordering::Equal,
896 (false, false) => true,
897 _ => false,
898 };
899 }
900}
901
902pub fn compare_values(op: Comparison, left: &Value, right: &Value) -> Result<Value> {
908 if op.is_total() {
909 let same = match (left.is_null(), right.is_null()) {
910 (true, true) => true,
911 (true, false) | (false, true) => false,
912 (false, false) => order(left, right)? == Ordering::Equal,
913 };
914 return Ok(Value::Boolean(match op {
915 Comparison::NotDistinctFrom => same,
916 _ => !same,
917 }));
918 }
919 if left.is_null() || right.is_null() {
920 return Ok(Value::Null);
921 }
922 let ordering = order(left, right)?;
923 let held = match op {
924 Comparison::Equal => ordering == Ordering::Equal,
925 Comparison::NotEqual => ordering != Ordering::Equal,
926 Comparison::Less => ordering == Ordering::Less,
927 Comparison::LessOrEqual => ordering != Ordering::Greater,
928 Comparison::Greater => ordering == Ordering::Greater,
929 Comparison::GreaterOrEqual => ordering != Ordering::Less,
930 Comparison::DistinctFrom | Comparison::NotDistinctFrom => {
931 return Err(Error::internal("a total comparison reached the ordered path"));
932 }
933 };
934 Ok(Value::Boolean(held))
935}
936
937pub fn order(left: &Value, right: &Value) -> Result<Ordering> {
948 match (left, right) {
949 (Value::Null, _) | (_, Value::Null) => {
950 Err(Error::internal("a null reached the ordering path"))
951 }
952 (Value::Boolean(a), Value::Boolean(b)) => Ok(a.cmp(b)),
953 (Value::Varchar(a), Value::Varchar(b)) => Ok(a.as_bytes().cmp(b.as_bytes())),
954 (Value::Blob(a), Value::Blob(b)) => Ok(a.cmp(b)),
955 (Value::Date(a), Value::Date(b)) => Ok(a.cmp(b)),
956 (Value::Time(a), Value::Time(b))
959 | (Value::TimeTz(a), Value::TimeTz(b))
960 | (Value::Timestamp(a), Value::Timestamp(b))
961 | (Value::TimestampTz(a), Value::TimestampTz(b)) => Ok(a.cmp(b)),
962 (
963 Value::Interval { months: am, days: ad, micros: au },
964 Value::Interval { months: bm, days: bd, micros: bu },
965 ) => Ok(interval_micros(*am, *ad, *au).cmp(&interval_micros(*bm, *bd, *bu))),
966 _ => numeric_order(left, right),
967 }
968}
969
970fn numeric_order(left: &Value, right: &Value) -> Result<Ordering> {
972 if let (Some(a), Some(b)) = (integral(left), integral(right)) {
973 return Ok(a.cmp(&b));
974 }
975 if let (
976 Value::Decimal { unscaled: a, scale: sa, .. },
977 Value::Decimal { unscaled: b, scale: sb, .. },
978 ) = (left, right)
979 {
980 if sa == sb {
981 return Ok(a.cmp(b));
982 }
983 }
984 match (approximate(left), approximate(right)) {
985 (Some(a), Some(b)) => Ok(float_order(a, b)),
986 _ => Err(Error::not_implemented(format!(
987 "comparing {} with {}",
988 left.logical_type(),
989 right.logical_type()
990 ))),
991 }
992}
993
994fn float_order(left: f64, right: f64) -> Ordering {
996 if left == right {
997 return Ordering::Equal;
998 }
999 match (left.is_nan(), right.is_nan()) {
1000 (true, true) => Ordering::Equal,
1001 (true, false) => Ordering::Greater,
1002 (false, true) => Ordering::Less,
1003 (false, false) => left.partial_cmp(&right).unwrap_or(Ordering::Equal),
1004 }
1005}
1006
1007pub fn order_with_nulls(left: &Value, right: &Value, nulls_first: bool) -> Result<Ordering> {
1016 match (left.is_null(), right.is_null()) {
1017 (true, true) => Ok(Ordering::Equal),
1018 (true, false) => Ok(if nulls_first { Ordering::Less } else { Ordering::Greater }),
1019 (false, true) => Ok(if nulls_first { Ordering::Greater } else { Ordering::Less }),
1020 (false, false) => order(left, right),
1021 }
1022}
1023
1024#[cfg(test)]
1025mod tests {
1026 use super::*;
1027
1028 fn compared(op: Comparison, left: Value, right: Value) -> Value {
1029 compare_values(op, &left, &right).expect("these types compare")
1030 }
1031
1032 const EVERY: [Comparison; 8] = [
1034 Comparison::Equal,
1035 Comparison::NotEqual,
1036 Comparison::Less,
1037 Comparison::LessOrEqual,
1038 Comparison::Greater,
1039 Comparison::GreaterOrEqual,
1040 Comparison::DistinctFrom,
1041 Comparison::NotDistinctFrom,
1042 ];
1043
1044 fn oracle(op: Comparison, left: &Vector, right: &Vector) -> Vector {
1050 let values: Vec<Value> = (0..left.len())
1051 .map(|index| {
1052 compare_values(op, &left.value_at(index), &right.value_at(index))
1053 .expect("the oracle is only asked about types that compare")
1054 })
1055 .collect();
1056 Vector::from_values(LogicalType::Boolean, &values).expect("booleans")
1057 }
1058
1059 fn agrees(op: Comparison, left: &Vector, right: &Vector) {
1063 let fast = compare(op, left, right).expect("compares");
1064 let slow = oracle(op, left, right);
1065 assert_eq!(fast, slow, "{op:?} on a {:?} against a {:?}", left.form(), right.form());
1066 }
1067
1068 struct Rng(u64);
1071
1072 impl Rng {
1073 fn next(&mut self) -> u64 {
1074 self.0 ^= self.0 << 13;
1075 self.0 ^= self.0 >> 7;
1076 self.0 ^= self.0 << 17;
1077 self.0
1078 }
1079
1080 fn below(&mut self, bound: u64) -> u64 {
1081 self.next() % bound
1082 }
1083 }
1084
1085 #[test]
1086 fn an_ordinary_comparison_is_null_when_either_side_is() {
1087 assert_eq!(compared(Comparison::Equal, Value::Integer(1), Value::Null), Value::Null);
1088 assert_eq!(compared(Comparison::Less, Value::Null, Value::Integer(1)), Value::Null);
1089 }
1090
1091 #[test]
1092 fn a_total_comparison_is_never_null() {
1093 assert_eq!(
1094 compared(Comparison::NotDistinctFrom, Value::Null, Value::Null),
1095 Value::Boolean(true)
1096 );
1097 assert_eq!(
1098 compared(Comparison::NotDistinctFrom, Value::Integer(1), Value::Null),
1099 Value::Boolean(false)
1100 );
1101 assert_eq!(
1102 compared(Comparison::DistinctFrom, Value::Integer(1), Value::Null),
1103 Value::Boolean(true)
1104 );
1105 }
1106
1107 #[test]
1108 fn a_string_compares_by_bytes() {
1109 assert_eq!(
1110 compared(Comparison::Less, Value::Varchar("a".into()), Value::Varchar("b".into())),
1111 Value::Boolean(true)
1112 );
1113 assert_eq!(
1114 compared(Comparison::Less, Value::Varchar("Z".into()), Value::Varchar("a".into())),
1115 Value::Boolean(true)
1116 );
1117 }
1118
1119 #[test]
1122 fn two_nans_are_one_value_and_they_sort_above_the_numbers() {
1123 assert_eq!(
1124 compared(Comparison::Equal, Value::Double(f64::NAN), Value::Double(f64::NAN)),
1125 Value::Boolean(true)
1126 );
1127 assert_eq!(
1128 compared(Comparison::Greater, Value::Double(f64::NAN), Value::Double(1e300)),
1129 Value::Boolean(true)
1130 );
1131 }
1132
1133 #[test]
1134 fn zero_has_one_value_however_it_is_signed() {
1135 assert_eq!(
1136 compared(Comparison::Equal, Value::Double(0.0), Value::Double(-0.0)),
1137 Value::Boolean(true)
1138 );
1139 }
1140
1141 #[test]
1146 fn two_intervals_of_the_same_length_are_one_value() {
1147 let day = Value::Interval { months: 0, days: 1, micros: 0 };
1148 let hours = Value::Interval { months: 0, days: 0, micros: 86_400_000_000 };
1149 let month = Value::Interval { months: 1, days: 0, micros: 0 };
1150 let thirty = Value::Interval { months: 0, days: 30, micros: 0 };
1151 let long_day = Value::Interval { months: 0, days: 0, micros: 90_000_000_000 };
1152 assert_eq!(compared(Comparison::Equal, day.clone(), hours), Value::Boolean(true));
1153 assert_eq!(compared(Comparison::Equal, month, thirty), Value::Boolean(true));
1154 assert_eq!(compared(Comparison::Greater, long_day, day), Value::Boolean(true));
1155 }
1156
1157 #[test]
1158 fn a_number_compares_the_same_however_it_is_stored() {
1159 assert_eq!(
1160 compared(Comparison::Equal, Value::Integer(3), Value::BigInt(3)),
1161 Value::Boolean(true)
1162 );
1163 assert_eq!(
1164 compared(Comparison::Less, Value::Integer(3), Value::Double(3.5)),
1165 Value::Boolean(true)
1166 );
1167 }
1168
1169 #[test]
1170 fn nulls_go_where_the_query_asked_for_them() {
1171 assert_eq!(
1172 order_with_nulls(&Value::Null, &Value::Integer(1), true).expect("orders"),
1173 Ordering::Less
1174 );
1175 assert_eq!(
1176 order_with_nulls(&Value::Null, &Value::Integer(1), false).expect("orders"),
1177 Ordering::Greater
1178 );
1179 }
1180
1181 #[test]
1182 fn two_constant_vectors_cost_one_comparison() {
1183 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 512);
1184 let right = Vector::constant(LogicalType::Integer, Value::Integer(2), 512);
1185 let result = compare(Comparison::Less, &left, &right).expect("compares");
1186 assert_eq!(result.form(), Form::Constant);
1187 assert_eq!(result.value_at(500), Value::Boolean(true));
1188 }
1189
1190 #[test]
1191 fn a_comparison_of_two_vectors_is_one_answer_per_row() {
1192 let left = Vector::from_values(
1193 LogicalType::Integer,
1194 &[Value::Integer(1), Value::Integer(5), Value::Null],
1195 )
1196 .expect("three rows");
1197 let right = Vector::constant(LogicalType::Integer, Value::Integer(3), 3);
1198 let result = compare(Comparison::Greater, &left, &right).expect("compares");
1199 assert_eq!(result.value_at(0), Value::Boolean(false));
1200 assert_eq!(result.value_at(1), Value::Boolean(true));
1201 assert_eq!(result.value_at(2), Value::Null);
1202 }
1203
1204 #[test]
1205 fn two_vectors_of_different_lengths_are_caught() {
1206 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1207 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 5);
1208 let error = compare(Comparison::Equal, &left, &right).expect_err("ragged");
1209 assert!(error.message().contains("4 row vector"), "{error}");
1210 }
1211
1212 #[test]
1213 fn turning_a_comparison_around_is_what_the_other_side_would_have_said() {
1214 for op in EVERY {
1215 let left = Value::Integer(3);
1216 let right = Value::Integer(7);
1217 assert_eq!(
1218 compare_values(op, &left, &right).expect("compares"),
1219 compare_values(op.swapped(), &right, &left).expect("compares"),
1220 "{op:?}"
1221 );
1222 }
1223 }
1224
1225 #[test]
1228 fn every_specialized_path_agrees_with_the_row_at_a_time_path() {
1229 let mut rng = Rng(0x5eed_1234_9876_4321);
1230 let types: [LogicalType; 11] = [
1231 LogicalType::Boolean,
1232 LogicalType::TinyInt,
1233 LogicalType::SmallInt,
1234 LogicalType::Integer,
1235 LogicalType::BigInt,
1236 LogicalType::HugeInt,
1237 LogicalType::UInteger,
1238 LogicalType::Float,
1239 LogicalType::Double,
1240 LogicalType::Varchar,
1241 LogicalType::Interval,
1242 ];
1243 for ty in &types {
1244 for nulls in [0u64, 1, 3] {
1245 let len = 37;
1246 let make = |rng: &mut Rng| {
1247 let values: Vec<Value> = (0..len)
1248 .map(|_| {
1249 if nulls > 0 && rng.below(nulls + 1) == 0 {
1250 Value::Null
1251 } else {
1252 sample(ty, rng)
1253 }
1254 })
1255 .collect();
1256 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1257 };
1258 let left = make(&mut rng);
1259 let right = make(&mut rng);
1260 let literal = sample(ty, &mut rng);
1261 let constant = Vector::constant(ty.clone(), literal, len);
1262 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1263 let codes: Vec<u32> =
1264 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1265 let dictionary =
1266 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1267 let ends: Vec<u32> = (1..=left.len())
1270 .map(|run| ((run * len) / left.len()).max(run) as u32)
1271 .collect();
1272 let runs = Vector::runs(ends, left.clone()).expect("one value for each run");
1273
1274 for op in EVERY {
1275 agrees(op, &left, &right);
1276 agrees(op, &left, &constant);
1277 agrees(op, &constant, &left);
1278 agrees(op, &left, &null_constant);
1279 agrees(op, &null_constant, &left);
1280 agrees(op, &dictionary, &constant);
1281 agrees(op, &constant, &dictionary);
1282 agrees(op, &dictionary, &right);
1286 agrees(op, &right, &dictionary);
1287 agrees(op, &runs, &constant);
1291 agrees(op, &constant, &runs);
1292 agrees(op, &runs, &right);
1293 agrees(op, &right, &runs);
1294 }
1295 }
1296 }
1297 }
1298
1299 fn refined(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) -> Selection {
1301 let mut out = Vec::new();
1302 for &row in kept.indices() {
1303 let index = row as usize;
1304 let answer = compare_values(op, &left.value_at(index), &right.value_at(index))
1305 .expect("the oracle is only asked about types that compare");
1306 if is_true(&answer) {
1307 out.push(row);
1308 }
1309 }
1310 Selection::from_indices(out)
1311 }
1312
1313 fn threads(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) {
1314 let fast = refine(op, left, right, kept).expect("compares");
1315 assert_eq!(
1316 fast,
1317 refined(op, left, right, kept),
1318 "{op:?} on a {:?} against a {:?} over {} rows",
1319 left.form(),
1320 right.form(),
1321 kept.len()
1322 );
1323 }
1324
1325 #[test]
1329 fn a_threaded_comparison_keeps_what_the_row_at_a_time_path_keeps() {
1330 let mut rng = Rng(0x5eed_4321_1234_9876);
1331 let types = [LogicalType::Integer, LogicalType::Double, LogicalType::Varchar];
1332 for ty in &types {
1333 for nulls in [0u64, 1, 3] {
1334 let len = 37;
1335 let make = |rng: &mut Rng| {
1336 let values: Vec<Value> = (0..len)
1337 .map(|_| {
1338 if nulls > 0 && rng.below(nulls + 1) == 0 {
1339 Value::Null
1340 } else {
1341 sample(ty, rng)
1342 }
1343 })
1344 .collect();
1345 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1346 };
1347 let left = make(&mut rng);
1348 let right = make(&mut rng);
1349 let constant = Vector::constant(ty.clone(), sample(ty, &mut rng), len);
1350 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1351 let codes: Vec<u32> =
1352 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1353 let dictionary =
1354 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1355
1356 let selections = [
1360 Selection::identity(len),
1361 Selection::from_indices((0..len as u32).filter(|row| row % 3 == 0).collect()),
1362 Selection::from_indices(vec![2, 5, 6, 17, 36]),
1363 Selection::empty(),
1364 ];
1365 for op in EVERY {
1366 for kept in &selections {
1367 threads(op, &left, &right, kept);
1368 threads(op, &left, &constant, kept);
1369 threads(op, &constant, &left, kept);
1370 threads(op, &left, &null_constant, kept);
1371 threads(op, &null_constant, &left, kept);
1372 threads(op, &constant, &null_constant, kept);
1373 threads(op, &dictionary, &constant, kept);
1374 threads(op, &constant, &dictionary, kept);
1375 threads(op, &dictionary, &right, kept);
1376 threads(op, &right, &dictionary, kept);
1377 }
1378 }
1379 }
1380 }
1381 }
1382
1383 #[test]
1387 fn a_second_conjunct_reads_only_what_the_first_one_left() {
1388 let numbers: Vec<Value> = (0..64).map(|row| Value::Integer(row % 10)).collect();
1389 let column = Vector::from_values(LogicalType::Integer, &numbers).expect("a flat vector");
1390 let three = Vector::constant(LogicalType::Integer, Value::Integer(3), 64);
1391 let seven = Vector::constant(LogicalType::Integer, Value::Integer(7), 64);
1392
1393 let first = refine(Comparison::Greater, &column, &three, &Selection::identity(64))
1394 .expect("compares");
1395 let both = refine(Comparison::Less, &column, &seven, &first).expect("compares");
1396
1397 let expected: Vec<u32> = (0..64)
1398 .filter(|row| {
1399 let value = row % 10;
1400 value > 3 && value < 7
1401 })
1402 .collect();
1403 assert_eq!(both.indices(), expected.as_slice());
1404 assert!(both.len() < first.len(), "the second conjunct narrowed the selection");
1405 }
1406
1407 #[test]
1411 fn a_null_row_is_not_kept_by_an_ordinary_comparison_and_is_by_a_total_one() {
1412 let column = Vector::from_values(
1413 LogicalType::Integer,
1414 &[Value::Integer(1), Value::Null, Value::Integer(3), Value::Null],
1415 )
1416 .expect("four rows");
1417 let cut = Vector::constant(LogicalType::Integer, Value::Integer(2), 4);
1418 let all = Selection::identity(4);
1419 assert_eq!(
1420 refine(Comparison::Less, &column, &cut, &all).expect("compares").indices(),
1421 &[0]
1422 );
1423 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 4);
1425 assert_eq!(
1426 refine(Comparison::NotDistinctFrom, &column, &nulls, &all).expect("compares").indices(),
1427 &[1, 3]
1428 );
1429 }
1430
1431 #[test]
1432 fn a_selection_past_the_end_is_caught() {
1433 let column = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1434 let past = Selection::from_indices(vec![0, 4]);
1435 let error = refine(Comparison::Equal, &column, &column, &past).expect_err("out of range");
1436 assert!(error.message().contains("4 row vector"), "{error}");
1437 }
1438
1439 fn sample(ty: &LogicalType, rng: &mut Rng) -> Value {
1441 match ty {
1442 LogicalType::Boolean => Value::Boolean(rng.below(2) == 1),
1443 LogicalType::TinyInt => Value::TinyInt(rng.below(7) as i8 - 3),
1444 LogicalType::SmallInt => Value::SmallInt(rng.below(11) as i16 - 5),
1445 LogicalType::Integer => Value::Integer(rng.below(9) as i32 - 4),
1446 LogicalType::BigInt => Value::BigInt(rng.below(9) as i64 - 4),
1447 LogicalType::HugeInt => Value::HugeInt(i128::from(rng.below(9)) - 4),
1448 LogicalType::UInteger => Value::UInteger(rng.below(9) as u32),
1449 LogicalType::Float => Value::Float(match rng.below(5) {
1452 0 => f32::NAN,
1453 1 => -0.0,
1454 other => other as f32 - 2.0,
1455 }),
1456 LogicalType::Double => Value::Double(match rng.below(5) {
1457 0 => f64::NAN,
1458 1 => -0.0,
1459 other => other as f64 - 2.0,
1460 }),
1461 LogicalType::Interval => match rng.below(6) {
1465 0 => Value::Interval { months: 0, days: 1, micros: 0 },
1466 1 => Value::Interval { months: 0, days: 0, micros: 86_400_000_000 },
1467 2 => Value::Interval { months: 1, days: -29, micros: 86_400_000_000 },
1468 3 => Value::Interval { months: 1, days: 0, micros: 0 },
1469 4 => Value::Interval { months: 0, days: 0, micros: 90_000_000_000 },
1470 _ => Value::Interval { months: -1, days: 0, micros: 0 },
1471 },
1472 LogicalType::Varchar => Value::Varchar(
1475 match rng.below(6) {
1476 0 => "",
1477 1 => "ab",
1478 2 => "abc",
1479 3 => "abcdefghijkl",
1480 4 => "abcdefghijklm",
1481 _ => "abcdefghijklmnopqrstuvwxyz",
1482 }
1483 .to_owned(),
1484 ),
1485 other => panic!("the generator has no values for {other}"),
1486 }
1487 }
1488
1489 #[test]
1493 fn prefix_order_is_byte_order_whenever_the_prefixes_differ() {
1494 let words =
1495 ["", "a", "ab", "abc", "abcd", "abcde", "b", "abcdefghijklmnop", "abcdefghijklmnoq"];
1496 let mut column = StringColumn::new();
1497 for word in words {
1498 column.push(word);
1499 }
1500 for (i, one) in words.iter().enumerate() {
1501 for (j, other) in words.iter().enumerate() {
1502 assert_eq!(
1503 string_order(&column, i, &column, j),
1504 one.as_bytes().cmp(other.as_bytes()),
1505 "{one:?} against {other:?}"
1506 );
1507 }
1508 }
1509 }
1510
1511 #[test]
1514 fn a_dictionary_against_a_constant_reads_its_nulls_from_the_values() {
1515 let values = Vector::from_values(
1516 LogicalType::Integer,
1517 &[Value::Integer(1), Value::Null, Value::Integer(9)],
1518 )
1519 .expect("three values");
1520 let dictionary =
1521 Vector::dictionary(vec![0, 1, 2, 1, 0], values).expect("codes are in range");
1522 let constant = Vector::constant(LogicalType::Integer, Value::Integer(5), 5);
1523 let result = compare(Comparison::Less, &dictionary, &constant).expect("compares");
1524 assert_eq!(result.value_at(0), Value::Boolean(true));
1525 assert_eq!(result.value_at(1), Value::Null);
1526 assert_eq!(result.value_at(2), Value::Boolean(false));
1527 assert_eq!(result.value_at(3), Value::Null);
1528 assert_eq!(result.value_at(4), Value::Boolean(true));
1529 }
1530
1531 #[test]
1534 fn a_form_pair_with_no_loop_is_still_right_and_says_so() {
1535 let before = fallback::count(Kernel::Compare, Form::Sequence, Form::Flat);
1537 let sequence = Vector::sequence(10, 1, 4);
1538 let flat = Vector::from_values(
1539 LogicalType::BigInt,
1540 &[Value::BigInt(9), Value::BigInt(11), Value::BigInt(12), Value::Null],
1541 )
1542 .expect("four rows");
1543 let result = compare(Comparison::Less, &sequence, &flat).expect("compares");
1544 assert_eq!(result.value_at(0), Value::Boolean(false));
1545 assert_eq!(result.value_at(1), Value::Boolean(false));
1546 assert_eq!(result.value_at(2), Value::Boolean(false));
1547 assert_eq!(result.value_at(3), Value::Null);
1548 assert!(fallback::count(Kernel::Compare, Form::Sequence, Form::Flat) > before);
1549 }
1550
1551 #[test]
1561 fn a_second_level_of_codes_does_not_turn_the_loops_off() {
1562 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
1563 let values = Vector::from_values(
1564 LogicalType::Integer,
1565 &[Value::Integer(1), Value::Integer(5), Value::Integer(9)],
1566 )
1567 .expect("three rows");
1568 let once = Vector::dictionary(vec![2, 1, 0], values).expect("codes are in range");
1569 let twice = Vector::dictionary(vec![1, 2], once).expect("codes are in range");
1570 let cut = Vector::constant(LogicalType::Integer, Value::Integer(4), 2);
1571 let result = compare(Comparison::Greater, &twice, &cut).expect("compares");
1572 assert_eq!(result.value_at(0), Value::Boolean(true));
1573 assert_eq!(result.value_at(1), Value::Boolean(false));
1574 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
1575 }
1576
1577 #[test]
1581 fn a_side_that_is_entirely_null_answers_without_reading_the_other() {
1582 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 6);
1583 let flat = Vector::from_values(
1584 LogicalType::Integer,
1585 &[
1586 Value::Integer(1),
1587 Value::Integer(2),
1588 Value::Integer(3),
1589 Value::Integer(4),
1590 Value::Integer(5),
1591 Value::Integer(6),
1592 ],
1593 )
1594 .expect("six rows");
1595 agrees(Comparison::Less, &nulls, &flat);
1596 agrees(Comparison::Equal, &flat, &nulls);
1597 assert_eq!(
1598 compare(Comparison::Less, &nulls, &flat).expect("compares").validity(),
1599 &Validity::AllInvalid
1600 );
1601 }
1602
1603 #[test]
1606 fn an_empty_comparison_is_an_empty_answer() {
1607 let left = Vector::from_values(LogicalType::Integer, &[]).expect("no rows");
1608 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 0);
1609 let result = compare(Comparison::Equal, &left, &right).expect("compares");
1610 assert_eq!(result.len(), 0);
1611 }
1612
1613 fn words() -> Vector {
1616 Vector::from_values(
1617 LogicalType::Varchar,
1618 &[
1619 Value::Varchar("http://a".into()),
1620 Value::Varchar("http://b".into()),
1621 Value::Null,
1622 Value::Varchar("ab".into()),
1623 Value::Varchar("http://a".into()),
1624 Value::Varchar("z".into()),
1625 ],
1626 )
1627 .expect("six rows")
1628 }
1629
1630 #[test]
1636 fn a_literal_built_early_answers_what_one_built_here_answers() {
1637 let column = words();
1638 let value = Value::Varchar("http://b".into());
1639 let constant = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
1640 let held = Held::of(&LogicalType::Varchar, &value).expect("a varchar has a column");
1641 let kept = Selection::from_indices(vec![0, 1, 3, 5]);
1642 for op in [
1643 Comparison::Equal,
1644 Comparison::NotEqual,
1645 Comparison::Less,
1646 Comparison::LessOrEqual,
1647 Comparison::Greater,
1648 Comparison::GreaterOrEqual,
1649 Comparison::DistinctFrom,
1650 Comparison::NotDistinctFrom,
1651 ] {
1652 let prepared = compare_prepared(op, &column, &constant, Some(&held)).expect("compares");
1653 assert_eq!(prepared, compare(op, &column, &constant).expect("compares"), "{op:?}");
1654 let flipped = compare_prepared(op, &constant, &column, Some(&held)).expect("compares");
1656 assert_eq!(flipped, compare(op, &constant, &column).expect("compares"), "{op:?}");
1657 let refined =
1658 refine_prepared(op, &column, &constant, &kept, Some(&held)).expect("refines");
1659 assert_eq!(refined, refine(op, &column, &constant, &kept).expect("refines"), "{op:?}");
1660 }
1661 }
1662
1663 #[test]
1670 fn a_literal_built_for_another_value_is_ignored() {
1671 let column = words();
1672 let constant = Vector::constant(LogicalType::Varchar, Value::Varchar("z".into()), 6);
1673 let wrong = Held::of(&LogicalType::Varchar, &Value::Varchar("ab".into()))
1674 .expect("a varchar has a column");
1675 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&wrong))
1676 .expect("compares");
1677 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1678 let other = Held::of(&LogicalType::Integer, &Value::Integer(1)).expect("an integer column");
1681 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&other))
1682 .expect("compares");
1683 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1684 }
1685
1686 #[test]
1689 fn a_packed_column_against_a_constant_answers_what_the_oracle_answers() {
1690 let values: Vec<i32> = (0..64).map(|row| 1000 + (row * 37) % 500).collect();
1691 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1692 .expect("integers are an i32 layout");
1693 let packed = flat.bit_packed().expect("a five hundred wide range packs");
1694 assert_eq!(packed.form(), Form::BitPacked);
1695 for literal in [999, 1000, 1200, 1499, 1500, 2000] {
1696 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 64);
1697 for op in EVERY {
1698 agrees(op, &packed, &constant);
1699 agrees(op, &constant, &packed);
1700 }
1701 }
1702 }
1703
1704 #[test]
1708 fn a_packed_column_with_nulls_answers_what_the_oracle_answers() {
1709 let values: Vec<i32> = (0..32).map(|row| 40 + row * 3).collect();
1710 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1711 .expect("integers are an i32 layout")
1712 .with_validity(Validity::from_iter(32, |row| row % 5 != 0));
1713 let packed = flat.bit_packed().expect("packs");
1714 let constant = Vector::constant(LogicalType::Integer, Value::Integer(80), 32);
1715 for op in EVERY {
1716 agrees(op, &packed, &constant);
1717 }
1718 }
1719
1720 #[test]
1723 fn a_literal_outside_the_packed_range_answers_the_whole_vector_at_once() {
1724 let before = fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant);
1725 let values: Vec<i32> = (0..16).map(|row| 500 + row).collect();
1726 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1727 .expect("integers are an i32 layout");
1728 let packed = flat.bit_packed().expect("packs");
1729 let literals = [-1, 0, 499, 516, 100_000];
1730 for literal in literals {
1731 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 16);
1732 for op in EVERY {
1733 agrees(op, &packed, &constant);
1734 }
1735 }
1736 let total = EVERY.iter().filter(|op| op.is_total()).count();
1741 assert_eq!(
1742 fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant) - before,
1743 (literals.len() * total) as u64,
1744 "only the two total comparisons fall through"
1745 );
1746 }
1747
1748 #[test]
1751 fn refining_a_selection_over_a_packed_column_keeps_the_same_rows() {
1752 let values: Vec<i32> = (0..64).map(|row| 200 + (row * 11) % 128).collect();
1753 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.clone().into()))
1754 .expect("integers are an i32 layout");
1755 let packed = flat.bit_packed().expect("packs");
1756 let kept = Selection::from_predicate(64, |row| row % 3 == 0);
1757 let constant = Vector::constant(LogicalType::Integer, Value::Integer(260), 64);
1758 let packed_rows = refine(Comparison::Greater, &packed, &constant, &kept).expect("refines");
1759 let flat_rows = refine(Comparison::Greater, &flat, &constant, &kept).expect("refines");
1760 assert_eq!(packed_rows.indices(), flat_rows.indices());
1761 assert!(!packed_rows.is_empty(), "the literal is inside the range");
1762 }
1763
1764 fn urls(count: usize) -> Vector {
1767 let mut rng = Rng(0x5eed_1234);
1768 let values: Vec<Value> = (0..count)
1769 .map(|_| {
1770 let host = rng.below(6);
1771 let path = rng.below(40);
1772 Value::Varchar(format!("http://example{host}.test/a/rather/long/path/{path}"))
1773 })
1774 .collect();
1775 Vector::from_values(LogicalType::Varchar, &values).expect("strings")
1776 }
1777
1778 #[test]
1779 fn a_string_view_column_against_a_literal_answers_what_the_oracle_answers() {
1780 let before = fallback::count(Kernel::Compare, Form::StringView, Form::Constant);
1781 let shared = urls(64).shared_text().expect("shares");
1782 assert_eq!(shared.form(), Form::StringView);
1783 let literals = ["http://example3.test/a/rather/long/path/7", "a", "zzz", ""];
1784 for literal in literals {
1785 let value = Value::Varchar(literal.to_owned());
1786 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1787 for op in EVERY {
1788 agrees(op, &shared, &constant);
1789 agrees(op, &constant, &shared);
1790 }
1791 }
1792 assert_eq!(
1793 fallback::count(Kernel::Compare, Form::StringView, Form::Constant),
1794 before,
1795 "the form has a loop of its own for every comparison"
1796 );
1797 }
1798
1799 #[test]
1800 fn a_string_view_column_against_another_one_answers_what_the_oracle_answers() {
1801 let shared = urls(48).shared_text().expect("shares");
1802 let other = urls(48).shared_text().expect("shares");
1803 let flat = urls(48);
1804 for op in EVERY {
1805 agrees(op, &shared, &other);
1806 agrees(op, &shared, &flat);
1807 agrees(op, &flat, &shared);
1808 }
1809 }
1810
1811 #[test]
1812 fn the_nulls_of_a_string_view_column_are_the_nulls_the_oracle_sees() {
1813 let shared = urls(32)
1814 .with_validity(Validity::from_iter(32, |row| row % 4 != 1))
1815 .shared_text()
1816 .expect("shares");
1817 let constant =
1818 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 32);
1819 for op in EVERY {
1820 agrees(op, &shared, &constant);
1821 }
1822 }
1823
1824 #[test]
1825 fn a_compressed_column_against_a_literal_answers_what_the_oracle_answers() {
1826 let before = fallback::count(Kernel::Compare, Form::Fsst, Form::Constant);
1827 let flat = urls(64);
1828 let coded = flat.clone().compressed().expect("compresses");
1829 assert_eq!(coded.form(), Form::Fsst);
1830 let present = match coded.value_at(9) {
1831 Value::Varchar(text) => text,
1832 other => panic!("a string column reads back strings, not {other:?}"),
1833 };
1834 for literal in [present.as_str(), "http://example3.test/nothing/like/it", ""] {
1835 let value = Value::Varchar(literal.to_owned());
1836 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1837 for op in EVERY {
1838 agrees(op, &coded, &constant);
1839 agrees(op, &constant, &coded);
1840 }
1841 }
1842 let ordered = EVERY.len() - 2;
1846 assert_eq!(
1847 fallback::count(Kernel::Compare, Form::Fsst, Form::Constant) - before,
1848 (3 * ordered) as u64,
1849 "only the comparisons that need an order fall through"
1850 );
1851 }
1852
1853 #[test]
1856 fn every_row_of_a_compressed_column_matches_itself_and_nothing_else() {
1857 let flat = urls(48);
1858 let coded = flat.clone().compressed().expect("compresses");
1859 for row in 0..48 {
1860 let constant = Vector::constant(LogicalType::Varchar, flat.value_at(row), 48);
1861 let equal = compare(Comparison::Equal, &coded, &constant).expect("compares");
1862 for other in 0..48 {
1863 let want = flat.value_at(other) == flat.value_at(row);
1864 assert_eq!(
1865 equal.value_at(other),
1866 Value::Boolean(want),
1867 "row {row} against {other}"
1868 );
1869 }
1870 }
1871 }
1872
1873 #[test]
1874 fn the_nulls_of_a_compressed_column_are_the_nulls_the_oracle_sees() {
1875 let coded = urls(32)
1876 .with_validity(Validity::from_iter(32, |row| row % 3 != 0))
1877 .compressed()
1878 .expect("compresses");
1879 let value = coded.value_at(1);
1880 let constant = Vector::constant(LogicalType::Varchar, value, 32);
1881 for op in EVERY {
1882 agrees(op, &coded, &constant);
1883 }
1884 }
1885
1886 #[test]
1890 fn a_filter_over_either_string_form_keeps_the_same_rows() {
1891 let flat = urls(96);
1892 let shared = flat.clone().shared_text().expect("shares");
1893 let constant =
1894 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 96);
1895 let kept = Selection::from_predicate(96, |row| row % 5 != 0);
1896 for op in EVERY {
1897 let over_flat = refine(op, &flat, &constant, &kept).expect("refines");
1898 let over_shared = refine(op, &shared, &constant, &kept).expect("refines");
1899 assert_eq!(over_shared.indices(), over_flat.indices(), "{op:?}");
1900 }
1901 }
1902
1903 #[test]
1907 fn a_comparison_peeled_over_a_shared_dictionary_answers_what_the_oracle_answers() {
1908 let words = ["", "one", "two", "", "three"];
1909 let values: Vec<Value> = words.iter().map(|text| Value::Varchar((*text).into())).collect();
1910 let values = std::sync::Arc::new(
1911 Vector::from_values(LogicalType::Varchar, &values).expect("a vector of text"),
1912 );
1913 let codes = vec![0, 1, 3, 2, 0, 4, 1, 0];
1914 let column = Vector::stable_dictionary(codes.clone(), values).expect("codes are in range");
1915 for literal in ["", "one"] {
1916 for op in [Comparison::Equal, Comparison::NotEqual] {
1917 let value = Value::Varchar(literal.to_owned());
1918 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
1919 let right = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
1920 let wanted = oracle(op, &column, &right);
1921 let got = compare_prepared(op, &column, &right, Some(&held))
1922 .expect("the peeled path answers");
1923 assert_eq!(got, wanted, "{literal:?} under {op:?}");
1924 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
1926 let kept = Selection::from_predicate(column.len(), |row| row % 3 != 1);
1927 let refined = refine_prepared(op, &column, &right, &kept, Some(&held))
1928 .expect("the peeled path narrows");
1929 let wanted: Vec<u32> = kept
1930 .indices()
1931 .iter()
1932 .copied()
1933 .filter(|&row| is_true(&wanted.value_at(row as usize)))
1934 .collect();
1935 assert_eq!(refined.indices(), wanted, "{literal:?} under {op:?}, narrowed");
1936 }
1937 }
1938 }
1939}