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
132pub fn compare(op: Comparison, left: &Vector, right: &Vector) -> Result<Vector> {
138 compare_prepared(op, left, right, None)
139}
140
141pub fn compare_prepared(
151 op: Comparison,
152 left: &Vector,
153 right: &Vector,
154 held: Option<&Held>,
155) -> Result<Vector> {
156 if left.len() != right.len() {
157 return Err(Error::internal(format!(
158 "a comparison of a {} row vector with a {} row one",
159 left.len(),
160 right.len()
161 )));
162 }
163 let len = left.len();
164 if left.form() == Form::Constant && right.form() == Form::Constant && len > 0 {
165 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
166 return Ok(Vector::constant(LogicalType::Boolean, single, len));
167 }
168
169 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
170 if !op.is_total()
174 && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
175 && len > 0
176 {
177 return boolean(vec![false; len], Validity::AllInvalid, len);
178 }
179
180 if let Some(answers) = external_text_literal(op, left, right, len, identity, held)? {
181 let validity = left_valid.and(&right_valid, len);
182 return boolean(blank_the_nulls(answers, &validity), validity, len);
183 }
184 if let Some(answers) =
185 specialized(op, left, right, &left_valid, &right_valid, len, identity, held)
186 {
187 let validity =
188 if op.is_total() { Validity::AllValid } else { left_valid.and(&right_valid, len) };
189 return boolean(blank_the_nulls(answers, &validity), validity, len);
190 }
191
192 fallback::record(Kernel::Compare, left.form(), right.form());
193 let mut values = Vec::with_capacity(len);
194 for index in 0..len {
197 values.push(compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?);
198 }
199 Vector::from_values(LogicalType::Boolean, &values)
200}
201
202pub fn refine(
220 op: Comparison,
221 left: &Vector,
222 right: &Vector,
223 kept: &Selection,
224) -> Result<Selection> {
225 refine_prepared(op, left, right, kept, None)
226}
227
228pub fn refine_prepared(
238 op: Comparison,
239 left: &Vector,
240 right: &Vector,
241 kept: &Selection,
242 held: Option<&Held>,
243) -> Result<Selection> {
244 if left.len() != right.len() {
245 return Err(Error::internal(format!(
246 "a comparison of a {} row vector with a {} row one",
247 left.len(),
248 right.len()
249 )));
250 }
251 let len = left.len();
252 if kept.indices().iter().any(|&row| row as usize >= len) {
256 return Err(Error::internal(format!("a selection past the end of a {len} row vector")));
257 }
258 if kept.is_empty() {
259 return Ok(Selection::empty());
260 }
261 if left.form() == Form::Constant && right.form() == Form::Constant {
262 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
263 return Ok(if is_true(&single) { kept.clone() } else { Selection::empty() });
264 }
265
266 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
267 if !op.is_total() && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
268 {
269 return Ok(Selection::empty());
270 }
271
272 let rows = kept.indices();
273 let map = |slot: usize| rows[slot] as usize;
274 if let Some(answers) = external_text_literal(op, left, right, kept.len(), map, held)? {
275 return Ok(narrowed(&answers, rows, |slot| {
276 let row = rows[slot] as usize;
277 left_valid.is_valid(row) && right_valid.is_valid(row)
278 }));
279 }
280 if let Some(answers) =
281 specialized(op, left, right, &left_valid, &right_valid, kept.len(), map, held)
282 {
283 if op.is_total() || (left_valid == Validity::AllValid && right_valid == Validity::AllValid)
286 {
287 return Ok(narrowed(&answers, rows, |_| true));
288 }
289 return Ok(narrowed(&answers, rows, |slot| {
293 let row = rows[slot] as usize;
294 left_valid.is_valid(row) && right_valid.is_valid(row)
295 }));
296 }
297
298 fallback::record(Kernel::Compare, left.form(), right.form());
299 let mut out = Vec::with_capacity(kept.len());
300 for &row in rows {
303 let index = row as usize;
304 if is_true(&compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?) {
305 out.push(row);
306 }
307 }
308 Ok(Selection::from_indices(out))
309}
310
311fn external_text_literal<M>(
318 op: Comparison,
319 left: &Vector,
320 right: &Vector,
321 len: usize,
322 map: M,
323 held: Option<&Held>,
324) -> Result<Option<Vec<bool>>>
325where
326 M: Fn(usize) -> usize + Copy,
327{
328 if !matches!(op, Comparison::Equal | Comparison::NotEqual)
329 || left.logical_type() != &LogicalType::Varchar
330 || right.logical_type() != &LogicalType::Varchar
331 {
332 return Ok(None);
333 }
334 let (column, literal, swapped) = match (left.constant_value(), right.constant_value()) {
335 (None, Some(Value::Varchar(literal))) if left.positions().is_some() => {
336 (left, literal.as_bytes(), false)
337 }
338 (Some(Value::Varchar(literal)), None) if right.positions().is_some() => {
339 (right, literal.as_bytes(), true)
340 }
341 _ => return Ok(None),
342 };
343 let same = if swapped { op.swapped() } else { op } == Comparison::Equal;
344 if let Some(held) = held.filter(|held| held.text() == Some(literal)) {
348 if let Some(found) = held.lookup().find(column, literal) {
351 return Ok(Some(against_code(column, found?, len, map, same)?));
352 }
353 let decide = |dictionary: &Vector, code: usize| -> Result<bool> {
354 let found = if literal.is_empty() {
355 dictionary.try_bytes_len_at(code)?.is_some_and(|length| length == 0)
356 } else {
357 dictionary.try_bytes_at(code)?.is_some_and(|bytes| bytes == literal)
358 };
359 Ok(found)
360 };
361 if let Some(answers) = held.peel().answer(column, len, map, decide) {
362 let mut answers = answers?;
363 if !same {
364 for answer in &mut answers {
365 *answer = !*answer;
366 }
367 }
368 return Ok(Some(answers));
369 }
370 }
371 let mut answers = Vec::with_capacity(len);
372 for slot in 0..len {
373 let row = map(slot);
374 let equal = if literal.is_empty() {
375 column.try_bytes_len_at(row)?.is_some_and(|length| length == 0)
376 } else {
377 column.try_bytes_at(row)?.is_some_and(|bytes| bytes == literal)
378 };
379 answers.push(equal == same);
380 }
381 Ok(Some(answers))
382}
383
384fn against_code<M>(
392 column: &Vector,
393 found: Found,
394 len: usize,
395 map: M,
396 same: bool,
397) -> Result<Vec<bool>>
398where
399 M: Fn(usize) -> usize,
400{
401 let Found::At(wanted) = found else { return Ok(vec![!same; len]) };
402 let (codes, _) = column
403 .shared_dictionary_parts()
404 .ok_or_else(|| Error::internal("a resolved literal lost the codes it was resolved for"))?;
405 let mut answers = Vec::with_capacity(len);
406 for slot in 0..len {
408 let code = *codes
409 .get(map(slot))
410 .ok_or_else(|| Error::internal("a compared row is past the end of its codes"))?;
411 answers.push((code == wanted) == same);
412 }
413 Ok(answers)
414}
415
416fn narrowed<L: Fn(usize) -> bool>(answers: &[bool], rows: &[u32], live: L) -> Selection {
423 let mut out = vec![0_u32; answers.len()];
424 let mut count = 0;
425 for (slot, &answer) in answers.iter().enumerate() {
426 out[count] = rows[slot];
427 count += usize::from(answer & live(slot));
429 }
430 out.truncate(count);
431 Selection::from_indices(out)
432}
433
434fn boolean(answers: Vec<bool>, validity: Validity, len: usize) -> Result<Vector> {
436 let validity = if len == 0 { Validity::AllValid } else { validity.normalize(len) };
440 Ok(Vector::flat(LogicalType::Boolean, Data::Bool(answers.into()))?.with_validity(validity))
441}
442
443fn blank_the_nulls(mut answers: Vec<bool>, validity: &Validity) -> Vec<bool> {
451 if let Validity::Mask(mask) = validity {
452 for (index, answer) in answers.iter_mut().enumerate() {
453 if !mask.get(index) {
454 *answer = false;
455 }
456 }
457 }
458 answers
459}
460
461#[expect(
473 clippy::too_many_arguments,
474 reason = "two sides, two validities, the operator, the length, the index mapping and the \
475 literal that was built early, all of which the branches below need"
476)]
477fn specialized<M>(
478 op: Comparison,
479 left: &Vector,
480 right: &Vector,
481 left_valid: &Validity,
482 right_valid: &Validity,
483 len: usize,
484 map: M,
485 held: Option<&Held>,
486) -> Option<Vec<bool>>
487where
488 M: Fn(usize) -> usize + Copy,
489{
490 if left.logical_type() != right.logical_type() {
494 return None;
495 }
496
497 if let (Some(one), Some(other)) = (left.data(), right.data()) {
498 return dispatch(op, len, one, map, other, map, left_valid, right_valid, map);
499 }
500 if !op.is_total() {
506 if let (Some(packed), Some(value)) = (left.packed_parts(), right.constant_value()) {
507 let wanted = exact(held, left.logical_type(), value)?;
508 return Some(packed_against(op, &packed, wanted, len, map));
509 }
510 if let (Some(value), Some(packed)) = (left.constant_value(), right.packed_parts()) {
511 let wanted = exact(held, right.logical_type(), value)?;
512 return Some(packed_against(op.swapped(), &packed, wanted, len, map));
513 }
514 }
515 if let (Some(one), Some(value)) = (left.data(), right.constant_value()) {
516 let column = readied(held, left.logical_type(), value)?;
517 let other = column.data()?;
518 return dispatch(op, len, one, map, other, first, left_valid, right_valid, map);
519 }
520 if let (Some(value), Some(other)) = (left.constant_value(), right.data()) {
521 let column = readied(held, right.logical_type(), value)?;
523 let one = column.data()?;
524 return dispatch(op.swapped(), len, other, map, one, first, right_valid, left_valid, map);
525 }
526 if matches!(op, Comparison::Equal | Comparison::NotEqual) {
531 if let (Some(coded), Some(value)) = (left.coded_parts(), right.constant_value()) {
532 let wanted = encoded(&coded, held, left.logical_type(), value)?;
533 return Some(coded_against(op, &coded, &wanted, len, map));
534 }
535 if let (Some(value), Some(coded)) = (left.constant_value(), right.coded_parts()) {
536 let wanted = encoded(&coded, held, right.logical_type(), value)?;
537 return Some(coded_against(op, &coded, &wanted, len, map));
538 }
539 }
540 if let (Some((one, one_arena)), Some((other, other_arena))) =
546 (left.text_parts(), right.text_parts())
547 {
548 return Some(sweep(
549 op,
550 len,
551 |index| view_order(one.get(map(index)), one_arena, other.get(map(index)), other_arena),
552 left_valid,
553 right_valid,
554 map,
555 ));
556 }
557 if let (Some((one, one_arena)), Some(value)) = (left.text_parts(), right.constant_value()) {
561 let column = readied(held, left.logical_type(), value)?;
562 let (other, other_arena) = column.text_parts()?;
563 let wanted = other.first();
564 return Some(sweep(
565 op,
566 len,
567 |index| view_order(one.get(map(index)), one_arena, wanted, other_arena),
568 left_valid,
569 right_valid,
570 map,
571 ));
572 }
573 if let (Some(value), Some((other, other_arena))) = (left.constant_value(), right.text_parts()) {
574 let column = readied(held, right.logical_type(), value)?;
576 let (one, one_arena) = column.text_parts()?;
577 let wanted = one.first();
578 return Some(sweep(
579 op.swapped(),
580 len,
581 |index| view_order(other.get(map(index)), other_arena, wanted, one_arena),
582 right_valid,
583 left_valid,
584 map,
585 ));
586 }
587 if let (Some((codes, values)), Some(value)) = (left.positions(), right.constant_value()) {
588 let one = values.data()?;
589 let column = readied(held, left.logical_type(), value)?;
590 let other = column.data()?;
591 let at = |index: usize| codes[map(index)] as usize;
592 return dispatch(op, len, one, at, other, first, left_valid, right_valid, map);
593 }
594 if let (Some(value), Some((codes, values))) = (left.constant_value(), right.positions()) {
595 let other = values.data()?;
596 let column = readied(held, right.logical_type(), value)?;
597 let one = column.data()?;
598 let at = |index: usize| codes[map(index)] as usize;
599 return dispatch(op.swapped(), len, other, at, one, first, right_valid, left_valid, map);
600 }
601 if let (Some((codes, values)), Some(other)) = (left.positions(), right.data()) {
607 let one = values.data()?;
608 let at = |index: usize| codes[map(index)] as usize;
609 return dispatch(op, len, one, at, other, map, left_valid, right_valid, map);
610 }
611 if let (Some(one), Some((codes, values))) = (left.data(), right.positions()) {
612 let other = values.data()?;
613 let at = |index: usize| codes[map(index)] as usize;
614 return dispatch(op.swapped(), len, other, at, one, map, right_valid, left_valid, map);
615 }
616 None
617}
618
619fn exact(held: Option<&Held>, ty: &LogicalType, value: &Value) -> Option<i128> {
626 let column = readied(held, ty, value)?;
627 let data = column.data()?;
628 data.signed_at(0).or_else(|| data.unsigned_at(0).and_then(|value| i128::try_from(value).ok()))
629}
630
631fn encoded(
637 coded: &Coded<'_>,
638 held: Option<&Held>,
639 ty: &LogicalType,
640 value: &Value,
641) -> Option<Vec<u8>> {
642 let column = readied(held, ty, value)?;
643 let (views, arena) = column.text_parts()?;
644 Some(coded.encode(views.first()?.bytes_in(arena)?))
645}
646
647fn coded_against<M>(
653 op: Comparison,
654 coded: &Coded<'_>,
655 wanted: &[u8],
656 len: usize,
657 map: M,
658) -> Vec<bool>
659where
660 M: Fn(usize) -> usize + Copy,
661{
662 let same = op == Comparison::Equal;
663 let mut answers = Vec::with_capacity(len);
664 for row in 0..len {
665 answers.push((coded.row(map(row)) == Some(wanted)) == same);
666 }
667 answers
668}
669
670fn packed_against<M>(
676 op: Comparison,
677 packed: &Packed<'_>,
678 wanted: i128,
679 len: usize,
680 map: M,
681) -> Vec<bool>
682where
683 M: Fn(usize) -> usize + Copy,
684{
685 let Some(code) = packed.code_of(wanted) else {
686 let above = wanted > packed.ceiling();
689 let same = match op {
690 Comparison::Equal | Comparison::NotDistinctFrom => false,
691 Comparison::NotEqual | Comparison::DistinctFrom => true,
692 Comparison::Less | Comparison::LessOrEqual => above,
693 Comparison::Greater | Comparison::GreaterOrEqual => !above,
694 };
695 return vec![same; len];
696 };
697 let test: fn(u64, u64) -> bool = match op {
700 Comparison::Equal | Comparison::NotDistinctFrom => |found, want| found == want,
701 Comparison::NotEqual | Comparison::DistinctFrom => |found, want| found != want,
702 Comparison::Less => |found, want| found < want,
703 Comparison::LessOrEqual => |found, want| found <= want,
704 Comparison::Greater => |found, want| found > want,
705 Comparison::GreaterOrEqual => |found, want| found >= want,
706 };
707 let mut answers = Vec::with_capacity(len);
708 for row in 0..len {
709 answers.push(test(packed.code(map(row)), code));
710 }
711 answers
712}
713
714#[expect(
720 clippy::too_many_arguments,
721 reason = "two sides with an index each, the operator, the length and two validities, all of \
722 which the loop needs and none of which is worth a struct that exists for one call"
723)]
724fn dispatch<L, R, V>(
725 op: Comparison,
726 len: usize,
727 left: &Data,
728 at_left: L,
729 right: &Data,
730 at_right: R,
731 left_valid: &Validity,
732 right_valid: &Validity,
733 at_valid: V,
734) -> Option<Vec<bool>>
735where
736 L: Fn(usize) -> usize,
737 R: Fn(usize) -> usize,
738 V: Fn(usize) -> usize,
739{
740 macro_rules! layouts {
741 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
742 match (left, right) {
743 $(
744 (Data::$variant(one), Data::$variant(other)) => Some(sweep(
745 op,
746 len,
747 |index| one[at_left(index)].cmp(&other[at_right(index)]),
748 left_valid,
749 right_valid,
750 &at_valid,
751 )),
752 )+
753 (Data::Float32(one), Data::Float32(other)) => Some(sweep(
756 op,
757 len,
758 |index| {
759 float_order(
760 f64::from(one[at_left(index)]),
761 f64::from(other[at_right(index)]),
762 )
763 },
764 left_valid,
765 right_valid,
766 &at_valid,
767 )),
768 (Data::Float64(one), Data::Float64(other)) => Some(sweep(
769 op,
770 len,
771 |index| float_order(one[at_left(index)], other[at_right(index)]),
772 left_valid,
773 right_valid,
774 &at_valid,
775 )),
776 (Data::Interval(one), Data::Interval(other)) => Some(sweep(
779 op,
780 len,
781 |index| {
782 let (months, days, micros) = one[at_left(index)];
783 let (bm, bd, bu) = other[at_right(index)];
784 interval_micros(months, days, micros).cmp(&interval_micros(bm, bd, bu))
785 },
786 left_valid,
787 right_valid,
788 &at_valid,
789 )),
790 (Data::Varlen(one), Data::Varlen(other)) => Some(sweep(
791 op,
792 len,
793 |index| string_order(one, at_left(index), other, at_right(index)),
794 left_valid,
795 right_valid,
796 &at_valid,
797 )),
798 _ => None,
799 }
800 };
801 }
802 rudb_vector::for_each_layout!(ordered, layouts)
803}
804
805fn readied<'a>(held: Option<&'a Held>, ty: &LogicalType, value: &Value) -> Option<Cow<'a, Vector>> {
811 match held {
812 Some(held) if held.matches(ty, value) => Some(Cow::Borrowed(held.single())),
813 _ => Some(Cow::Owned(single(ty, value)?)),
814 }
815}
816
817fn string_order(
825 left: &StringColumn,
826 at_left: usize,
827 right: &StringColumn,
828 at_right: usize,
829) -> Ordering {
830 view_order(left.views().get(at_left), left.arena(), right.views().get(at_right), right.arena())
831}
832
833fn view_order(
839 one: Option<&StringView>,
840 one_arena: &[u8],
841 other: Option<&StringView>,
842 other_arena: &[u8],
843) -> Ordering {
844 let (Some(one), Some(other)) = (one, other) else {
845 return Ordering::Equal;
846 };
847 let (prefix, against) = (one.prefix(), other.prefix());
848 if prefix != against {
849 return prefix.cmp(&against);
850 }
851 let bytes = one.bytes_in(one_arena).unwrap_or_default();
856 let against_bytes = other.bytes_in(other_arena).unwrap_or_default();
857 bytes.cmp(against_bytes)
858}
859
860fn sweep<O, V>(
866 op: Comparison,
867 len: usize,
868 order_at: O,
869 left_valid: &Validity,
870 right_valid: &Validity,
871 at_valid: V,
872) -> Vec<bool>
873where
874 O: Fn(usize) -> Ordering,
875 V: Fn(usize) -> usize,
876{
877 let mut answers = vec![false; len];
878 match op {
879 Comparison::Equal => fill(&mut answers, order_at, |o| o == Ordering::Equal),
880 Comparison::NotEqual => fill(&mut answers, order_at, |o| o != Ordering::Equal),
881 Comparison::Less => fill(&mut answers, order_at, |o| o == Ordering::Less),
882 Comparison::LessOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Greater),
883 Comparison::Greater => fill(&mut answers, order_at, |o| o == Ordering::Greater),
884 Comparison::GreaterOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Less),
885 Comparison::DistinctFrom => {
886 total(&mut answers, order_at, left_valid, right_valid, at_valid);
887 for answer in &mut answers {
888 *answer = !*answer;
889 }
890 }
891 Comparison::NotDistinctFrom => {
892 total(&mut answers, order_at, left_valid, right_valid, at_valid);
893 }
894 }
895 answers
896}
897
898#[inline]
900fn fill<O, H>(answers: &mut [bool], order_at: O, held: H)
901where
902 O: Fn(usize) -> Ordering,
903 H: Fn(Ordering) -> bool,
904{
905 for (index, answer) in answers.iter_mut().enumerate() {
906 *answer = held(order_at(index));
907 }
908}
909
910fn total<O, V>(
917 answers: &mut [bool],
918 order_at: O,
919 left_valid: &Validity,
920 right_valid: &Validity,
921 at_valid: V,
922) where
923 O: Fn(usize) -> Ordering,
924 V: Fn(usize) -> usize,
925{
926 if *left_valid == Validity::AllValid && *right_valid == Validity::AllValid {
927 fill(answers, order_at, |o| o == Ordering::Equal);
928 return;
929 }
930 for (index, answer) in answers.iter_mut().enumerate() {
931 let row = at_valid(index);
932 *answer = match (left_valid.is_valid(row), right_valid.is_valid(row)) {
933 (true, true) => order_at(index) == Ordering::Equal,
934 (false, false) => true,
935 _ => false,
936 };
937 }
938}
939
940pub fn compare_values(op: Comparison, left: &Value, right: &Value) -> Result<Value> {
946 if op.is_total() {
947 let same = match (left.is_null(), right.is_null()) {
948 (true, true) => true,
949 (true, false) | (false, true) => false,
950 (false, false) => order(left, right)? == Ordering::Equal,
951 };
952 return Ok(Value::Boolean(match op {
953 Comparison::NotDistinctFrom => same,
954 _ => !same,
955 }));
956 }
957 if left.is_null() || right.is_null() {
958 return Ok(Value::Null);
959 }
960 let ordering = order(left, right)?;
961 let held = match op {
962 Comparison::Equal => ordering == Ordering::Equal,
963 Comparison::NotEqual => ordering != Ordering::Equal,
964 Comparison::Less => ordering == Ordering::Less,
965 Comparison::LessOrEqual => ordering != Ordering::Greater,
966 Comparison::Greater => ordering == Ordering::Greater,
967 Comparison::GreaterOrEqual => ordering != Ordering::Less,
968 Comparison::DistinctFrom | Comparison::NotDistinctFrom => {
969 return Err(Error::internal("a total comparison reached the ordered path"));
970 }
971 };
972 Ok(Value::Boolean(held))
973}
974
975pub fn order(left: &Value, right: &Value) -> Result<Ordering> {
986 match (left, right) {
987 (Value::Null, _) | (_, Value::Null) => {
988 Err(Error::internal("a null reached the ordering path"))
989 }
990 (Value::Boolean(a), Value::Boolean(b)) => Ok(a.cmp(b)),
991 (Value::Varchar(a), Value::Varchar(b)) => Ok(a.as_bytes().cmp(b.as_bytes())),
992 (Value::Blob(a), Value::Blob(b)) => Ok(a.cmp(b)),
993 (Value::Date(a), Value::Date(b)) => Ok(a.cmp(b)),
994 (Value::Time(a), Value::Time(b))
997 | (Value::TimeTz(a), Value::TimeTz(b))
998 | (Value::Timestamp(a), Value::Timestamp(b))
999 | (Value::TimestampTz(a), Value::TimestampTz(b)) => Ok(a.cmp(b)),
1000 (
1001 Value::Interval { months: am, days: ad, micros: au },
1002 Value::Interval { months: bm, days: bd, micros: bu },
1003 ) => Ok(interval_micros(*am, *ad, *au).cmp(&interval_micros(*bm, *bd, *bu))),
1004 _ => numeric_order(left, right),
1005 }
1006}
1007
1008fn numeric_order(left: &Value, right: &Value) -> Result<Ordering> {
1010 if let (Some(a), Some(b)) = (integral(left), integral(right)) {
1011 return Ok(a.cmp(&b));
1012 }
1013 if let (
1014 Value::Decimal { unscaled: a, scale: sa, .. },
1015 Value::Decimal { unscaled: b, scale: sb, .. },
1016 ) = (left, right)
1017 {
1018 if sa == sb {
1019 return Ok(a.cmp(b));
1020 }
1021 }
1022 match (approximate(left), approximate(right)) {
1023 (Some(a), Some(b)) => Ok(float_order(a, b)),
1024 _ => Err(Error::not_implemented(format!(
1025 "comparing {} with {}",
1026 left.logical_type(),
1027 right.logical_type()
1028 ))),
1029 }
1030}
1031
1032fn float_order(left: f64, right: f64) -> Ordering {
1034 if left == right {
1035 return Ordering::Equal;
1036 }
1037 match (left.is_nan(), right.is_nan()) {
1038 (true, true) => Ordering::Equal,
1039 (true, false) => Ordering::Greater,
1040 (false, true) => Ordering::Less,
1041 (false, false) => left.partial_cmp(&right).unwrap_or(Ordering::Equal),
1042 }
1043}
1044
1045pub fn order_with_nulls(left: &Value, right: &Value, nulls_first: bool) -> Result<Ordering> {
1054 match (left.is_null(), right.is_null()) {
1055 (true, true) => Ok(Ordering::Equal),
1056 (true, false) => Ok(if nulls_first { Ordering::Less } else { Ordering::Greater }),
1057 (false, true) => Ok(if nulls_first { Ordering::Greater } else { Ordering::Less }),
1058 (false, false) => order(left, right),
1059 }
1060}
1061
1062#[cfg(test)]
1063mod tests {
1064 use super::*;
1065
1066 fn compared(op: Comparison, left: Value, right: Value) -> Value {
1067 compare_values(op, &left, &right).expect("these types compare")
1068 }
1069
1070 const EVERY: [Comparison; 8] = [
1072 Comparison::Equal,
1073 Comparison::NotEqual,
1074 Comparison::Less,
1075 Comparison::LessOrEqual,
1076 Comparison::Greater,
1077 Comparison::GreaterOrEqual,
1078 Comparison::DistinctFrom,
1079 Comparison::NotDistinctFrom,
1080 ];
1081
1082 fn oracle(op: Comparison, left: &Vector, right: &Vector) -> Vector {
1088 let values: Vec<Value> = (0..left.len())
1089 .map(|index| {
1090 compare_values(op, &left.value_at(index), &right.value_at(index))
1091 .expect("the oracle is only asked about types that compare")
1092 })
1093 .collect();
1094 Vector::from_values(LogicalType::Boolean, &values).expect("booleans")
1095 }
1096
1097 fn agrees(op: Comparison, left: &Vector, right: &Vector) {
1101 let fast = compare(op, left, right).expect("compares");
1102 let slow = oracle(op, left, right);
1103 assert_eq!(fast, slow, "{op:?} on a {:?} against a {:?}", left.form(), right.form());
1104 }
1105
1106 struct Rng(u64);
1109
1110 impl Rng {
1111 fn next(&mut self) -> u64 {
1112 self.0 ^= self.0 << 13;
1113 self.0 ^= self.0 >> 7;
1114 self.0 ^= self.0 << 17;
1115 self.0
1116 }
1117
1118 fn below(&mut self, bound: u64) -> u64 {
1119 self.next() % bound
1120 }
1121 }
1122
1123 #[test]
1124 fn an_ordinary_comparison_is_null_when_either_side_is() {
1125 assert_eq!(compared(Comparison::Equal, Value::Integer(1), Value::Null), Value::Null);
1126 assert_eq!(compared(Comparison::Less, Value::Null, Value::Integer(1)), Value::Null);
1127 }
1128
1129 #[test]
1130 fn a_total_comparison_is_never_null() {
1131 assert_eq!(
1132 compared(Comparison::NotDistinctFrom, Value::Null, Value::Null),
1133 Value::Boolean(true)
1134 );
1135 assert_eq!(
1136 compared(Comparison::NotDistinctFrom, Value::Integer(1), Value::Null),
1137 Value::Boolean(false)
1138 );
1139 assert_eq!(
1140 compared(Comparison::DistinctFrom, Value::Integer(1), Value::Null),
1141 Value::Boolean(true)
1142 );
1143 }
1144
1145 #[test]
1146 fn a_string_compares_by_bytes() {
1147 assert_eq!(
1148 compared(Comparison::Less, Value::Varchar("a".into()), Value::Varchar("b".into())),
1149 Value::Boolean(true)
1150 );
1151 assert_eq!(
1152 compared(Comparison::Less, Value::Varchar("Z".into()), Value::Varchar("a".into())),
1153 Value::Boolean(true)
1154 );
1155 }
1156
1157 #[test]
1160 fn two_nans_are_one_value_and_they_sort_above_the_numbers() {
1161 assert_eq!(
1162 compared(Comparison::Equal, Value::Double(f64::NAN), Value::Double(f64::NAN)),
1163 Value::Boolean(true)
1164 );
1165 assert_eq!(
1166 compared(Comparison::Greater, Value::Double(f64::NAN), Value::Double(1e300)),
1167 Value::Boolean(true)
1168 );
1169 }
1170
1171 #[test]
1172 fn zero_has_one_value_however_it_is_signed() {
1173 assert_eq!(
1174 compared(Comparison::Equal, Value::Double(0.0), Value::Double(-0.0)),
1175 Value::Boolean(true)
1176 );
1177 }
1178
1179 #[test]
1184 fn two_intervals_of_the_same_length_are_one_value() {
1185 let day = Value::Interval { months: 0, days: 1, micros: 0 };
1186 let hours = Value::Interval { months: 0, days: 0, micros: 86_400_000_000 };
1187 let month = Value::Interval { months: 1, days: 0, micros: 0 };
1188 let thirty = Value::Interval { months: 0, days: 30, micros: 0 };
1189 let long_day = Value::Interval { months: 0, days: 0, micros: 90_000_000_000 };
1190 assert_eq!(compared(Comparison::Equal, day.clone(), hours), Value::Boolean(true));
1191 assert_eq!(compared(Comparison::Equal, month, thirty), Value::Boolean(true));
1192 assert_eq!(compared(Comparison::Greater, long_day, day), Value::Boolean(true));
1193 }
1194
1195 #[test]
1196 fn a_number_compares_the_same_however_it_is_stored() {
1197 assert_eq!(
1198 compared(Comparison::Equal, Value::Integer(3), Value::BigInt(3)),
1199 Value::Boolean(true)
1200 );
1201 assert_eq!(
1202 compared(Comparison::Less, Value::Integer(3), Value::Double(3.5)),
1203 Value::Boolean(true)
1204 );
1205 }
1206
1207 #[test]
1208 fn nulls_go_where_the_query_asked_for_them() {
1209 assert_eq!(
1210 order_with_nulls(&Value::Null, &Value::Integer(1), true).expect("orders"),
1211 Ordering::Less
1212 );
1213 assert_eq!(
1214 order_with_nulls(&Value::Null, &Value::Integer(1), false).expect("orders"),
1215 Ordering::Greater
1216 );
1217 }
1218
1219 #[test]
1220 fn two_constant_vectors_cost_one_comparison() {
1221 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 512);
1222 let right = Vector::constant(LogicalType::Integer, Value::Integer(2), 512);
1223 let result = compare(Comparison::Less, &left, &right).expect("compares");
1224 assert_eq!(result.form(), Form::Constant);
1225 assert_eq!(result.value_at(500), Value::Boolean(true));
1226 }
1227
1228 #[test]
1229 fn a_comparison_of_two_vectors_is_one_answer_per_row() {
1230 let left = Vector::from_values(
1231 LogicalType::Integer,
1232 &[Value::Integer(1), Value::Integer(5), Value::Null],
1233 )
1234 .expect("three rows");
1235 let right = Vector::constant(LogicalType::Integer, Value::Integer(3), 3);
1236 let result = compare(Comparison::Greater, &left, &right).expect("compares");
1237 assert_eq!(result.value_at(0), Value::Boolean(false));
1238 assert_eq!(result.value_at(1), Value::Boolean(true));
1239 assert_eq!(result.value_at(2), Value::Null);
1240 }
1241
1242 #[test]
1243 fn two_vectors_of_different_lengths_are_caught() {
1244 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1245 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 5);
1246 let error = compare(Comparison::Equal, &left, &right).expect_err("ragged");
1247 assert!(error.message().contains("4 row vector"), "{error}");
1248 }
1249
1250 #[test]
1251 fn turning_a_comparison_around_is_what_the_other_side_would_have_said() {
1252 for op in EVERY {
1253 let left = Value::Integer(3);
1254 let right = Value::Integer(7);
1255 assert_eq!(
1256 compare_values(op, &left, &right).expect("compares"),
1257 compare_values(op.swapped(), &right, &left).expect("compares"),
1258 "{op:?}"
1259 );
1260 }
1261 }
1262
1263 #[test]
1266 fn every_specialized_path_agrees_with_the_row_at_a_time_path() {
1267 let mut rng = Rng(0x5eed_1234_9876_4321);
1268 let types: [LogicalType; 11] = [
1269 LogicalType::Boolean,
1270 LogicalType::TinyInt,
1271 LogicalType::SmallInt,
1272 LogicalType::Integer,
1273 LogicalType::BigInt,
1274 LogicalType::HugeInt,
1275 LogicalType::UInteger,
1276 LogicalType::Float,
1277 LogicalType::Double,
1278 LogicalType::Varchar,
1279 LogicalType::Interval,
1280 ];
1281 for ty in &types {
1282 for nulls in [0u64, 1, 3] {
1283 let len = 37;
1284 let make = |rng: &mut Rng| {
1285 let values: Vec<Value> = (0..len)
1286 .map(|_| {
1287 if nulls > 0 && rng.below(nulls + 1) == 0 {
1288 Value::Null
1289 } else {
1290 sample(ty, rng)
1291 }
1292 })
1293 .collect();
1294 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1295 };
1296 let left = make(&mut rng);
1297 let right = make(&mut rng);
1298 let literal = sample(ty, &mut rng);
1299 let constant = Vector::constant(ty.clone(), literal, len);
1300 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1301 let codes: Vec<u32> =
1302 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1303 let dictionary =
1304 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1305 let ends: Vec<u32> = (1..=left.len())
1308 .map(|run| ((run * len) / left.len()).max(run) as u32)
1309 .collect();
1310 let runs = Vector::runs(ends, left.clone()).expect("one value for each run");
1311
1312 for op in EVERY {
1313 agrees(op, &left, &right);
1314 agrees(op, &left, &constant);
1315 agrees(op, &constant, &left);
1316 agrees(op, &left, &null_constant);
1317 agrees(op, &null_constant, &left);
1318 agrees(op, &dictionary, &constant);
1319 agrees(op, &constant, &dictionary);
1320 agrees(op, &dictionary, &right);
1324 agrees(op, &right, &dictionary);
1325 agrees(op, &runs, &constant);
1329 agrees(op, &constant, &runs);
1330 agrees(op, &runs, &right);
1331 agrees(op, &right, &runs);
1332 }
1333 }
1334 }
1335 }
1336
1337 fn refined(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) -> Selection {
1339 let mut out = Vec::new();
1340 for &row in kept.indices() {
1341 let index = row as usize;
1342 let answer = compare_values(op, &left.value_at(index), &right.value_at(index))
1343 .expect("the oracle is only asked about types that compare");
1344 if is_true(&answer) {
1345 out.push(row);
1346 }
1347 }
1348 Selection::from_indices(out)
1349 }
1350
1351 fn threads(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) {
1352 let fast = refine(op, left, right, kept).expect("compares");
1353 assert_eq!(
1354 fast,
1355 refined(op, left, right, kept),
1356 "{op:?} on a {:?} against a {:?} over {} rows",
1357 left.form(),
1358 right.form(),
1359 kept.len()
1360 );
1361 }
1362
1363 #[test]
1367 fn a_threaded_comparison_keeps_what_the_row_at_a_time_path_keeps() {
1368 let mut rng = Rng(0x5eed_4321_1234_9876);
1369 let types = [LogicalType::Integer, LogicalType::Double, LogicalType::Varchar];
1370 for ty in &types {
1371 for nulls in [0u64, 1, 3] {
1372 let len = 37;
1373 let make = |rng: &mut Rng| {
1374 let values: Vec<Value> = (0..len)
1375 .map(|_| {
1376 if nulls > 0 && rng.below(nulls + 1) == 0 {
1377 Value::Null
1378 } else {
1379 sample(ty, rng)
1380 }
1381 })
1382 .collect();
1383 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1384 };
1385 let left = make(&mut rng);
1386 let right = make(&mut rng);
1387 let constant = Vector::constant(ty.clone(), sample(ty, &mut rng), len);
1388 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1389 let codes: Vec<u32> =
1390 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1391 let dictionary =
1392 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1393
1394 let selections = [
1398 Selection::identity(len),
1399 Selection::from_indices((0..len as u32).filter(|row| row % 3 == 0).collect()),
1400 Selection::from_indices(vec![2, 5, 6, 17, 36]),
1401 Selection::empty(),
1402 ];
1403 for op in EVERY {
1404 for kept in &selections {
1405 threads(op, &left, &right, kept);
1406 threads(op, &left, &constant, kept);
1407 threads(op, &constant, &left, kept);
1408 threads(op, &left, &null_constant, kept);
1409 threads(op, &null_constant, &left, kept);
1410 threads(op, &constant, &null_constant, kept);
1411 threads(op, &dictionary, &constant, kept);
1412 threads(op, &constant, &dictionary, kept);
1413 threads(op, &dictionary, &right, kept);
1414 threads(op, &right, &dictionary, kept);
1415 }
1416 }
1417 }
1418 }
1419 }
1420
1421 #[test]
1425 fn a_second_conjunct_reads_only_what_the_first_one_left() {
1426 let numbers: Vec<Value> = (0..64).map(|row| Value::Integer(row % 10)).collect();
1427 let column = Vector::from_values(LogicalType::Integer, &numbers).expect("a flat vector");
1428 let three = Vector::constant(LogicalType::Integer, Value::Integer(3), 64);
1429 let seven = Vector::constant(LogicalType::Integer, Value::Integer(7), 64);
1430
1431 let first = refine(Comparison::Greater, &column, &three, &Selection::identity(64))
1432 .expect("compares");
1433 let both = refine(Comparison::Less, &column, &seven, &first).expect("compares");
1434
1435 let expected: Vec<u32> = (0..64)
1436 .filter(|row| {
1437 let value = row % 10;
1438 value > 3 && value < 7
1439 })
1440 .collect();
1441 assert_eq!(both.indices(), expected.as_slice());
1442 assert!(both.len() < first.len(), "the second conjunct narrowed the selection");
1443 }
1444
1445 #[test]
1449 fn a_null_row_is_not_kept_by_an_ordinary_comparison_and_is_by_a_total_one() {
1450 let column = Vector::from_values(
1451 LogicalType::Integer,
1452 &[Value::Integer(1), Value::Null, Value::Integer(3), Value::Null],
1453 )
1454 .expect("four rows");
1455 let cut = Vector::constant(LogicalType::Integer, Value::Integer(2), 4);
1456 let all = Selection::identity(4);
1457 assert_eq!(
1458 refine(Comparison::Less, &column, &cut, &all).expect("compares").indices(),
1459 &[0]
1460 );
1461 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 4);
1463 assert_eq!(
1464 refine(Comparison::NotDistinctFrom, &column, &nulls, &all).expect("compares").indices(),
1465 &[1, 3]
1466 );
1467 }
1468
1469 #[test]
1470 fn a_selection_past_the_end_is_caught() {
1471 let column = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1472 let past = Selection::from_indices(vec![0, 4]);
1473 let error = refine(Comparison::Equal, &column, &column, &past).expect_err("out of range");
1474 assert!(error.message().contains("4 row vector"), "{error}");
1475 }
1476
1477 fn sample(ty: &LogicalType, rng: &mut Rng) -> Value {
1479 match ty {
1480 LogicalType::Boolean => Value::Boolean(rng.below(2) == 1),
1481 LogicalType::TinyInt => Value::TinyInt(rng.below(7) as i8 - 3),
1482 LogicalType::SmallInt => Value::SmallInt(rng.below(11) as i16 - 5),
1483 LogicalType::Integer => Value::Integer(rng.below(9) as i32 - 4),
1484 LogicalType::BigInt => Value::BigInt(rng.below(9) as i64 - 4),
1485 LogicalType::HugeInt => Value::HugeInt(i128::from(rng.below(9)) - 4),
1486 LogicalType::UInteger => Value::UInteger(rng.below(9) as u32),
1487 LogicalType::Float => Value::Float(match rng.below(5) {
1490 0 => f32::NAN,
1491 1 => -0.0,
1492 other => other as f32 - 2.0,
1493 }),
1494 LogicalType::Double => Value::Double(match rng.below(5) {
1495 0 => f64::NAN,
1496 1 => -0.0,
1497 other => other as f64 - 2.0,
1498 }),
1499 LogicalType::Interval => match rng.below(6) {
1503 0 => Value::Interval { months: 0, days: 1, micros: 0 },
1504 1 => Value::Interval { months: 0, days: 0, micros: 86_400_000_000 },
1505 2 => Value::Interval { months: 1, days: -29, micros: 86_400_000_000 },
1506 3 => Value::Interval { months: 1, days: 0, micros: 0 },
1507 4 => Value::Interval { months: 0, days: 0, micros: 90_000_000_000 },
1508 _ => Value::Interval { months: -1, days: 0, micros: 0 },
1509 },
1510 LogicalType::Varchar => Value::Varchar(
1513 match rng.below(6) {
1514 0 => "",
1515 1 => "ab",
1516 2 => "abc",
1517 3 => "abcdefghijkl",
1518 4 => "abcdefghijklm",
1519 _ => "abcdefghijklmnopqrstuvwxyz",
1520 }
1521 .to_owned(),
1522 ),
1523 other => panic!("the generator has no values for {other}"),
1524 }
1525 }
1526
1527 #[test]
1531 fn prefix_order_is_byte_order_whenever_the_prefixes_differ() {
1532 let words =
1533 ["", "a", "ab", "abc", "abcd", "abcde", "b", "abcdefghijklmnop", "abcdefghijklmnoq"];
1534 let mut column = StringColumn::new();
1535 for word in words {
1536 column.push(word);
1537 }
1538 for (i, one) in words.iter().enumerate() {
1539 for (j, other) in words.iter().enumerate() {
1540 assert_eq!(
1541 string_order(&column, i, &column, j),
1542 one.as_bytes().cmp(other.as_bytes()),
1543 "{one:?} against {other:?}"
1544 );
1545 }
1546 }
1547 }
1548
1549 #[test]
1552 fn a_dictionary_against_a_constant_reads_its_nulls_from_the_values() {
1553 let values = Vector::from_values(
1554 LogicalType::Integer,
1555 &[Value::Integer(1), Value::Null, Value::Integer(9)],
1556 )
1557 .expect("three values");
1558 let dictionary =
1559 Vector::dictionary(vec![0, 1, 2, 1, 0], values).expect("codes are in range");
1560 let constant = Vector::constant(LogicalType::Integer, Value::Integer(5), 5);
1561 let result = compare(Comparison::Less, &dictionary, &constant).expect("compares");
1562 assert_eq!(result.value_at(0), Value::Boolean(true));
1563 assert_eq!(result.value_at(1), Value::Null);
1564 assert_eq!(result.value_at(2), Value::Boolean(false));
1565 assert_eq!(result.value_at(3), Value::Null);
1566 assert_eq!(result.value_at(4), Value::Boolean(true));
1567 }
1568
1569 #[test]
1572 fn a_form_pair_with_no_loop_is_still_right_and_says_so() {
1573 let before = fallback::count(Kernel::Compare, Form::Sequence, Form::Flat);
1575 let sequence = Vector::sequence(10, 1, 4);
1576 let flat = Vector::from_values(
1577 LogicalType::BigInt,
1578 &[Value::BigInt(9), Value::BigInt(11), Value::BigInt(12), Value::Null],
1579 )
1580 .expect("four rows");
1581 let result = compare(Comparison::Less, &sequence, &flat).expect("compares");
1582 assert_eq!(result.value_at(0), Value::Boolean(false));
1583 assert_eq!(result.value_at(1), Value::Boolean(false));
1584 assert_eq!(result.value_at(2), Value::Boolean(false));
1585 assert_eq!(result.value_at(3), Value::Null);
1586 assert!(fallback::count(Kernel::Compare, Form::Sequence, Form::Flat) > before);
1587 }
1588
1589 #[test]
1599 fn a_second_level_of_codes_does_not_turn_the_loops_off() {
1600 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
1601 let values = Vector::from_values(
1602 LogicalType::Integer,
1603 &[Value::Integer(1), Value::Integer(5), Value::Integer(9)],
1604 )
1605 .expect("three rows");
1606 let once = Vector::dictionary(vec![2, 1, 0], values).expect("codes are in range");
1607 let twice = Vector::dictionary(vec![1, 2], once).expect("codes are in range");
1608 let cut = Vector::constant(LogicalType::Integer, Value::Integer(4), 2);
1609 let result = compare(Comparison::Greater, &twice, &cut).expect("compares");
1610 assert_eq!(result.value_at(0), Value::Boolean(true));
1611 assert_eq!(result.value_at(1), Value::Boolean(false));
1612 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
1613 }
1614
1615 #[test]
1619 fn a_side_that_is_entirely_null_answers_without_reading_the_other() {
1620 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 6);
1621 let flat = Vector::from_values(
1622 LogicalType::Integer,
1623 &[
1624 Value::Integer(1),
1625 Value::Integer(2),
1626 Value::Integer(3),
1627 Value::Integer(4),
1628 Value::Integer(5),
1629 Value::Integer(6),
1630 ],
1631 )
1632 .expect("six rows");
1633 agrees(Comparison::Less, &nulls, &flat);
1634 agrees(Comparison::Equal, &flat, &nulls);
1635 assert_eq!(
1636 compare(Comparison::Less, &nulls, &flat).expect("compares").validity(),
1637 &Validity::AllInvalid
1638 );
1639 }
1640
1641 #[test]
1644 fn an_empty_comparison_is_an_empty_answer() {
1645 let left = Vector::from_values(LogicalType::Integer, &[]).expect("no rows");
1646 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 0);
1647 let result = compare(Comparison::Equal, &left, &right).expect("compares");
1648 assert_eq!(result.len(), 0);
1649 }
1650
1651 fn words() -> Vector {
1654 Vector::from_values(
1655 LogicalType::Varchar,
1656 &[
1657 Value::Varchar("http://a".into()),
1658 Value::Varchar("http://b".into()),
1659 Value::Null,
1660 Value::Varchar("ab".into()),
1661 Value::Varchar("http://a".into()),
1662 Value::Varchar("z".into()),
1663 ],
1664 )
1665 .expect("six rows")
1666 }
1667
1668 #[test]
1674 fn a_literal_built_early_answers_what_one_built_here_answers() {
1675 let column = words();
1676 let value = Value::Varchar("http://b".into());
1677 let constant = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
1678 let held = Held::of(&LogicalType::Varchar, &value).expect("a varchar has a column");
1679 let kept = Selection::from_indices(vec![0, 1, 3, 5]);
1680 for op in [
1681 Comparison::Equal,
1682 Comparison::NotEqual,
1683 Comparison::Less,
1684 Comparison::LessOrEqual,
1685 Comparison::Greater,
1686 Comparison::GreaterOrEqual,
1687 Comparison::DistinctFrom,
1688 Comparison::NotDistinctFrom,
1689 ] {
1690 let prepared = compare_prepared(op, &column, &constant, Some(&held)).expect("compares");
1691 assert_eq!(prepared, compare(op, &column, &constant).expect("compares"), "{op:?}");
1692 let flipped = compare_prepared(op, &constant, &column, Some(&held)).expect("compares");
1694 assert_eq!(flipped, compare(op, &constant, &column).expect("compares"), "{op:?}");
1695 let refined =
1696 refine_prepared(op, &column, &constant, &kept, Some(&held)).expect("refines");
1697 assert_eq!(refined, refine(op, &column, &constant, &kept).expect("refines"), "{op:?}");
1698 }
1699 }
1700
1701 #[test]
1708 fn a_literal_built_for_another_value_is_ignored() {
1709 let column = words();
1710 let constant = Vector::constant(LogicalType::Varchar, Value::Varchar("z".into()), 6);
1711 let wrong = Held::of(&LogicalType::Varchar, &Value::Varchar("ab".into()))
1712 .expect("a varchar has a column");
1713 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&wrong))
1714 .expect("compares");
1715 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1716 let other = Held::of(&LogicalType::Integer, &Value::Integer(1)).expect("an integer column");
1719 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&other))
1720 .expect("compares");
1721 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1722 }
1723
1724 #[test]
1727 fn a_packed_column_against_a_constant_answers_what_the_oracle_answers() {
1728 let values: Vec<i32> = (0..64).map(|row| 1000 + (row * 37) % 500).collect();
1729 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1730 .expect("integers are an i32 layout");
1731 let packed = flat.bit_packed().expect("a five hundred wide range packs");
1732 assert_eq!(packed.form(), Form::BitPacked);
1733 for literal in [999, 1000, 1200, 1499, 1500, 2000] {
1734 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 64);
1735 for op in EVERY {
1736 agrees(op, &packed, &constant);
1737 agrees(op, &constant, &packed);
1738 }
1739 }
1740 }
1741
1742 #[test]
1746 fn a_packed_column_with_nulls_answers_what_the_oracle_answers() {
1747 let values: Vec<i32> = (0..32).map(|row| 40 + row * 3).collect();
1748 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1749 .expect("integers are an i32 layout")
1750 .with_validity(Validity::from_iter(32, |row| row % 5 != 0));
1751 let packed = flat.bit_packed().expect("packs");
1752 let constant = Vector::constant(LogicalType::Integer, Value::Integer(80), 32);
1753 for op in EVERY {
1754 agrees(op, &packed, &constant);
1755 }
1756 }
1757
1758 #[test]
1761 fn a_literal_outside_the_packed_range_answers_the_whole_vector_at_once() {
1762 let before = fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant);
1763 let values: Vec<i32> = (0..16).map(|row| 500 + row).collect();
1764 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1765 .expect("integers are an i32 layout");
1766 let packed = flat.bit_packed().expect("packs");
1767 let literals = [-1, 0, 499, 516, 100_000];
1768 for literal in literals {
1769 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 16);
1770 for op in EVERY {
1771 agrees(op, &packed, &constant);
1772 }
1773 }
1774 let total = EVERY.iter().filter(|op| op.is_total()).count();
1779 assert_eq!(
1780 fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant) - before,
1781 (literals.len() * total) as u64,
1782 "only the two total comparisons fall through"
1783 );
1784 }
1785
1786 #[test]
1789 fn refining_a_selection_over_a_packed_column_keeps_the_same_rows() {
1790 let values: Vec<i32> = (0..64).map(|row| 200 + (row * 11) % 128).collect();
1791 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.clone().into()))
1792 .expect("integers are an i32 layout");
1793 let packed = flat.bit_packed().expect("packs");
1794 let kept = Selection::from_predicate(64, |row| row % 3 == 0);
1795 let constant = Vector::constant(LogicalType::Integer, Value::Integer(260), 64);
1796 let packed_rows = refine(Comparison::Greater, &packed, &constant, &kept).expect("refines");
1797 let flat_rows = refine(Comparison::Greater, &flat, &constant, &kept).expect("refines");
1798 assert_eq!(packed_rows.indices(), flat_rows.indices());
1799 assert!(!packed_rows.is_empty(), "the literal is inside the range");
1800 }
1801
1802 fn urls(count: usize) -> Vector {
1805 let mut rng = Rng(0x5eed_1234);
1806 let values: Vec<Value> = (0..count)
1807 .map(|_| {
1808 let host = rng.below(6);
1809 let path = rng.below(40);
1810 Value::Varchar(format!("http://example{host}.test/a/rather/long/path/{path}"))
1811 })
1812 .collect();
1813 Vector::from_values(LogicalType::Varchar, &values).expect("strings")
1814 }
1815
1816 #[test]
1817 fn a_string_view_column_against_a_literal_answers_what_the_oracle_answers() {
1818 let before = fallback::count(Kernel::Compare, Form::StringView, Form::Constant);
1819 let shared = urls(64).shared_text().expect("shares");
1820 assert_eq!(shared.form(), Form::StringView);
1821 let literals = ["http://example3.test/a/rather/long/path/7", "a", "zzz", ""];
1822 for literal in literals {
1823 let value = Value::Varchar(literal.to_owned());
1824 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1825 for op in EVERY {
1826 agrees(op, &shared, &constant);
1827 agrees(op, &constant, &shared);
1828 }
1829 }
1830 assert_eq!(
1831 fallback::count(Kernel::Compare, Form::StringView, Form::Constant),
1832 before,
1833 "the form has a loop of its own for every comparison"
1834 );
1835 }
1836
1837 #[test]
1838 fn a_string_view_column_against_another_one_answers_what_the_oracle_answers() {
1839 let shared = urls(48).shared_text().expect("shares");
1840 let other = urls(48).shared_text().expect("shares");
1841 let flat = urls(48);
1842 for op in EVERY {
1843 agrees(op, &shared, &other);
1844 agrees(op, &shared, &flat);
1845 agrees(op, &flat, &shared);
1846 }
1847 }
1848
1849 #[test]
1850 fn the_nulls_of_a_string_view_column_are_the_nulls_the_oracle_sees() {
1851 let shared = urls(32)
1852 .with_validity(Validity::from_iter(32, |row| row % 4 != 1))
1853 .shared_text()
1854 .expect("shares");
1855 let constant =
1856 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 32);
1857 for op in EVERY {
1858 agrees(op, &shared, &constant);
1859 }
1860 }
1861
1862 #[test]
1863 fn a_compressed_column_against_a_literal_answers_what_the_oracle_answers() {
1864 let before = fallback::count(Kernel::Compare, Form::Fsst, Form::Constant);
1865 let flat = urls(64);
1866 let coded = flat.clone().compressed().expect("compresses");
1867 assert_eq!(coded.form(), Form::Fsst);
1868 let present = match coded.value_at(9) {
1869 Value::Varchar(text) => text,
1870 other => panic!("a string column reads back strings, not {other:?}"),
1871 };
1872 for literal in [present.as_str(), "http://example3.test/nothing/like/it", ""] {
1873 let value = Value::Varchar(literal.to_owned());
1874 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1875 for op in EVERY {
1876 agrees(op, &coded, &constant);
1877 agrees(op, &constant, &coded);
1878 }
1879 }
1880 let ordered = EVERY.len() - 2;
1884 assert_eq!(
1885 fallback::count(Kernel::Compare, Form::Fsst, Form::Constant) - before,
1886 (3 * ordered) as u64,
1887 "only the comparisons that need an order fall through"
1888 );
1889 }
1890
1891 #[test]
1894 fn every_row_of_a_compressed_column_matches_itself_and_nothing_else() {
1895 let flat = urls(48);
1896 let coded = flat.clone().compressed().expect("compresses");
1897 for row in 0..48 {
1898 let constant = Vector::constant(LogicalType::Varchar, flat.value_at(row), 48);
1899 let equal = compare(Comparison::Equal, &coded, &constant).expect("compares");
1900 for other in 0..48 {
1901 let want = flat.value_at(other) == flat.value_at(row);
1902 assert_eq!(
1903 equal.value_at(other),
1904 Value::Boolean(want),
1905 "row {row} against {other}"
1906 );
1907 }
1908 }
1909 }
1910
1911 #[test]
1912 fn the_nulls_of_a_compressed_column_are_the_nulls_the_oracle_sees() {
1913 let coded = urls(32)
1914 .with_validity(Validity::from_iter(32, |row| row % 3 != 0))
1915 .compressed()
1916 .expect("compresses");
1917 let value = coded.value_at(1);
1918 let constant = Vector::constant(LogicalType::Varchar, value, 32);
1919 for op in EVERY {
1920 agrees(op, &coded, &constant);
1921 }
1922 }
1923
1924 #[test]
1928 fn a_filter_over_either_string_form_keeps_the_same_rows() {
1929 let flat = urls(96);
1930 let shared = flat.clone().shared_text().expect("shares");
1931 let constant =
1932 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 96);
1933 let kept = Selection::from_predicate(96, |row| row % 5 != 0);
1934 for op in EVERY {
1935 let over_flat = refine(op, &flat, &constant, &kept).expect("refines");
1936 let over_shared = refine(op, &shared, &constant, &kept).expect("refines");
1937 assert_eq!(over_shared.indices(), over_flat.indices(), "{op:?}");
1938 }
1939 }
1940
1941 #[test]
1945 fn a_comparison_peeled_over_a_shared_dictionary_answers_what_the_oracle_answers() {
1946 let words = ["", "one", "two", "", "three"];
1947 let values: Vec<Value> = words.iter().map(|text| Value::Varchar((*text).into())).collect();
1948 let values = std::sync::Arc::new(
1949 Vector::from_values(LogicalType::Varchar, &values).expect("a vector of text"),
1950 );
1951 let codes = vec![0, 1, 3, 2, 0, 4, 1, 0];
1952 let column = Vector::stable_dictionary(codes.clone(), values).expect("codes are in range");
1953 same_as_the_oracle(&column);
1954 }
1955
1956 #[derive(Debug)]
1959 struct Filed {
1960 values: Vec<Vec<u8>>,
1961 order: Vec<u32>,
1962 }
1963
1964 impl rudb_vector::TextSource for Filed {
1965 fn len(&self) -> usize {
1966 self.values.len()
1967 }
1968
1969 fn bytes_at(&self, index: usize) -> Result<Option<&[u8]>> {
1970 Ok(self.values.get(index).map(Vec::as_slice))
1971 }
1972
1973 fn footprint(&self) -> usize {
1974 self.values.iter().map(Vec::len).sum()
1975 }
1976
1977 fn ranks(&self) -> Option<usize> {
1978 Some(self.order.len())
1979 }
1980
1981 fn compare_rank(&self, rank: usize, wanted: &[u8]) -> Result<Ordering> {
1982 Ok(self.values[self.order[rank] as usize].as_slice().cmp(wanted))
1985 }
1986
1987 fn code_at_rank(&self, rank: usize) -> Result<u32> {
1988 Ok(self.order[rank])
1989 }
1990 }
1991
1992 #[test]
1995 fn a_comparison_against_a_sorted_dictionary_answers_what_the_oracle_answers() {
1996 let words = ["", "one", "two", "four", "three"];
1999 let values: Vec<Vec<u8>> = words.iter().map(|text| text.as_bytes().to_vec()).collect();
2000 let mut order = (0..values.len() as u32).collect::<Vec<_>>();
2001 order.sort_by(|&left, &right| values[left as usize].cmp(&values[right as usize]));
2002 let values = Vector::external_text(
2003 LogicalType::Varchar,
2004 std::sync::Arc::new(Filed { values, order }),
2005 )
2006 .expect("a filed vector");
2007 let codes = vec![0, 1, 3, 2, 0, 4, 1, 0];
2008 let column = Vector::stable_dictionary(codes, std::sync::Arc::new(values))
2009 .expect("codes are in range");
2010 same_as_the_oracle(&column);
2011 }
2012
2013 fn same_as_the_oracle(column: &Vector) {
2017 for literal in ["", "one", "missing"] {
2018 for op in [Comparison::Equal, Comparison::NotEqual] {
2019 let value = Value::Varchar(literal.to_owned());
2020 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
2021 let right = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
2022 let wanted = oracle(op, column, &right);
2023 let got = compare_prepared(op, column, &right, Some(&held))
2024 .expect("the peeled path answers");
2025 assert_eq!(got, wanted, "{literal:?} under {op:?}");
2026 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
2028 let kept = Selection::from_predicate(column.len(), |row| row % 3 != 1);
2029 let refined = refine_prepared(op, column, &right, &kept, Some(&held))
2030 .expect("the peeled path narrows");
2031 let wanted: Vec<u32> = kept
2032 .indices()
2033 .iter()
2034 .copied()
2035 .filter(|&row| is_true(&wanted.value_at(row as usize)))
2036 .collect();
2037 assert_eq!(refined.indices(), wanted, "{literal:?} under {op:?}, narrowed");
2038 }
2039 }
2040 }
2041}