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::peel::Found;
83use crate::prepare::Held;
84use crate::shape::{first, identity, nulls_of, single};
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88pub enum Comparison {
89 Equal,
91 NotEqual,
93 Less,
95 LessOrEqual,
97 Greater,
99 GreaterOrEqual,
101 DistinctFrom,
103 NotDistinctFrom,
105}
106
107impl Comparison {
108 #[must_use]
110 pub fn is_total(self) -> bool {
111 matches!(self, Self::DistinctFrom | Self::NotDistinctFrom)
112 }
113
114 #[must_use]
121 pub fn swapped(self) -> Self {
122 match self {
123 Self::Less => Self::Greater,
124 Self::LessOrEqual => Self::GreaterOrEqual,
125 Self::Greater => Self::Less,
126 Self::GreaterOrEqual => Self::LessOrEqual,
127 same => same,
128 }
129 }
130
131 #[must_use]
137 fn holds(self, order: Ordering) -> bool {
138 match self {
139 Self::Equal => order == Ordering::Equal,
140 Self::NotEqual => order != Ordering::Equal,
141 Self::Less => order == Ordering::Less,
142 Self::LessOrEqual => order != Ordering::Greater,
143 Self::Greater => order == Ordering::Greater,
144 Self::GreaterOrEqual => order != Ordering::Less,
145 Self::DistinctFrom | Self::NotDistinctFrom => false,
146 }
147 }
148}
149
150pub fn compare(op: Comparison, left: &Vector, right: &Vector) -> Result<Vector> {
156 compare_prepared(op, left, right, None)
157}
158
159pub fn compare_prepared(
169 op: Comparison,
170 left: &Vector,
171 right: &Vector,
172 held: Option<&Held>,
173) -> Result<Vector> {
174 if left.len() != right.len() {
175 return Err(Error::internal(format!(
176 "a comparison of a {} row vector with a {} row one",
177 left.len(),
178 right.len()
179 )));
180 }
181 let len = left.len();
182 if left.form() == Form::Constant && right.form() == Form::Constant && len > 0 {
183 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
184 return Ok(Vector::constant(LogicalType::Boolean, single, len));
185 }
186
187 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
188 if !op.is_total()
192 && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
193 && len > 0
194 {
195 return boolean(vec![false; len], Validity::AllInvalid, len);
196 }
197
198 if let Some(answers) = external_text_literal(op, left, right, len, identity, held)? {
199 let validity = left_valid.and(&right_valid, len);
200 return boolean(blank_the_nulls(answers, &validity), validity, len);
201 }
202 if let Some(answers) =
203 specialized(op, left, right, &left_valid, &right_valid, len, identity, held)
204 {
205 let validity =
206 if op.is_total() { Validity::AllValid } else { left_valid.and(&right_valid, len) };
207 return boolean(blank_the_nulls(answers, &validity), validity, len);
208 }
209
210 fallback::record(Kernel::Compare, left.form(), right.form());
211 let mut values = Vec::with_capacity(len);
212 for index in 0..len {
215 values.push(compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?);
216 }
217 Vector::from_values(LogicalType::Boolean, &values)
218}
219
220pub fn refine(
238 op: Comparison,
239 left: &Vector,
240 right: &Vector,
241 kept: &Selection,
242) -> Result<Selection> {
243 refine_prepared(op, left, right, kept, None)
244}
245
246pub fn refine_prepared(
256 op: Comparison,
257 left: &Vector,
258 right: &Vector,
259 kept: &Selection,
260 held: Option<&Held>,
261) -> Result<Selection> {
262 if left.len() != right.len() {
263 return Err(Error::internal(format!(
264 "a comparison of a {} row vector with a {} row one",
265 left.len(),
266 right.len()
267 )));
268 }
269 let len = left.len();
270 if kept.indices().iter().any(|&row| row as usize >= len) {
274 return Err(Error::internal(format!("a selection past the end of a {len} row vector")));
275 }
276 if kept.is_empty() {
277 return Ok(Selection::empty());
278 }
279 if left.form() == Form::Constant && right.form() == Form::Constant {
280 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
281 return Ok(if is_true(&single) { kept.clone() } else { Selection::empty() });
282 }
283
284 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
285 if !op.is_total() && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
286 {
287 return Ok(Selection::empty());
288 }
289
290 let rows = kept.indices();
291 let map = |slot: usize| rows[slot] as usize;
292 if let Some(answers) = external_text_literal(op, left, right, kept.len(), map, held)? {
293 return Ok(narrowed(&answers, rows, |slot| {
294 let row = rows[slot] as usize;
295 left_valid.is_valid(row) && right_valid.is_valid(row)
296 }));
297 }
298 if let Some(answers) =
299 specialized(op, left, right, &left_valid, &right_valid, kept.len(), map, held)
300 {
301 if op.is_total() || (left_valid == Validity::AllValid && right_valid == Validity::AllValid)
304 {
305 return Ok(narrowed(&answers, rows, |_| true));
306 }
307 return Ok(narrowed(&answers, rows, |slot| {
311 let row = rows[slot] as usize;
312 left_valid.is_valid(row) && right_valid.is_valid(row)
313 }));
314 }
315
316 fallback::record(Kernel::Compare, left.form(), right.form());
317 let mut out = Vec::with_capacity(kept.len());
318 for &row in rows {
321 let index = row as usize;
322 if is_true(&compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?) {
323 out.push(row);
324 }
325 }
326 Ok(Selection::from_indices(out))
327}
328
329fn external_text_literal<M>(
345 op: Comparison,
346 left: &Vector,
347 right: &Vector,
348 len: usize,
349 map: M,
350 held: Option<&Held>,
351) -> Result<Option<Vec<bool>>>
352where
353 M: Fn(usize) -> usize + Copy,
354{
355 if op.is_total()
356 || left.logical_type() != &LogicalType::Varchar
357 || right.logical_type() != &LogicalType::Varchar
358 {
359 return Ok(None);
360 }
361 let (column, literal, swapped) = match (left.constant_value(), right.constant_value()) {
362 (None, Some(Value::Varchar(literal))) if left.positions().is_some() => {
363 (left, literal.as_bytes(), false)
364 }
365 (Some(Value::Varchar(literal)), None) if right.positions().is_some() => {
366 (right, literal.as_bytes(), true)
367 }
368 _ => return Ok(None),
369 };
370 let op = if swapped { op.swapped() } else { op };
373 let same = op == Comparison::Equal;
374 if matches!(op, Comparison::Equal | Comparison::NotEqual) {
375 if let Some(held) = held.filter(|held| held.text() == Some(literal)) {
379 if let Some(found) = held.lookup().find(column, literal) {
382 return Ok(Some(against_code(column, found?, len, map, same)?));
383 }
384 let decide = |dictionary: &Vector, code: usize| -> Result<bool> {
385 let found = if literal.is_empty() {
386 dictionary.try_bytes_len_at(code)?.is_some_and(|length| length == 0)
387 } else {
388 dictionary.try_bytes_at(code)?.is_some_and(|bytes| bytes == literal)
389 };
390 Ok(found)
391 };
392 if let Some(answers) = held.peel().answer(column, len, map, decide) {
393 let mut answers = answers?;
394 if !same {
395 for answer in &mut answers {
396 *answer = !*answer;
397 }
398 }
399 return Ok(Some(answers));
400 }
401 }
402 let mut answers = Vec::with_capacity(len);
403 for slot in 0..len {
404 let row = map(slot);
405 let equal = if literal.is_empty() {
408 column.try_bytes_len_at(row)?.is_some_and(|length| length == 0)
409 } else {
410 column.try_bytes_at(row)?.is_some_and(|bytes| bytes == literal)
411 };
412 answers.push(equal == same);
413 }
414 return Ok(Some(answers));
415 }
416 let mut answers = Vec::with_capacity(len);
417 for slot in 0..len {
418 let row = map(slot);
419 let order = match column.try_bytes_at(row)? {
423 Some(bytes) => bytes.cmp(literal),
424 None => Ordering::Equal,
425 };
426 answers.push(op.holds(order));
427 }
428 Ok(Some(answers))
429}
430
431fn against_code<M>(
439 column: &Vector,
440 found: Found,
441 len: usize,
442 map: M,
443 same: bool,
444) -> Result<Vec<bool>>
445where
446 M: Fn(usize) -> usize,
447{
448 let Found::At(wanted) = found else { return Ok(vec![!same; len]) };
449 let (codes, _) = column
450 .shared_dictionary_parts()
451 .ok_or_else(|| Error::internal("a resolved literal lost the codes it was resolved for"))?;
452 let mut answers = Vec::with_capacity(len);
453 for slot in 0..len {
455 let code = *codes
456 .get(map(slot))
457 .ok_or_else(|| Error::internal("a compared row is past the end of its codes"))?;
458 answers.push((code == wanted) == same);
459 }
460 Ok(answers)
461}
462
463fn narrowed<L: Fn(usize) -> bool>(answers: &[bool], rows: &[u32], live: L) -> Selection {
470 let mut out = vec![0_u32; answers.len()];
471 let mut count = 0;
472 for (slot, &answer) in answers.iter().enumerate() {
473 out[count] = rows[slot];
474 count += usize::from(answer & live(slot));
476 }
477 out.truncate(count);
478 Selection::from_indices(out)
479}
480
481fn boolean(answers: Vec<bool>, validity: Validity, len: usize) -> Result<Vector> {
483 let validity = if len == 0 { Validity::AllValid } else { validity.normalize(len) };
487 Ok(Vector::flat(LogicalType::Boolean, Data::Bool(answers.into()))?.with_validity(validity))
488}
489
490fn blank_the_nulls(mut answers: Vec<bool>, validity: &Validity) -> Vec<bool> {
498 if let Validity::Mask(mask) = validity {
499 for (index, answer) in answers.iter_mut().enumerate() {
500 if !mask.get(index) {
501 *answer = false;
502 }
503 }
504 }
505 answers
506}
507
508#[expect(
520 clippy::too_many_arguments,
521 reason = "two sides, two validities, the operator, the length, the index mapping and the \
522 literal that was built early, all of which the branches below need"
523)]
524fn specialized<M>(
525 op: Comparison,
526 left: &Vector,
527 right: &Vector,
528 left_valid: &Validity,
529 right_valid: &Validity,
530 len: usize,
531 map: M,
532 held: Option<&Held>,
533) -> Option<Vec<bool>>
534where
535 M: Fn(usize) -> usize + Copy,
536{
537 if left.logical_type() != right.logical_type() {
541 return None;
542 }
543
544 if let (Some(one), Some(other)) = (left.data(), right.data()) {
545 return dispatch(op, len, one, map, other, map, left_valid, right_valid, map);
546 }
547 if !op.is_total() {
553 if let (Some(packed), Some(value)) = (left.packed_parts(), right.constant_value()) {
554 let wanted = exact(held, left.logical_type(), value)?;
555 return Some(packed_against(op, &packed, wanted, len, map));
556 }
557 if let (Some(value), Some(packed)) = (left.constant_value(), right.packed_parts()) {
558 let wanted = exact(held, right.logical_type(), value)?;
559 return Some(packed_against(op.swapped(), &packed, wanted, len, map));
560 }
561 }
562 if let (Some(one), Some(value)) = (left.data(), right.constant_value()) {
563 let column = readied(held, left.logical_type(), value)?;
564 let other = column.data()?;
565 return dispatch(op, len, one, map, other, first, left_valid, right_valid, map);
566 }
567 if let (Some(value), Some(other)) = (left.constant_value(), right.data()) {
568 let column = readied(held, right.logical_type(), value)?;
570 let one = column.data()?;
571 return dispatch(op.swapped(), len, other, map, one, first, right_valid, left_valid, map);
572 }
573 if matches!(op, Comparison::Equal | Comparison::NotEqual) {
578 if let (Some(coded), Some(value)) = (left.coded_parts(), right.constant_value()) {
579 let wanted = encoded(&coded, held, left.logical_type(), value)?;
580 return Some(coded_against(op, &coded, &wanted, len, map));
581 }
582 if let (Some(value), Some(coded)) = (left.constant_value(), right.coded_parts()) {
583 let wanted = encoded(&coded, held, right.logical_type(), value)?;
584 return Some(coded_against(op, &coded, &wanted, len, map));
585 }
586 }
587 if let (Some((one, one_arena)), Some((other, other_arena))) =
593 (left.text_parts(), right.text_parts())
594 {
595 return Some(sweep(
596 op,
597 len,
598 |index| view_order(one.get(map(index)), one_arena, other.get(map(index)), other_arena),
599 left_valid,
600 right_valid,
601 map,
602 ));
603 }
604 if let (Some((one, one_arena)), Some(value)) = (left.text_parts(), right.constant_value()) {
608 let column = readied(held, left.logical_type(), value)?;
609 let (other, other_arena) = column.text_parts()?;
610 let wanted = other.first();
611 return Some(sweep(
612 op,
613 len,
614 |index| view_order(one.get(map(index)), one_arena, wanted, other_arena),
615 left_valid,
616 right_valid,
617 map,
618 ));
619 }
620 if let (Some(value), Some((other, other_arena))) = (left.constant_value(), right.text_parts()) {
621 let column = readied(held, right.logical_type(), value)?;
623 let (one, one_arena) = column.text_parts()?;
624 let wanted = one.first();
625 return Some(sweep(
626 op.swapped(),
627 len,
628 |index| view_order(other.get(map(index)), other_arena, wanted, one_arena),
629 right_valid,
630 left_valid,
631 map,
632 ));
633 }
634 if let (Some((codes, values)), Some(value)) = (left.positions(), right.constant_value()) {
635 let one = values.data()?;
636 let column = readied(held, left.logical_type(), value)?;
637 let other = column.data()?;
638 let at = |index: usize| codes[map(index)] as usize;
639 return dispatch(op, len, one, at, other, first, left_valid, right_valid, map);
640 }
641 if let (Some(value), Some((codes, values))) = (left.constant_value(), right.positions()) {
642 let other = values.data()?;
643 let column = readied(held, right.logical_type(), value)?;
644 let one = column.data()?;
645 let at = |index: usize| codes[map(index)] as usize;
646 return dispatch(op.swapped(), len, other, at, one, first, right_valid, left_valid, map);
647 }
648 if let (Some((codes, values)), Some(other)) = (left.positions(), right.data()) {
654 let one = values.data()?;
655 let at = |index: usize| codes[map(index)] as usize;
656 return dispatch(op, len, one, at, other, map, left_valid, right_valid, map);
657 }
658 if let (Some(one), Some((codes, values))) = (left.data(), right.positions()) {
659 let other = values.data()?;
660 let at = |index: usize| codes[map(index)] as usize;
661 return dispatch(op.swapped(), len, other, at, one, map, right_valid, left_valid, map);
662 }
663 None
664}
665
666fn exact(held: Option<&Held>, ty: &LogicalType, value: &Value) -> Option<i128> {
673 let column = readied(held, ty, value)?;
674 let data = column.data()?;
675 data.signed_at(0).or_else(|| data.unsigned_at(0).and_then(|value| i128::try_from(value).ok()))
676}
677
678fn encoded(
684 coded: &Coded<'_>,
685 held: Option<&Held>,
686 ty: &LogicalType,
687 value: &Value,
688) -> Option<Vec<u8>> {
689 let column = readied(held, ty, value)?;
690 let (views, arena) = column.text_parts()?;
691 Some(coded.encode(views.first()?.bytes_in(arena)?))
692}
693
694fn coded_against<M>(
700 op: Comparison,
701 coded: &Coded<'_>,
702 wanted: &[u8],
703 len: usize,
704 map: M,
705) -> Vec<bool>
706where
707 M: Fn(usize) -> usize + Copy,
708{
709 let same = op == Comparison::Equal;
710 let mut answers = Vec::with_capacity(len);
711 for row in 0..len {
712 answers.push((coded.row(map(row)) == Some(wanted)) == same);
713 }
714 answers
715}
716
717fn packed_against<M>(
723 op: Comparison,
724 packed: &Packed<'_>,
725 wanted: i128,
726 len: usize,
727 map: M,
728) -> Vec<bool>
729where
730 M: Fn(usize) -> usize + Copy,
731{
732 let Some(code) = packed.code_of(wanted) else {
733 let above = wanted > packed.ceiling();
736 let same = match op {
737 Comparison::Equal | Comparison::NotDistinctFrom => false,
738 Comparison::NotEqual | Comparison::DistinctFrom => true,
739 Comparison::Less | Comparison::LessOrEqual => above,
740 Comparison::Greater | Comparison::GreaterOrEqual => !above,
741 };
742 return vec![same; len];
743 };
744 let test: fn(u64, u64) -> bool = match op {
747 Comparison::Equal | Comparison::NotDistinctFrom => |found, want| found == want,
748 Comparison::NotEqual | Comparison::DistinctFrom => |found, want| found != want,
749 Comparison::Less => |found, want| found < want,
750 Comparison::LessOrEqual => |found, want| found <= want,
751 Comparison::Greater => |found, want| found > want,
752 Comparison::GreaterOrEqual => |found, want| found >= want,
753 };
754 let mut answers = Vec::with_capacity(len);
755 for row in 0..len {
756 answers.push(test(packed.code(map(row)), code));
757 }
758 answers
759}
760
761#[expect(
767 clippy::too_many_arguments,
768 reason = "two sides with an index each, the operator, the length and two validities, all of \
769 which the loop needs and none of which is worth a struct that exists for one call"
770)]
771fn dispatch<L, R, V>(
772 op: Comparison,
773 len: usize,
774 left: &Data,
775 at_left: L,
776 right: &Data,
777 at_right: R,
778 left_valid: &Validity,
779 right_valid: &Validity,
780 at_valid: V,
781) -> Option<Vec<bool>>
782where
783 L: Fn(usize) -> usize,
784 R: Fn(usize) -> usize,
785 V: Fn(usize) -> usize,
786{
787 macro_rules! layouts {
788 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
789 match (left, right) {
790 $(
791 (Data::$variant(one), Data::$variant(other)) => Some(sweep(
792 op,
793 len,
794 |index| one[at_left(index)].cmp(&other[at_right(index)]),
795 left_valid,
796 right_valid,
797 &at_valid,
798 )),
799 )+
800 (Data::Float32(one), Data::Float32(other)) => Some(sweep(
803 op,
804 len,
805 |index| {
806 float_order(
807 f64::from(one[at_left(index)]),
808 f64::from(other[at_right(index)]),
809 )
810 },
811 left_valid,
812 right_valid,
813 &at_valid,
814 )),
815 (Data::Float64(one), Data::Float64(other)) => Some(sweep(
816 op,
817 len,
818 |index| float_order(one[at_left(index)], other[at_right(index)]),
819 left_valid,
820 right_valid,
821 &at_valid,
822 )),
823 (Data::Interval(one), Data::Interval(other)) => Some(sweep(
826 op,
827 len,
828 |index| {
829 let (months, days, micros) = one[at_left(index)];
830 let (bm, bd, bu) = other[at_right(index)];
831 interval_micros(months, days, micros).cmp(&interval_micros(bm, bd, bu))
832 },
833 left_valid,
834 right_valid,
835 &at_valid,
836 )),
837 (Data::Varlen(one), Data::Varlen(other)) => Some(sweep(
838 op,
839 len,
840 |index| string_order(one, at_left(index), other, at_right(index)),
841 left_valid,
842 right_valid,
843 &at_valid,
844 )),
845 _ => None,
846 }
847 };
848 }
849 rudb_vector::for_each_layout!(ordered, layouts)
850}
851
852fn readied<'a>(held: Option<&'a Held>, ty: &LogicalType, value: &Value) -> Option<Cow<'a, Vector>> {
858 match held {
859 Some(held) if held.matches(ty, value) => Some(Cow::Borrowed(held.single())),
860 _ => Some(Cow::Owned(single(ty, value)?)),
861 }
862}
863
864fn string_order(
872 left: &StringColumn,
873 at_left: usize,
874 right: &StringColumn,
875 at_right: usize,
876) -> Ordering {
877 view_order(left.views().get(at_left), left.arena(), right.views().get(at_right), right.arena())
878}
879
880fn view_order(
886 one: Option<&StringView>,
887 one_arena: &[u8],
888 other: Option<&StringView>,
889 other_arena: &[u8],
890) -> Ordering {
891 let (Some(one), Some(other)) = (one, other) else {
892 return Ordering::Equal;
893 };
894 let (prefix, against) = (one.prefix(), other.prefix());
895 if prefix != against {
896 return prefix.cmp(&against);
897 }
898 let bytes = one.bytes_in(one_arena).unwrap_or_default();
903 let against_bytes = other.bytes_in(other_arena).unwrap_or_default();
904 bytes.cmp(against_bytes)
905}
906
907fn sweep<O, V>(
913 op: Comparison,
914 len: usize,
915 order_at: O,
916 left_valid: &Validity,
917 right_valid: &Validity,
918 at_valid: V,
919) -> Vec<bool>
920where
921 O: Fn(usize) -> Ordering,
922 V: Fn(usize) -> usize,
923{
924 let mut answers = vec![false; len];
925 match op {
926 Comparison::Equal => fill(&mut answers, order_at, |o| o == Ordering::Equal),
927 Comparison::NotEqual => fill(&mut answers, order_at, |o| o != Ordering::Equal),
928 Comparison::Less => fill(&mut answers, order_at, |o| o == Ordering::Less),
929 Comparison::LessOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Greater),
930 Comparison::Greater => fill(&mut answers, order_at, |o| o == Ordering::Greater),
931 Comparison::GreaterOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Less),
932 Comparison::DistinctFrom => {
933 total(&mut answers, order_at, left_valid, right_valid, at_valid);
934 for answer in &mut answers {
935 *answer = !*answer;
936 }
937 }
938 Comparison::NotDistinctFrom => {
939 total(&mut answers, order_at, left_valid, right_valid, at_valid);
940 }
941 }
942 answers
943}
944
945#[inline]
947fn fill<O, H>(answers: &mut [bool], order_at: O, held: H)
948where
949 O: Fn(usize) -> Ordering,
950 H: Fn(Ordering) -> bool,
951{
952 for (index, answer) in answers.iter_mut().enumerate() {
953 *answer = held(order_at(index));
954 }
955}
956
957fn total<O, V>(
964 answers: &mut [bool],
965 order_at: O,
966 left_valid: &Validity,
967 right_valid: &Validity,
968 at_valid: V,
969) where
970 O: Fn(usize) -> Ordering,
971 V: Fn(usize) -> usize,
972{
973 if *left_valid == Validity::AllValid && *right_valid == Validity::AllValid {
974 fill(answers, order_at, |o| o == Ordering::Equal);
975 return;
976 }
977 for (index, answer) in answers.iter_mut().enumerate() {
978 let row = at_valid(index);
979 *answer = match (left_valid.is_valid(row), right_valid.is_valid(row)) {
980 (true, true) => order_at(index) == Ordering::Equal,
981 (false, false) => true,
982 _ => false,
983 };
984 }
985}
986
987pub fn compare_values(op: Comparison, left: &Value, right: &Value) -> Result<Value> {
993 if op.is_total() {
994 let same = match (left.is_null(), right.is_null()) {
995 (true, true) => true,
996 (true, false) | (false, true) => false,
997 (false, false) => order(left, right)? == Ordering::Equal,
998 };
999 return Ok(Value::Boolean(match op {
1000 Comparison::NotDistinctFrom => same,
1001 _ => !same,
1002 }));
1003 }
1004 if left.is_null() || right.is_null() {
1005 return Ok(Value::Null);
1006 }
1007 let ordering = order(left, right)?;
1008 let held = match op {
1009 Comparison::Equal => ordering == Ordering::Equal,
1010 Comparison::NotEqual => ordering != Ordering::Equal,
1011 Comparison::Less => ordering == Ordering::Less,
1012 Comparison::LessOrEqual => ordering != Ordering::Greater,
1013 Comparison::Greater => ordering == Ordering::Greater,
1014 Comparison::GreaterOrEqual => ordering != Ordering::Less,
1015 Comparison::DistinctFrom | Comparison::NotDistinctFrom => {
1016 return Err(Error::internal("a total comparison reached the ordered path"));
1017 }
1018 };
1019 Ok(Value::Boolean(held))
1020}
1021
1022pub fn order(left: &Value, right: &Value) -> Result<Ordering> {
1033 match (left, right) {
1034 (Value::Null, _) | (_, Value::Null) => {
1035 Err(Error::internal("a null reached the ordering path"))
1036 }
1037 (Value::Boolean(a), Value::Boolean(b)) => Ok(a.cmp(b)),
1038 (Value::Varchar(a), Value::Varchar(b)) => Ok(a.as_bytes().cmp(b.as_bytes())),
1039 (Value::Blob(a), Value::Blob(b)) => Ok(a.cmp(b)),
1040 (Value::Date(a), Value::Date(b)) => Ok(a.cmp(b)),
1041 (Value::Time(a), Value::Time(b))
1044 | (Value::TimeTz(a), Value::TimeTz(b))
1045 | (Value::Timestamp(a), Value::Timestamp(b))
1046 | (Value::TimestampTz(a), Value::TimestampTz(b)) => Ok(a.cmp(b)),
1047 (
1048 Value::Interval { months: am, days: ad, micros: au },
1049 Value::Interval { months: bm, days: bd, micros: bu },
1050 ) => Ok(interval_micros(*am, *ad, *au).cmp(&interval_micros(*bm, *bd, *bu))),
1051 _ => numeric_order(left, right),
1052 }
1053}
1054
1055fn numeric_order(left: &Value, right: &Value) -> Result<Ordering> {
1057 if let (Some(a), Some(b)) = (integral(left), integral(right)) {
1058 return Ok(a.cmp(&b));
1059 }
1060 if let (
1061 Value::Decimal { unscaled: a, scale: sa, .. },
1062 Value::Decimal { unscaled: b, scale: sb, .. },
1063 ) = (left, right)
1064 {
1065 if sa == sb {
1066 return Ok(a.cmp(b));
1067 }
1068 }
1069 match (approximate(left), approximate(right)) {
1070 (Some(a), Some(b)) => Ok(float_order(a, b)),
1071 _ => Err(Error::not_implemented(format!(
1072 "comparing {} with {}",
1073 left.logical_type(),
1074 right.logical_type()
1075 ))),
1076 }
1077}
1078
1079fn float_order(left: f64, right: f64) -> Ordering {
1081 if left == right {
1082 return Ordering::Equal;
1083 }
1084 match (left.is_nan(), right.is_nan()) {
1085 (true, true) => Ordering::Equal,
1086 (true, false) => Ordering::Greater,
1087 (false, true) => Ordering::Less,
1088 (false, false) => left.partial_cmp(&right).unwrap_or(Ordering::Equal),
1089 }
1090}
1091
1092pub fn order_with_nulls(left: &Value, right: &Value, nulls_first: bool) -> Result<Ordering> {
1101 match (left.is_null(), right.is_null()) {
1102 (true, true) => Ok(Ordering::Equal),
1103 (true, false) => Ok(if nulls_first { Ordering::Less } else { Ordering::Greater }),
1104 (false, true) => Ok(if nulls_first { Ordering::Greater } else { Ordering::Less }),
1105 (false, false) => order(left, right),
1106 }
1107}
1108
1109#[cfg(test)]
1110mod tests {
1111 use super::*;
1112
1113 fn compared(op: Comparison, left: Value, right: Value) -> Value {
1114 compare_values(op, &left, &right).expect("these types compare")
1115 }
1116
1117 const EVERY: [Comparison; 8] = [
1119 Comparison::Equal,
1120 Comparison::NotEqual,
1121 Comparison::Less,
1122 Comparison::LessOrEqual,
1123 Comparison::Greater,
1124 Comparison::GreaterOrEqual,
1125 Comparison::DistinctFrom,
1126 Comparison::NotDistinctFrom,
1127 ];
1128
1129 fn oracle(op: Comparison, left: &Vector, right: &Vector) -> Vector {
1135 let values: Vec<Value> = (0..left.len())
1136 .map(|index| {
1137 compare_values(op, &left.value_at(index), &right.value_at(index))
1138 .expect("the oracle is only asked about types that compare")
1139 })
1140 .collect();
1141 Vector::from_values(LogicalType::Boolean, &values).expect("booleans")
1142 }
1143
1144 fn agrees(op: Comparison, left: &Vector, right: &Vector) {
1148 let fast = compare(op, left, right).expect("compares");
1149 let slow = oracle(op, left, right);
1150 assert_eq!(fast, slow, "{op:?} on a {:?} against a {:?}", left.form(), right.form());
1151 }
1152
1153 struct Rng(u64);
1156
1157 impl Rng {
1158 fn next(&mut self) -> u64 {
1159 self.0 ^= self.0 << 13;
1160 self.0 ^= self.0 >> 7;
1161 self.0 ^= self.0 << 17;
1162 self.0
1163 }
1164
1165 fn below(&mut self, bound: u64) -> u64 {
1166 self.next() % bound
1167 }
1168 }
1169
1170 #[test]
1171 fn an_ordinary_comparison_is_null_when_either_side_is() {
1172 assert_eq!(compared(Comparison::Equal, Value::Integer(1), Value::Null), Value::Null);
1173 assert_eq!(compared(Comparison::Less, Value::Null, Value::Integer(1)), Value::Null);
1174 }
1175
1176 #[test]
1177 fn a_total_comparison_is_never_null() {
1178 assert_eq!(
1179 compared(Comparison::NotDistinctFrom, Value::Null, Value::Null),
1180 Value::Boolean(true)
1181 );
1182 assert_eq!(
1183 compared(Comparison::NotDistinctFrom, Value::Integer(1), Value::Null),
1184 Value::Boolean(false)
1185 );
1186 assert_eq!(
1187 compared(Comparison::DistinctFrom, Value::Integer(1), Value::Null),
1188 Value::Boolean(true)
1189 );
1190 }
1191
1192 #[test]
1193 fn a_string_compares_by_bytes() {
1194 assert_eq!(
1195 compared(Comparison::Less, Value::Varchar("a".into()), Value::Varchar("b".into())),
1196 Value::Boolean(true)
1197 );
1198 assert_eq!(
1199 compared(Comparison::Less, Value::Varchar("Z".into()), Value::Varchar("a".into())),
1200 Value::Boolean(true)
1201 );
1202 }
1203
1204 #[test]
1207 fn two_nans_are_one_value_and_they_sort_above_the_numbers() {
1208 assert_eq!(
1209 compared(Comparison::Equal, Value::Double(f64::NAN), Value::Double(f64::NAN)),
1210 Value::Boolean(true)
1211 );
1212 assert_eq!(
1213 compared(Comparison::Greater, Value::Double(f64::NAN), Value::Double(1e300)),
1214 Value::Boolean(true)
1215 );
1216 }
1217
1218 #[test]
1219 fn zero_has_one_value_however_it_is_signed() {
1220 assert_eq!(
1221 compared(Comparison::Equal, Value::Double(0.0), Value::Double(-0.0)),
1222 Value::Boolean(true)
1223 );
1224 }
1225
1226 #[test]
1231 fn two_intervals_of_the_same_length_are_one_value() {
1232 let day = Value::Interval { months: 0, days: 1, micros: 0 };
1233 let hours = Value::Interval { months: 0, days: 0, micros: 86_400_000_000 };
1234 let month = Value::Interval { months: 1, days: 0, micros: 0 };
1235 let thirty = Value::Interval { months: 0, days: 30, micros: 0 };
1236 let long_day = Value::Interval { months: 0, days: 0, micros: 90_000_000_000 };
1237 assert_eq!(compared(Comparison::Equal, day.clone(), hours), Value::Boolean(true));
1238 assert_eq!(compared(Comparison::Equal, month, thirty), Value::Boolean(true));
1239 assert_eq!(compared(Comparison::Greater, long_day, day), Value::Boolean(true));
1240 }
1241
1242 #[test]
1243 fn a_number_compares_the_same_however_it_is_stored() {
1244 assert_eq!(
1245 compared(Comparison::Equal, Value::Integer(3), Value::BigInt(3)),
1246 Value::Boolean(true)
1247 );
1248 assert_eq!(
1249 compared(Comparison::Less, Value::Integer(3), Value::Double(3.5)),
1250 Value::Boolean(true)
1251 );
1252 }
1253
1254 #[test]
1255 fn nulls_go_where_the_query_asked_for_them() {
1256 assert_eq!(
1257 order_with_nulls(&Value::Null, &Value::Integer(1), true).expect("orders"),
1258 Ordering::Less
1259 );
1260 assert_eq!(
1261 order_with_nulls(&Value::Null, &Value::Integer(1), false).expect("orders"),
1262 Ordering::Greater
1263 );
1264 }
1265
1266 #[test]
1267 fn two_constant_vectors_cost_one_comparison() {
1268 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 512);
1269 let right = Vector::constant(LogicalType::Integer, Value::Integer(2), 512);
1270 let result = compare(Comparison::Less, &left, &right).expect("compares");
1271 assert_eq!(result.form(), Form::Constant);
1272 assert_eq!(result.value_at(500), Value::Boolean(true));
1273 }
1274
1275 #[test]
1276 fn a_comparison_of_two_vectors_is_one_answer_per_row() {
1277 let left = Vector::from_values(
1278 LogicalType::Integer,
1279 &[Value::Integer(1), Value::Integer(5), Value::Null],
1280 )
1281 .expect("three rows");
1282 let right = Vector::constant(LogicalType::Integer, Value::Integer(3), 3);
1283 let result = compare(Comparison::Greater, &left, &right).expect("compares");
1284 assert_eq!(result.value_at(0), Value::Boolean(false));
1285 assert_eq!(result.value_at(1), Value::Boolean(true));
1286 assert_eq!(result.value_at(2), Value::Null);
1287 }
1288
1289 #[test]
1290 fn two_vectors_of_different_lengths_are_caught() {
1291 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1292 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 5);
1293 let error = compare(Comparison::Equal, &left, &right).expect_err("ragged");
1294 assert!(error.message().contains("4 row vector"), "{error}");
1295 }
1296
1297 #[test]
1298 fn turning_a_comparison_around_is_what_the_other_side_would_have_said() {
1299 for op in EVERY {
1300 let left = Value::Integer(3);
1301 let right = Value::Integer(7);
1302 assert_eq!(
1303 compare_values(op, &left, &right).expect("compares"),
1304 compare_values(op.swapped(), &right, &left).expect("compares"),
1305 "{op:?}"
1306 );
1307 }
1308 }
1309
1310 #[test]
1313 fn every_specialized_path_agrees_with_the_row_at_a_time_path() {
1314 let mut rng = Rng(0x5eed_1234_9876_4321);
1315 let types: [LogicalType; 11] = [
1316 LogicalType::Boolean,
1317 LogicalType::TinyInt,
1318 LogicalType::SmallInt,
1319 LogicalType::Integer,
1320 LogicalType::BigInt,
1321 LogicalType::HugeInt,
1322 LogicalType::UInteger,
1323 LogicalType::Float,
1324 LogicalType::Double,
1325 LogicalType::Varchar,
1326 LogicalType::Interval,
1327 ];
1328 for ty in &types {
1329 for nulls in [0u64, 1, 3] {
1330 let len = 37;
1331 let make = |rng: &mut Rng| {
1332 let values: Vec<Value> = (0..len)
1333 .map(|_| {
1334 if nulls > 0 && rng.below(nulls + 1) == 0 {
1335 Value::Null
1336 } else {
1337 sample(ty, rng)
1338 }
1339 })
1340 .collect();
1341 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1342 };
1343 let left = make(&mut rng);
1344 let right = make(&mut rng);
1345 let literal = sample(ty, &mut rng);
1346 let constant = Vector::constant(ty.clone(), literal, len);
1347 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1348 let codes: Vec<u32> =
1349 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1350 let dictionary =
1351 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1352 let ends: Vec<u32> = (1..=left.len())
1355 .map(|run| ((run * len) / left.len()).max(run) as u32)
1356 .collect();
1357 let runs = Vector::runs(ends, left.clone()).expect("one value for each run");
1358
1359 for op in EVERY {
1360 agrees(op, &left, &right);
1361 agrees(op, &left, &constant);
1362 agrees(op, &constant, &left);
1363 agrees(op, &left, &null_constant);
1364 agrees(op, &null_constant, &left);
1365 agrees(op, &dictionary, &constant);
1366 agrees(op, &constant, &dictionary);
1367 agrees(op, &dictionary, &right);
1371 agrees(op, &right, &dictionary);
1372 agrees(op, &runs, &constant);
1376 agrees(op, &constant, &runs);
1377 agrees(op, &runs, &right);
1378 agrees(op, &right, &runs);
1379 }
1380 }
1381 }
1382 }
1383
1384 fn refined(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) -> Selection {
1386 let mut out = Vec::new();
1387 for &row in kept.indices() {
1388 let index = row as usize;
1389 let answer = compare_values(op, &left.value_at(index), &right.value_at(index))
1390 .expect("the oracle is only asked about types that compare");
1391 if is_true(&answer) {
1392 out.push(row);
1393 }
1394 }
1395 Selection::from_indices(out)
1396 }
1397
1398 fn threads(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) {
1399 let fast = refine(op, left, right, kept).expect("compares");
1400 assert_eq!(
1401 fast,
1402 refined(op, left, right, kept),
1403 "{op:?} on a {:?} against a {:?} over {} rows",
1404 left.form(),
1405 right.form(),
1406 kept.len()
1407 );
1408 }
1409
1410 #[test]
1414 fn a_threaded_comparison_keeps_what_the_row_at_a_time_path_keeps() {
1415 let mut rng = Rng(0x5eed_4321_1234_9876);
1416 let types = [LogicalType::Integer, LogicalType::Double, LogicalType::Varchar];
1417 for ty in &types {
1418 for nulls in [0u64, 1, 3] {
1419 let len = 37;
1420 let make = |rng: &mut Rng| {
1421 let values: Vec<Value> = (0..len)
1422 .map(|_| {
1423 if nulls > 0 && rng.below(nulls + 1) == 0 {
1424 Value::Null
1425 } else {
1426 sample(ty, rng)
1427 }
1428 })
1429 .collect();
1430 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1431 };
1432 let left = make(&mut rng);
1433 let right = make(&mut rng);
1434 let constant = Vector::constant(ty.clone(), sample(ty, &mut rng), len);
1435 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1436 let codes: Vec<u32> =
1437 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1438 let dictionary =
1439 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1440
1441 let selections = [
1445 Selection::identity(len),
1446 Selection::from_indices((0..len as u32).filter(|row| row % 3 == 0).collect()),
1447 Selection::from_indices(vec![2, 5, 6, 17, 36]),
1448 Selection::empty(),
1449 ];
1450 for op in EVERY {
1451 for kept in &selections {
1452 threads(op, &left, &right, kept);
1453 threads(op, &left, &constant, kept);
1454 threads(op, &constant, &left, kept);
1455 threads(op, &left, &null_constant, kept);
1456 threads(op, &null_constant, &left, kept);
1457 threads(op, &constant, &null_constant, kept);
1458 threads(op, &dictionary, &constant, kept);
1459 threads(op, &constant, &dictionary, kept);
1460 threads(op, &dictionary, &right, kept);
1461 threads(op, &right, &dictionary, kept);
1462 }
1463 }
1464 }
1465 }
1466 }
1467
1468 #[test]
1472 fn a_second_conjunct_reads_only_what_the_first_one_left() {
1473 let numbers: Vec<Value> = (0..64).map(|row| Value::Integer(row % 10)).collect();
1474 let column = Vector::from_values(LogicalType::Integer, &numbers).expect("a flat vector");
1475 let three = Vector::constant(LogicalType::Integer, Value::Integer(3), 64);
1476 let seven = Vector::constant(LogicalType::Integer, Value::Integer(7), 64);
1477
1478 let first = refine(Comparison::Greater, &column, &three, &Selection::identity(64))
1479 .expect("compares");
1480 let both = refine(Comparison::Less, &column, &seven, &first).expect("compares");
1481
1482 let expected: Vec<u32> = (0..64)
1483 .filter(|row| {
1484 let value = row % 10;
1485 value > 3 && value < 7
1486 })
1487 .collect();
1488 assert_eq!(both.indices(), expected.as_slice());
1489 assert!(both.len() < first.len(), "the second conjunct narrowed the selection");
1490 }
1491
1492 #[test]
1496 fn a_null_row_is_not_kept_by_an_ordinary_comparison_and_is_by_a_total_one() {
1497 let column = Vector::from_values(
1498 LogicalType::Integer,
1499 &[Value::Integer(1), Value::Null, Value::Integer(3), Value::Null],
1500 )
1501 .expect("four rows");
1502 let cut = Vector::constant(LogicalType::Integer, Value::Integer(2), 4);
1503 let all = Selection::identity(4);
1504 assert_eq!(
1505 refine(Comparison::Less, &column, &cut, &all).expect("compares").indices(),
1506 &[0]
1507 );
1508 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 4);
1510 assert_eq!(
1511 refine(Comparison::NotDistinctFrom, &column, &nulls, &all).expect("compares").indices(),
1512 &[1, 3]
1513 );
1514 }
1515
1516 #[test]
1517 fn a_selection_past_the_end_is_caught() {
1518 let column = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1519 let past = Selection::from_indices(vec![0, 4]);
1520 let error = refine(Comparison::Equal, &column, &column, &past).expect_err("out of range");
1521 assert!(error.message().contains("4 row vector"), "{error}");
1522 }
1523
1524 fn sample(ty: &LogicalType, rng: &mut Rng) -> Value {
1526 match ty {
1527 LogicalType::Boolean => Value::Boolean(rng.below(2) == 1),
1528 LogicalType::TinyInt => Value::TinyInt(rng.below(7) as i8 - 3),
1529 LogicalType::SmallInt => Value::SmallInt(rng.below(11) as i16 - 5),
1530 LogicalType::Integer => Value::Integer(rng.below(9) as i32 - 4),
1531 LogicalType::BigInt => Value::BigInt(rng.below(9) as i64 - 4),
1532 LogicalType::HugeInt => Value::HugeInt(i128::from(rng.below(9)) - 4),
1533 LogicalType::UInteger => Value::UInteger(rng.below(9) as u32),
1534 LogicalType::Float => Value::Float(match rng.below(5) {
1537 0 => f32::NAN,
1538 1 => -0.0,
1539 other => other as f32 - 2.0,
1540 }),
1541 LogicalType::Double => Value::Double(match rng.below(5) {
1542 0 => f64::NAN,
1543 1 => -0.0,
1544 other => other as f64 - 2.0,
1545 }),
1546 LogicalType::Interval => match rng.below(6) {
1550 0 => Value::Interval { months: 0, days: 1, micros: 0 },
1551 1 => Value::Interval { months: 0, days: 0, micros: 86_400_000_000 },
1552 2 => Value::Interval { months: 1, days: -29, micros: 86_400_000_000 },
1553 3 => Value::Interval { months: 1, days: 0, micros: 0 },
1554 4 => Value::Interval { months: 0, days: 0, micros: 90_000_000_000 },
1555 _ => Value::Interval { months: -1, days: 0, micros: 0 },
1556 },
1557 LogicalType::Varchar => Value::Varchar(
1560 match rng.below(6) {
1561 0 => "",
1562 1 => "ab",
1563 2 => "abc",
1564 3 => "abcdefghijkl",
1565 4 => "abcdefghijklm",
1566 _ => "abcdefghijklmnopqrstuvwxyz",
1567 }
1568 .to_owned(),
1569 ),
1570 other => panic!("the generator has no values for {other}"),
1571 }
1572 }
1573
1574 #[test]
1578 fn prefix_order_is_byte_order_whenever_the_prefixes_differ() {
1579 let words =
1580 ["", "a", "ab", "abc", "abcd", "abcde", "b", "abcdefghijklmnop", "abcdefghijklmnoq"];
1581 let mut column = StringColumn::new();
1582 for word in words {
1583 column.push(word);
1584 }
1585 for (i, one) in words.iter().enumerate() {
1586 for (j, other) in words.iter().enumerate() {
1587 assert_eq!(
1588 string_order(&column, i, &column, j),
1589 one.as_bytes().cmp(other.as_bytes()),
1590 "{one:?} against {other:?}"
1591 );
1592 }
1593 }
1594 }
1595
1596 #[test]
1599 fn a_dictionary_against_a_constant_reads_its_nulls_from_the_values() {
1600 let values = Vector::from_values(
1601 LogicalType::Integer,
1602 &[Value::Integer(1), Value::Null, Value::Integer(9)],
1603 )
1604 .expect("three values");
1605 let dictionary =
1606 Vector::dictionary(vec![0, 1, 2, 1, 0], values).expect("codes are in range");
1607 let constant = Vector::constant(LogicalType::Integer, Value::Integer(5), 5);
1608 let result = compare(Comparison::Less, &dictionary, &constant).expect("compares");
1609 assert_eq!(result.value_at(0), Value::Boolean(true));
1610 assert_eq!(result.value_at(1), Value::Null);
1611 assert_eq!(result.value_at(2), Value::Boolean(false));
1612 assert_eq!(result.value_at(3), Value::Null);
1613 assert_eq!(result.value_at(4), Value::Boolean(true));
1614 }
1615
1616 #[test]
1625 fn an_ordering_on_text_against_a_literal_does_not_fall_back() {
1626 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
1627 let values = Vector::from_values(
1628 LogicalType::Varchar,
1629 &[Value::Varchar("apple".into()), Value::Null, Value::Varchar("pear".into())],
1630 )
1631 .expect("three values");
1632 let column = Vector::dictionary(vec![0, 1, 2, 0], values).expect("codes are in range");
1633 let cut = Vector::constant(LogicalType::Varchar, Value::Varchar("melon".into()), 4);
1634 let result = compare(Comparison::Less, &column, &cut).expect("compares");
1635 assert_eq!(result.value_at(0), Value::Boolean(true));
1636 assert_eq!(result.value_at(1), Value::Null);
1637 assert_eq!(result.value_at(2), Value::Boolean(false));
1638 assert_eq!(result.value_at(3), Value::Boolean(true));
1639 let other = compare(Comparison::Greater, &cut, &column).expect("compares");
1642 assert_eq!(other.value_at(0), Value::Boolean(true));
1643 assert_eq!(other.value_at(1), Value::Null);
1644 assert_eq!(other.value_at(2), Value::Boolean(false));
1645 let kept = refine(Comparison::GreaterOrEqual, &column, &cut, &Selection::identity(4))
1647 .expect("refines");
1648 assert_eq!(kept.indices(), [2]);
1649 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
1650 }
1651
1652 #[test]
1655 fn a_form_pair_with_no_loop_is_still_right_and_says_so() {
1656 let before = fallback::count(Kernel::Compare, Form::Sequence, Form::Flat);
1658 let sequence = Vector::sequence(10, 1, 4);
1659 let flat = Vector::from_values(
1660 LogicalType::BigInt,
1661 &[Value::BigInt(9), Value::BigInt(11), Value::BigInt(12), Value::Null],
1662 )
1663 .expect("four rows");
1664 let result = compare(Comparison::Less, &sequence, &flat).expect("compares");
1665 assert_eq!(result.value_at(0), Value::Boolean(false));
1666 assert_eq!(result.value_at(1), Value::Boolean(false));
1667 assert_eq!(result.value_at(2), Value::Boolean(false));
1668 assert_eq!(result.value_at(3), Value::Null);
1669 assert!(fallback::count(Kernel::Compare, Form::Sequence, Form::Flat) > before);
1670 }
1671
1672 #[test]
1682 fn a_second_level_of_codes_does_not_turn_the_loops_off() {
1683 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
1684 let values = Vector::from_values(
1685 LogicalType::Integer,
1686 &[Value::Integer(1), Value::Integer(5), Value::Integer(9)],
1687 )
1688 .expect("three rows");
1689 let once = Vector::dictionary(vec![2, 1, 0], values).expect("codes are in range");
1690 let twice = Vector::dictionary(vec![1, 2], once).expect("codes are in range");
1691 let cut = Vector::constant(LogicalType::Integer, Value::Integer(4), 2);
1692 let result = compare(Comparison::Greater, &twice, &cut).expect("compares");
1693 assert_eq!(result.value_at(0), Value::Boolean(true));
1694 assert_eq!(result.value_at(1), Value::Boolean(false));
1695 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
1696 }
1697
1698 #[test]
1702 fn a_side_that_is_entirely_null_answers_without_reading_the_other() {
1703 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 6);
1704 let flat = Vector::from_values(
1705 LogicalType::Integer,
1706 &[
1707 Value::Integer(1),
1708 Value::Integer(2),
1709 Value::Integer(3),
1710 Value::Integer(4),
1711 Value::Integer(5),
1712 Value::Integer(6),
1713 ],
1714 )
1715 .expect("six rows");
1716 agrees(Comparison::Less, &nulls, &flat);
1717 agrees(Comparison::Equal, &flat, &nulls);
1718 assert_eq!(
1719 compare(Comparison::Less, &nulls, &flat).expect("compares").validity(),
1720 &Validity::AllInvalid
1721 );
1722 }
1723
1724 #[test]
1727 fn an_empty_comparison_is_an_empty_answer() {
1728 let left = Vector::from_values(LogicalType::Integer, &[]).expect("no rows");
1729 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 0);
1730 let result = compare(Comparison::Equal, &left, &right).expect("compares");
1731 assert_eq!(result.len(), 0);
1732 }
1733
1734 fn words() -> Vector {
1737 Vector::from_values(
1738 LogicalType::Varchar,
1739 &[
1740 Value::Varchar("http://a".into()),
1741 Value::Varchar("http://b".into()),
1742 Value::Null,
1743 Value::Varchar("ab".into()),
1744 Value::Varchar("http://a".into()),
1745 Value::Varchar("z".into()),
1746 ],
1747 )
1748 .expect("six rows")
1749 }
1750
1751 #[test]
1757 fn a_literal_built_early_answers_what_one_built_here_answers() {
1758 let column = words();
1759 let value = Value::Varchar("http://b".into());
1760 let constant = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
1761 let held = Held::of(&LogicalType::Varchar, &value).expect("a varchar has a column");
1762 let kept = Selection::from_indices(vec![0, 1, 3, 5]);
1763 for op in [
1764 Comparison::Equal,
1765 Comparison::NotEqual,
1766 Comparison::Less,
1767 Comparison::LessOrEqual,
1768 Comparison::Greater,
1769 Comparison::GreaterOrEqual,
1770 Comparison::DistinctFrom,
1771 Comparison::NotDistinctFrom,
1772 ] {
1773 let prepared = compare_prepared(op, &column, &constant, Some(&held)).expect("compares");
1774 assert_eq!(prepared, compare(op, &column, &constant).expect("compares"), "{op:?}");
1775 let flipped = compare_prepared(op, &constant, &column, Some(&held)).expect("compares");
1777 assert_eq!(flipped, compare(op, &constant, &column).expect("compares"), "{op:?}");
1778 let refined =
1779 refine_prepared(op, &column, &constant, &kept, Some(&held)).expect("refines");
1780 assert_eq!(refined, refine(op, &column, &constant, &kept).expect("refines"), "{op:?}");
1781 }
1782 }
1783
1784 #[test]
1791 fn a_literal_built_for_another_value_is_ignored() {
1792 let column = words();
1793 let constant = Vector::constant(LogicalType::Varchar, Value::Varchar("z".into()), 6);
1794 let wrong = Held::of(&LogicalType::Varchar, &Value::Varchar("ab".into()))
1795 .expect("a varchar has a column");
1796 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&wrong))
1797 .expect("compares");
1798 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1799 let other = Held::of(&LogicalType::Integer, &Value::Integer(1)).expect("an integer column");
1802 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&other))
1803 .expect("compares");
1804 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1805 }
1806
1807 #[test]
1810 fn a_packed_column_against_a_constant_answers_what_the_oracle_answers() {
1811 let values: Vec<i32> = (0..64).map(|row| 1000 + (row * 37) % 500).collect();
1812 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1813 .expect("integers are an i32 layout");
1814 let packed = flat.bit_packed().expect("a five hundred wide range packs");
1815 assert_eq!(packed.form(), Form::BitPacked);
1816 for literal in [999, 1000, 1200, 1499, 1500, 2000] {
1817 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 64);
1818 for op in EVERY {
1819 agrees(op, &packed, &constant);
1820 agrees(op, &constant, &packed);
1821 }
1822 }
1823 }
1824
1825 #[test]
1829 fn a_packed_column_with_nulls_answers_what_the_oracle_answers() {
1830 let values: Vec<i32> = (0..32).map(|row| 40 + row * 3).collect();
1831 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1832 .expect("integers are an i32 layout")
1833 .with_validity(Validity::from_iter(32, |row| row % 5 != 0));
1834 let packed = flat.bit_packed().expect("packs");
1835 let constant = Vector::constant(LogicalType::Integer, Value::Integer(80), 32);
1836 for op in EVERY {
1837 agrees(op, &packed, &constant);
1838 }
1839 }
1840
1841 #[test]
1844 fn a_literal_outside_the_packed_range_answers_the_whole_vector_at_once() {
1845 let before = fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant);
1846 let values: Vec<i32> = (0..16).map(|row| 500 + row).collect();
1847 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1848 .expect("integers are an i32 layout");
1849 let packed = flat.bit_packed().expect("packs");
1850 let literals = [-1, 0, 499, 516, 100_000];
1851 for literal in literals {
1852 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 16);
1853 for op in EVERY {
1854 agrees(op, &packed, &constant);
1855 }
1856 }
1857 let total = EVERY.iter().filter(|op| op.is_total()).count();
1862 assert_eq!(
1863 fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant) - before,
1864 (literals.len() * total) as u64,
1865 "only the two total comparisons fall through"
1866 );
1867 }
1868
1869 #[test]
1872 fn refining_a_selection_over_a_packed_column_keeps_the_same_rows() {
1873 let values: Vec<i32> = (0..64).map(|row| 200 + (row * 11) % 128).collect();
1874 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.clone().into()))
1875 .expect("integers are an i32 layout");
1876 let packed = flat.bit_packed().expect("packs");
1877 let kept = Selection::from_predicate(64, |row| row % 3 == 0);
1878 let constant = Vector::constant(LogicalType::Integer, Value::Integer(260), 64);
1879 let packed_rows = refine(Comparison::Greater, &packed, &constant, &kept).expect("refines");
1880 let flat_rows = refine(Comparison::Greater, &flat, &constant, &kept).expect("refines");
1881 assert_eq!(packed_rows.indices(), flat_rows.indices());
1882 assert!(!packed_rows.is_empty(), "the literal is inside the range");
1883 }
1884
1885 fn urls(count: usize) -> Vector {
1888 let mut rng = Rng(0x5eed_1234);
1889 let values: Vec<Value> = (0..count)
1890 .map(|_| {
1891 let host = rng.below(6);
1892 let path = rng.below(40);
1893 Value::Varchar(format!("http://example{host}.test/a/rather/long/path/{path}"))
1894 })
1895 .collect();
1896 Vector::from_values(LogicalType::Varchar, &values).expect("strings")
1897 }
1898
1899 #[test]
1900 fn a_string_view_column_against_a_literal_answers_what_the_oracle_answers() {
1901 let before = fallback::count(Kernel::Compare, Form::StringView, Form::Constant);
1902 let shared = urls(64).shared_text().expect("shares");
1903 assert_eq!(shared.form(), Form::StringView);
1904 let literals = ["http://example3.test/a/rather/long/path/7", "a", "zzz", ""];
1905 for literal in literals {
1906 let value = Value::Varchar(literal.to_owned());
1907 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1908 for op in EVERY {
1909 agrees(op, &shared, &constant);
1910 agrees(op, &constant, &shared);
1911 }
1912 }
1913 assert_eq!(
1914 fallback::count(Kernel::Compare, Form::StringView, Form::Constant),
1915 before,
1916 "the form has a loop of its own for every comparison"
1917 );
1918 }
1919
1920 #[test]
1921 fn a_string_view_column_against_another_one_answers_what_the_oracle_answers() {
1922 let shared = urls(48).shared_text().expect("shares");
1923 let other = urls(48).shared_text().expect("shares");
1924 let flat = urls(48);
1925 for op in EVERY {
1926 agrees(op, &shared, &other);
1927 agrees(op, &shared, &flat);
1928 agrees(op, &flat, &shared);
1929 }
1930 }
1931
1932 #[test]
1933 fn the_nulls_of_a_string_view_column_are_the_nulls_the_oracle_sees() {
1934 let shared = urls(32)
1935 .with_validity(Validity::from_iter(32, |row| row % 4 != 1))
1936 .shared_text()
1937 .expect("shares");
1938 let constant =
1939 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 32);
1940 for op in EVERY {
1941 agrees(op, &shared, &constant);
1942 }
1943 }
1944
1945 #[test]
1946 fn a_compressed_column_against_a_literal_answers_what_the_oracle_answers() {
1947 let before = fallback::count(Kernel::Compare, Form::Fsst, Form::Constant);
1948 let flat = urls(64);
1949 let coded = flat.clone().compressed().expect("compresses");
1950 assert_eq!(coded.form(), Form::Fsst);
1951 let present = match coded.value_at(9) {
1952 Value::Varchar(text) => text,
1953 other => panic!("a string column reads back strings, not {other:?}"),
1954 };
1955 for literal in [present.as_str(), "http://example3.test/nothing/like/it", ""] {
1956 let value = Value::Varchar(literal.to_owned());
1957 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1958 for op in EVERY {
1959 agrees(op, &coded, &constant);
1960 agrees(op, &constant, &coded);
1961 }
1962 }
1963 let ordered = EVERY.len() - 2;
1967 assert_eq!(
1968 fallback::count(Kernel::Compare, Form::Fsst, Form::Constant) - before,
1969 (3 * ordered) as u64,
1970 "only the comparisons that need an order fall through"
1971 );
1972 }
1973
1974 #[test]
1977 fn every_row_of_a_compressed_column_matches_itself_and_nothing_else() {
1978 let flat = urls(48);
1979 let coded = flat.clone().compressed().expect("compresses");
1980 for row in 0..48 {
1981 let constant = Vector::constant(LogicalType::Varchar, flat.value_at(row), 48);
1982 let equal = compare(Comparison::Equal, &coded, &constant).expect("compares");
1983 for other in 0..48 {
1984 let want = flat.value_at(other) == flat.value_at(row);
1985 assert_eq!(
1986 equal.value_at(other),
1987 Value::Boolean(want),
1988 "row {row} against {other}"
1989 );
1990 }
1991 }
1992 }
1993
1994 #[test]
1995 fn the_nulls_of_a_compressed_column_are_the_nulls_the_oracle_sees() {
1996 let coded = urls(32)
1997 .with_validity(Validity::from_iter(32, |row| row % 3 != 0))
1998 .compressed()
1999 .expect("compresses");
2000 let value = coded.value_at(1);
2001 let constant = Vector::constant(LogicalType::Varchar, value, 32);
2002 for op in EVERY {
2003 agrees(op, &coded, &constant);
2004 }
2005 }
2006
2007 #[test]
2011 fn a_filter_over_either_string_form_keeps_the_same_rows() {
2012 let flat = urls(96);
2013 let shared = flat.clone().shared_text().expect("shares");
2014 let constant =
2015 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 96);
2016 let kept = Selection::from_predicate(96, |row| row % 5 != 0);
2017 for op in EVERY {
2018 let over_flat = refine(op, &flat, &constant, &kept).expect("refines");
2019 let over_shared = refine(op, &shared, &constant, &kept).expect("refines");
2020 assert_eq!(over_shared.indices(), over_flat.indices(), "{op:?}");
2021 }
2022 }
2023
2024 #[test]
2028 fn a_comparison_peeled_over_a_shared_dictionary_answers_what_the_oracle_answers() {
2029 let words = ["", "one", "two", "", "three"];
2030 let values: Vec<Value> = words.iter().map(|text| Value::Varchar((*text).into())).collect();
2031 let values = std::sync::Arc::new(
2032 Vector::from_values(LogicalType::Varchar, &values).expect("a vector of text"),
2033 );
2034 let codes = vec![0, 1, 3, 2, 0, 4, 1, 0];
2035 let column = Vector::stable_dictionary(codes.clone(), values).expect("codes are in range");
2036 same_as_the_oracle(&column);
2037 }
2038
2039 #[derive(Debug)]
2042 struct Filed {
2043 values: Vec<Vec<u8>>,
2044 order: Vec<u32>,
2045 }
2046
2047 impl rudb_vector::TextSource for Filed {
2048 fn len(&self) -> usize {
2049 self.values.len()
2050 }
2051
2052 fn bytes_at(&self, index: usize) -> Result<Option<&[u8]>> {
2053 Ok(self.values.get(index).map(Vec::as_slice))
2054 }
2055
2056 fn footprint(&self) -> usize {
2057 self.values.iter().map(Vec::len).sum()
2058 }
2059
2060 fn ranks(&self) -> Option<usize> {
2061 Some(self.order.len())
2062 }
2063
2064 fn compare_rank(&self, rank: usize, wanted: &[u8]) -> Result<Ordering> {
2065 Ok(self.values[self.order[rank] as usize].as_slice().cmp(wanted))
2068 }
2069
2070 fn code_at_rank(&self, rank: usize) -> Result<u32> {
2071 Ok(self.order[rank])
2072 }
2073 }
2074
2075 #[test]
2078 fn a_comparison_against_a_sorted_dictionary_answers_what_the_oracle_answers() {
2079 let words = ["", "one", "two", "four", "three"];
2082 let values: Vec<Vec<u8>> = words.iter().map(|text| text.as_bytes().to_vec()).collect();
2083 let mut order = (0..values.len() as u32).collect::<Vec<_>>();
2084 order.sort_by(|&left, &right| values[left as usize].cmp(&values[right as usize]));
2085 let values = Vector::external_text(
2086 LogicalType::Varchar,
2087 std::sync::Arc::new(Filed { values, order }),
2088 )
2089 .expect("a filed vector");
2090 let codes = vec![0, 1, 3, 2, 0, 4, 1, 0];
2091 let column = Vector::stable_dictionary(codes, std::sync::Arc::new(values))
2092 .expect("codes are in range");
2093 same_as_the_oracle(&column);
2094 }
2095
2096 fn same_as_the_oracle(column: &Vector) {
2100 for literal in ["", "one", "missing"] {
2101 for op in [Comparison::Equal, Comparison::NotEqual] {
2102 let value = Value::Varchar(literal.to_owned());
2103 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
2104 let right = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
2105 let wanted = oracle(op, column, &right);
2106 let got = compare_prepared(op, column, &right, Some(&held))
2107 .expect("the peeled path answers");
2108 assert_eq!(got, wanted, "{literal:?} under {op:?}");
2109 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
2111 let kept = Selection::from_predicate(column.len(), |row| row % 3 != 1);
2112 let refined = refine_prepared(op, column, &right, &kept, Some(&held))
2113 .expect("the peeled path narrows");
2114 let wanted: Vec<u32> = kept
2115 .indices()
2116 .iter()
2117 .copied()
2118 .filter(|&row| is_true(&wanted.value_at(row as usize)))
2119 .collect();
2120 assert_eq!(refined.indices(), wanted, "{literal:?} under {op:?}, narrowed");
2121 }
2122 }
2123 }
2124}