1use std::borrow::Cow;
72use std::cmp::Ordering;
73
74use rudb_common::{Error, LogicalType, Result, Value, interval_micros};
75use rudb_vector::{
76 Coded, Data, Form, Packed, Selection, StringColumn, StringView, Validity, Vector,
77};
78
79use crate::fallback::{self, Kernel};
80use crate::logic::is_true;
81use crate::number::{approximate, integral};
82use crate::prepare::Held;
83use crate::shape::{first, identity, nulls_of, single};
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
87pub enum Comparison {
88 Equal,
90 NotEqual,
92 Less,
94 LessOrEqual,
96 Greater,
98 GreaterOrEqual,
100 DistinctFrom,
102 NotDistinctFrom,
104}
105
106impl Comparison {
107 #[must_use]
109 pub fn is_total(self) -> bool {
110 matches!(self, Self::DistinctFrom | Self::NotDistinctFrom)
111 }
112
113 #[must_use]
120 pub fn swapped(self) -> Self {
121 match self {
122 Self::Less => Self::Greater,
123 Self::LessOrEqual => Self::GreaterOrEqual,
124 Self::Greater => Self::Less,
125 Self::GreaterOrEqual => Self::LessOrEqual,
126 same => same,
127 }
128 }
129}
130
131pub fn compare(op: Comparison, left: &Vector, right: &Vector) -> Result<Vector> {
137 compare_prepared(op, left, right, None)
138}
139
140pub fn compare_prepared(
150 op: Comparison,
151 left: &Vector,
152 right: &Vector,
153 held: Option<&Held>,
154) -> Result<Vector> {
155 if left.len() != right.len() {
156 return Err(Error::internal(format!(
157 "a comparison of a {} row vector with a {} row one",
158 left.len(),
159 right.len()
160 )));
161 }
162 let len = left.len();
163 if left.form() == Form::Constant && right.form() == Form::Constant && len > 0 {
164 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
165 return Ok(Vector::constant(LogicalType::Boolean, single, len));
166 }
167
168 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
169 if !op.is_total()
173 && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
174 && len > 0
175 {
176 return boolean(vec![false; len], Validity::AllInvalid, len);
177 }
178
179 if let Some(answers) = external_text_literal(op, left, right, len, identity)? {
180 let validity = left_valid.and(&right_valid, len);
181 return boolean(blank_the_nulls(answers, &validity), validity, len);
182 }
183 if let Some(answers) =
184 specialized(op, left, right, &left_valid, &right_valid, len, identity, held)
185 {
186 let validity =
187 if op.is_total() { Validity::AllValid } else { left_valid.and(&right_valid, len) };
188 return boolean(blank_the_nulls(answers, &validity), validity, len);
189 }
190
191 fallback::record(Kernel::Compare, left.form(), right.form());
192 let mut values = Vec::with_capacity(len);
193 for index in 0..len {
196 values.push(compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?);
197 }
198 Vector::from_values(LogicalType::Boolean, &values)
199}
200
201pub fn refine(
219 op: Comparison,
220 left: &Vector,
221 right: &Vector,
222 kept: &Selection,
223) -> Result<Selection> {
224 refine_prepared(op, left, right, kept, None)
225}
226
227pub fn refine_prepared(
237 op: Comparison,
238 left: &Vector,
239 right: &Vector,
240 kept: &Selection,
241 held: Option<&Held>,
242) -> Result<Selection> {
243 if left.len() != right.len() {
244 return Err(Error::internal(format!(
245 "a comparison of a {} row vector with a {} row one",
246 left.len(),
247 right.len()
248 )));
249 }
250 let len = left.len();
251 if kept.indices().iter().any(|&row| row as usize >= len) {
255 return Err(Error::internal(format!("a selection past the end of a {len} row vector")));
256 }
257 if kept.is_empty() {
258 return Ok(Selection::empty());
259 }
260 if left.form() == Form::Constant && right.form() == Form::Constant {
261 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
262 return Ok(if is_true(&single) { kept.clone() } else { Selection::empty() });
263 }
264
265 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
266 if !op.is_total() && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
267 {
268 return Ok(Selection::empty());
269 }
270
271 let rows = kept.indices();
272 let map = |slot: usize| rows[slot] as usize;
273 if let Some(answers) = external_text_literal(op, left, right, kept.len(), map)? {
274 return Ok(narrowed(&answers, rows, |slot| {
275 let row = rows[slot] as usize;
276 left_valid.is_valid(row) && right_valid.is_valid(row)
277 }));
278 }
279 if let Some(answers) =
280 specialized(op, left, right, &left_valid, &right_valid, kept.len(), map, held)
281 {
282 if op.is_total() || (left_valid == Validity::AllValid && right_valid == Validity::AllValid)
285 {
286 return Ok(narrowed(&answers, rows, |_| true));
287 }
288 return Ok(narrowed(&answers, rows, |slot| {
292 let row = rows[slot] as usize;
293 left_valid.is_valid(row) && right_valid.is_valid(row)
294 }));
295 }
296
297 fallback::record(Kernel::Compare, left.form(), right.form());
298 let mut out = Vec::with_capacity(kept.len());
299 for &row in rows {
302 let index = row as usize;
303 if is_true(&compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?) {
304 out.push(row);
305 }
306 }
307 Ok(Selection::from_indices(out))
308}
309
310fn external_text_literal<M>(
312 op: Comparison,
313 left: &Vector,
314 right: &Vector,
315 len: usize,
316 map: M,
317) -> Result<Option<Vec<bool>>>
318where
319 M: Fn(usize) -> usize + Copy,
320{
321 if !matches!(op, Comparison::Equal | Comparison::NotEqual)
322 || left.logical_type() != &LogicalType::Varchar
323 || right.logical_type() != &LogicalType::Varchar
324 {
325 return Ok(None);
326 }
327 let (column, literal, swapped) = match (left.constant_value(), right.constant_value()) {
328 (None, Some(Value::Varchar(literal))) if left.positions().is_some() => {
329 (left, literal.as_bytes(), false)
330 }
331 (Some(Value::Varchar(literal)), None) if right.positions().is_some() => {
332 (right, literal.as_bytes(), true)
333 }
334 _ => return Ok(None),
335 };
336 let same = if swapped { op.swapped() } else { op } == Comparison::Equal;
337 let mut answers = Vec::with_capacity(len);
338 for slot in 0..len {
339 let row = map(slot);
340 let equal = if literal.is_empty() {
341 column.try_bytes_len_at(row)?.is_some_and(|length| length == 0)
342 } else {
343 column.try_bytes_at(row)?.is_some_and(|bytes| bytes == literal)
344 };
345 answers.push(equal == same);
346 }
347 Ok(Some(answers))
348}
349
350fn narrowed<L: Fn(usize) -> bool>(answers: &[bool], rows: &[u32], live: L) -> Selection {
357 let mut out = vec![0_u32; answers.len()];
358 let mut count = 0;
359 for (slot, &answer) in answers.iter().enumerate() {
360 out[count] = rows[slot];
361 count += usize::from(answer & live(slot));
363 }
364 out.truncate(count);
365 Selection::from_indices(out)
366}
367
368fn boolean(answers: Vec<bool>, validity: Validity, len: usize) -> Result<Vector> {
370 let validity = if len == 0 { Validity::AllValid } else { validity.normalize(len) };
374 Ok(Vector::flat(LogicalType::Boolean, Data::Bool(answers.into()))?.with_validity(validity))
375}
376
377fn blank_the_nulls(mut answers: Vec<bool>, validity: &Validity) -> Vec<bool> {
385 if let Validity::Mask(mask) = validity {
386 for (index, answer) in answers.iter_mut().enumerate() {
387 if !mask.get(index) {
388 *answer = false;
389 }
390 }
391 }
392 answers
393}
394
395#[expect(
407 clippy::too_many_arguments,
408 reason = "two sides, two validities, the operator, the length, the index mapping and the \
409 literal that was built early, all of which the branches below need"
410)]
411fn specialized<M>(
412 op: Comparison,
413 left: &Vector,
414 right: &Vector,
415 left_valid: &Validity,
416 right_valid: &Validity,
417 len: usize,
418 map: M,
419 held: Option<&Held>,
420) -> Option<Vec<bool>>
421where
422 M: Fn(usize) -> usize + Copy,
423{
424 if left.logical_type() != right.logical_type() {
428 return None;
429 }
430
431 if let (Some(one), Some(other)) = (left.data(), right.data()) {
432 return dispatch(op, len, one, map, other, map, left_valid, right_valid, map);
433 }
434 if !op.is_total() {
440 if let (Some(packed), Some(value)) = (left.packed_parts(), right.constant_value()) {
441 let wanted = exact(held, left.logical_type(), value)?;
442 return Some(packed_against(op, &packed, wanted, len, map));
443 }
444 if let (Some(value), Some(packed)) = (left.constant_value(), right.packed_parts()) {
445 let wanted = exact(held, right.logical_type(), value)?;
446 return Some(packed_against(op.swapped(), &packed, wanted, len, map));
447 }
448 }
449 if let (Some(one), Some(value)) = (left.data(), right.constant_value()) {
450 let column = readied(held, left.logical_type(), value)?;
451 let other = column.data()?;
452 return dispatch(op, len, one, map, other, first, left_valid, right_valid, map);
453 }
454 if let (Some(value), Some(other)) = (left.constant_value(), right.data()) {
455 let column = readied(held, right.logical_type(), value)?;
457 let one = column.data()?;
458 return dispatch(op.swapped(), len, other, map, one, first, right_valid, left_valid, map);
459 }
460 if matches!(op, Comparison::Equal | Comparison::NotEqual) {
465 if let (Some(coded), Some(value)) = (left.coded_parts(), right.constant_value()) {
466 let wanted = encoded(&coded, held, left.logical_type(), value)?;
467 return Some(coded_against(op, &coded, &wanted, len, map));
468 }
469 if let (Some(value), Some(coded)) = (left.constant_value(), right.coded_parts()) {
470 let wanted = encoded(&coded, held, right.logical_type(), value)?;
471 return Some(coded_against(op, &coded, &wanted, len, map));
472 }
473 }
474 if let (Some((one, one_arena)), Some((other, other_arena))) =
480 (left.text_parts(), right.text_parts())
481 {
482 return Some(sweep(
483 op,
484 len,
485 |index| view_order(one.get(map(index)), one_arena, other.get(map(index)), other_arena),
486 left_valid,
487 right_valid,
488 map,
489 ));
490 }
491 if let (Some((one, one_arena)), Some(value)) = (left.text_parts(), right.constant_value()) {
495 let column = readied(held, left.logical_type(), value)?;
496 let (other, other_arena) = column.text_parts()?;
497 let wanted = other.first();
498 return Some(sweep(
499 op,
500 len,
501 |index| view_order(one.get(map(index)), one_arena, wanted, other_arena),
502 left_valid,
503 right_valid,
504 map,
505 ));
506 }
507 if let (Some(value), Some((other, other_arena))) = (left.constant_value(), right.text_parts()) {
508 let column = readied(held, right.logical_type(), value)?;
510 let (one, one_arena) = column.text_parts()?;
511 let wanted = one.first();
512 return Some(sweep(
513 op.swapped(),
514 len,
515 |index| view_order(other.get(map(index)), other_arena, wanted, one_arena),
516 right_valid,
517 left_valid,
518 map,
519 ));
520 }
521 if let (Some((codes, values)), Some(value)) = (left.positions(), right.constant_value()) {
522 let one = values.data()?;
523 let column = readied(held, left.logical_type(), value)?;
524 let other = column.data()?;
525 let at = |index: usize| codes[map(index)] as usize;
526 return dispatch(op, len, one, at, other, first, left_valid, right_valid, map);
527 }
528 if let (Some(value), Some((codes, values))) = (left.constant_value(), right.positions()) {
529 let other = values.data()?;
530 let column = readied(held, right.logical_type(), value)?;
531 let one = column.data()?;
532 let at = |index: usize| codes[map(index)] as usize;
533 return dispatch(op.swapped(), len, other, at, one, first, right_valid, left_valid, map);
534 }
535 if let (Some((codes, values)), Some(other)) = (left.positions(), right.data()) {
541 let one = values.data()?;
542 let at = |index: usize| codes[map(index)] as usize;
543 return dispatch(op, len, one, at, other, map, left_valid, right_valid, map);
544 }
545 if let (Some(one), Some((codes, values))) = (left.data(), right.positions()) {
546 let other = values.data()?;
547 let at = |index: usize| codes[map(index)] as usize;
548 return dispatch(op.swapped(), len, other, at, one, map, right_valid, left_valid, map);
549 }
550 None
551}
552
553fn exact(held: Option<&Held>, ty: &LogicalType, value: &Value) -> Option<i128> {
560 let column = readied(held, ty, value)?;
561 let data = column.data()?;
562 data.signed_at(0).or_else(|| data.unsigned_at(0).and_then(|value| i128::try_from(value).ok()))
563}
564
565fn encoded(
571 coded: &Coded<'_>,
572 held: Option<&Held>,
573 ty: &LogicalType,
574 value: &Value,
575) -> Option<Vec<u8>> {
576 let column = readied(held, ty, value)?;
577 let (views, arena) = column.text_parts()?;
578 Some(coded.encode(views.first()?.bytes_in(arena)?))
579}
580
581fn coded_against<M>(
587 op: Comparison,
588 coded: &Coded<'_>,
589 wanted: &[u8],
590 len: usize,
591 map: M,
592) -> Vec<bool>
593where
594 M: Fn(usize) -> usize + Copy,
595{
596 let same = op == Comparison::Equal;
597 let mut answers = Vec::with_capacity(len);
598 for row in 0..len {
599 answers.push((coded.row(map(row)) == Some(wanted)) == same);
600 }
601 answers
602}
603
604fn packed_against<M>(
610 op: Comparison,
611 packed: &Packed<'_>,
612 wanted: i128,
613 len: usize,
614 map: M,
615) -> Vec<bool>
616where
617 M: Fn(usize) -> usize + Copy,
618{
619 let Some(code) = packed.code_of(wanted) else {
620 let above = wanted > packed.ceiling();
623 let same = match op {
624 Comparison::Equal | Comparison::NotDistinctFrom => false,
625 Comparison::NotEqual | Comparison::DistinctFrom => true,
626 Comparison::Less | Comparison::LessOrEqual => above,
627 Comparison::Greater | Comparison::GreaterOrEqual => !above,
628 };
629 return vec![same; len];
630 };
631 let test: fn(u64, u64) -> bool = match op {
634 Comparison::Equal | Comparison::NotDistinctFrom => |found, want| found == want,
635 Comparison::NotEqual | Comparison::DistinctFrom => |found, want| found != want,
636 Comparison::Less => |found, want| found < want,
637 Comparison::LessOrEqual => |found, want| found <= want,
638 Comparison::Greater => |found, want| found > want,
639 Comparison::GreaterOrEqual => |found, want| found >= want,
640 };
641 let mut answers = Vec::with_capacity(len);
642 for row in 0..len {
643 answers.push(test(packed.code(map(row)), code));
644 }
645 answers
646}
647
648#[expect(
654 clippy::too_many_arguments,
655 reason = "two sides with an index each, the operator, the length and two validities, all of \
656 which the loop needs and none of which is worth a struct that exists for one call"
657)]
658fn dispatch<L, R, V>(
659 op: Comparison,
660 len: usize,
661 left: &Data,
662 at_left: L,
663 right: &Data,
664 at_right: R,
665 left_valid: &Validity,
666 right_valid: &Validity,
667 at_valid: V,
668) -> Option<Vec<bool>>
669where
670 L: Fn(usize) -> usize,
671 R: Fn(usize) -> usize,
672 V: Fn(usize) -> usize,
673{
674 macro_rules! layouts {
675 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
676 match (left, right) {
677 $(
678 (Data::$variant(one), Data::$variant(other)) => Some(sweep(
679 op,
680 len,
681 |index| one[at_left(index)].cmp(&other[at_right(index)]),
682 left_valid,
683 right_valid,
684 &at_valid,
685 )),
686 )+
687 (Data::Float32(one), Data::Float32(other)) => Some(sweep(
690 op,
691 len,
692 |index| {
693 float_order(
694 f64::from(one[at_left(index)]),
695 f64::from(other[at_right(index)]),
696 )
697 },
698 left_valid,
699 right_valid,
700 &at_valid,
701 )),
702 (Data::Float64(one), Data::Float64(other)) => Some(sweep(
703 op,
704 len,
705 |index| float_order(one[at_left(index)], other[at_right(index)]),
706 left_valid,
707 right_valid,
708 &at_valid,
709 )),
710 (Data::Interval(one), Data::Interval(other)) => Some(sweep(
713 op,
714 len,
715 |index| {
716 let (months, days, micros) = one[at_left(index)];
717 let (bm, bd, bu) = other[at_right(index)];
718 interval_micros(months, days, micros).cmp(&interval_micros(bm, bd, bu))
719 },
720 left_valid,
721 right_valid,
722 &at_valid,
723 )),
724 (Data::Varlen(one), Data::Varlen(other)) => Some(sweep(
725 op,
726 len,
727 |index| string_order(one, at_left(index), other, at_right(index)),
728 left_valid,
729 right_valid,
730 &at_valid,
731 )),
732 _ => None,
733 }
734 };
735 }
736 rudb_vector::for_each_layout!(ordered, layouts)
737}
738
739fn readied<'a>(held: Option<&'a Held>, ty: &LogicalType, value: &Value) -> Option<Cow<'a, Vector>> {
745 match held {
746 Some(held) if held.matches(ty, value) => Some(Cow::Borrowed(held.single())),
747 _ => Some(Cow::Owned(single(ty, value)?)),
748 }
749}
750
751fn string_order(
759 left: &StringColumn,
760 at_left: usize,
761 right: &StringColumn,
762 at_right: usize,
763) -> Ordering {
764 view_order(left.views().get(at_left), left.arena(), right.views().get(at_right), right.arena())
765}
766
767fn view_order(
773 one: Option<&StringView>,
774 one_arena: &[u8],
775 other: Option<&StringView>,
776 other_arena: &[u8],
777) -> Ordering {
778 let (Some(one), Some(other)) = (one, other) else {
779 return Ordering::Equal;
780 };
781 let (prefix, against) = (one.prefix(), other.prefix());
782 if prefix != against {
783 return prefix.cmp(&against);
784 }
785 let bytes = one.bytes_in(one_arena).unwrap_or_default();
790 let against_bytes = other.bytes_in(other_arena).unwrap_or_default();
791 bytes.cmp(against_bytes)
792}
793
794fn sweep<O, V>(
800 op: Comparison,
801 len: usize,
802 order_at: O,
803 left_valid: &Validity,
804 right_valid: &Validity,
805 at_valid: V,
806) -> Vec<bool>
807where
808 O: Fn(usize) -> Ordering,
809 V: Fn(usize) -> usize,
810{
811 let mut answers = vec![false; len];
812 match op {
813 Comparison::Equal => fill(&mut answers, order_at, |o| o == Ordering::Equal),
814 Comparison::NotEqual => fill(&mut answers, order_at, |o| o != Ordering::Equal),
815 Comparison::Less => fill(&mut answers, order_at, |o| o == Ordering::Less),
816 Comparison::LessOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Greater),
817 Comparison::Greater => fill(&mut answers, order_at, |o| o == Ordering::Greater),
818 Comparison::GreaterOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Less),
819 Comparison::DistinctFrom => {
820 total(&mut answers, order_at, left_valid, right_valid, at_valid);
821 for answer in &mut answers {
822 *answer = !*answer;
823 }
824 }
825 Comparison::NotDistinctFrom => {
826 total(&mut answers, order_at, left_valid, right_valid, at_valid);
827 }
828 }
829 answers
830}
831
832#[inline]
834fn fill<O, H>(answers: &mut [bool], order_at: O, held: H)
835where
836 O: Fn(usize) -> Ordering,
837 H: Fn(Ordering) -> bool,
838{
839 for (index, answer) in answers.iter_mut().enumerate() {
840 *answer = held(order_at(index));
841 }
842}
843
844fn total<O, V>(
851 answers: &mut [bool],
852 order_at: O,
853 left_valid: &Validity,
854 right_valid: &Validity,
855 at_valid: V,
856) where
857 O: Fn(usize) -> Ordering,
858 V: Fn(usize) -> usize,
859{
860 if *left_valid == Validity::AllValid && *right_valid == Validity::AllValid {
861 fill(answers, order_at, |o| o == Ordering::Equal);
862 return;
863 }
864 for (index, answer) in answers.iter_mut().enumerate() {
865 let row = at_valid(index);
866 *answer = match (left_valid.is_valid(row), right_valid.is_valid(row)) {
867 (true, true) => order_at(index) == Ordering::Equal,
868 (false, false) => true,
869 _ => false,
870 };
871 }
872}
873
874pub fn compare_values(op: Comparison, left: &Value, right: &Value) -> Result<Value> {
880 if op.is_total() {
881 let same = match (left.is_null(), right.is_null()) {
882 (true, true) => true,
883 (true, false) | (false, true) => false,
884 (false, false) => order(left, right)? == Ordering::Equal,
885 };
886 return Ok(Value::Boolean(match op {
887 Comparison::NotDistinctFrom => same,
888 _ => !same,
889 }));
890 }
891 if left.is_null() || right.is_null() {
892 return Ok(Value::Null);
893 }
894 let ordering = order(left, right)?;
895 let held = match op {
896 Comparison::Equal => ordering == Ordering::Equal,
897 Comparison::NotEqual => ordering != Ordering::Equal,
898 Comparison::Less => ordering == Ordering::Less,
899 Comparison::LessOrEqual => ordering != Ordering::Greater,
900 Comparison::Greater => ordering == Ordering::Greater,
901 Comparison::GreaterOrEqual => ordering != Ordering::Less,
902 Comparison::DistinctFrom | Comparison::NotDistinctFrom => {
903 return Err(Error::internal("a total comparison reached the ordered path"));
904 }
905 };
906 Ok(Value::Boolean(held))
907}
908
909pub fn order(left: &Value, right: &Value) -> Result<Ordering> {
920 match (left, right) {
921 (Value::Null, _) | (_, Value::Null) => {
922 Err(Error::internal("a null reached the ordering path"))
923 }
924 (Value::Boolean(a), Value::Boolean(b)) => Ok(a.cmp(b)),
925 (Value::Varchar(a), Value::Varchar(b)) => Ok(a.as_bytes().cmp(b.as_bytes())),
926 (Value::Blob(a), Value::Blob(b)) => Ok(a.cmp(b)),
927 (Value::Date(a), Value::Date(b)) => Ok(a.cmp(b)),
928 (Value::Time(a), Value::Time(b))
931 | (Value::TimeTz(a), Value::TimeTz(b))
932 | (Value::Timestamp(a), Value::Timestamp(b))
933 | (Value::TimestampTz(a), Value::TimestampTz(b)) => Ok(a.cmp(b)),
934 (
935 Value::Interval { months: am, days: ad, micros: au },
936 Value::Interval { months: bm, days: bd, micros: bu },
937 ) => Ok(interval_micros(*am, *ad, *au).cmp(&interval_micros(*bm, *bd, *bu))),
938 _ => numeric_order(left, right),
939 }
940}
941
942fn numeric_order(left: &Value, right: &Value) -> Result<Ordering> {
944 if let (Some(a), Some(b)) = (integral(left), integral(right)) {
945 return Ok(a.cmp(&b));
946 }
947 if let (
948 Value::Decimal { unscaled: a, scale: sa, .. },
949 Value::Decimal { unscaled: b, scale: sb, .. },
950 ) = (left, right)
951 {
952 if sa == sb {
953 return Ok(a.cmp(b));
954 }
955 }
956 match (approximate(left), approximate(right)) {
957 (Some(a), Some(b)) => Ok(float_order(a, b)),
958 _ => Err(Error::not_implemented(format!(
959 "comparing {} with {}",
960 left.logical_type(),
961 right.logical_type()
962 ))),
963 }
964}
965
966fn float_order(left: f64, right: f64) -> Ordering {
968 if left == right {
969 return Ordering::Equal;
970 }
971 match (left.is_nan(), right.is_nan()) {
972 (true, true) => Ordering::Equal,
973 (true, false) => Ordering::Greater,
974 (false, true) => Ordering::Less,
975 (false, false) => left.partial_cmp(&right).unwrap_or(Ordering::Equal),
976 }
977}
978
979pub fn order_with_nulls(left: &Value, right: &Value, nulls_first: bool) -> Result<Ordering> {
988 match (left.is_null(), right.is_null()) {
989 (true, true) => Ok(Ordering::Equal),
990 (true, false) => Ok(if nulls_first { Ordering::Less } else { Ordering::Greater }),
991 (false, true) => Ok(if nulls_first { Ordering::Greater } else { Ordering::Less }),
992 (false, false) => order(left, right),
993 }
994}
995
996#[cfg(test)]
997mod tests {
998 use super::*;
999
1000 fn compared(op: Comparison, left: Value, right: Value) -> Value {
1001 compare_values(op, &left, &right).expect("these types compare")
1002 }
1003
1004 const EVERY: [Comparison; 8] = [
1006 Comparison::Equal,
1007 Comparison::NotEqual,
1008 Comparison::Less,
1009 Comparison::LessOrEqual,
1010 Comparison::Greater,
1011 Comparison::GreaterOrEqual,
1012 Comparison::DistinctFrom,
1013 Comparison::NotDistinctFrom,
1014 ];
1015
1016 fn oracle(op: Comparison, left: &Vector, right: &Vector) -> Vector {
1022 let values: Vec<Value> = (0..left.len())
1023 .map(|index| {
1024 compare_values(op, &left.value_at(index), &right.value_at(index))
1025 .expect("the oracle is only asked about types that compare")
1026 })
1027 .collect();
1028 Vector::from_values(LogicalType::Boolean, &values).expect("booleans")
1029 }
1030
1031 fn agrees(op: Comparison, left: &Vector, right: &Vector) {
1035 let fast = compare(op, left, right).expect("compares");
1036 let slow = oracle(op, left, right);
1037 assert_eq!(fast, slow, "{op:?} on a {:?} against a {:?}", left.form(), right.form());
1038 }
1039
1040 struct Rng(u64);
1043
1044 impl Rng {
1045 fn next(&mut self) -> u64 {
1046 self.0 ^= self.0 << 13;
1047 self.0 ^= self.0 >> 7;
1048 self.0 ^= self.0 << 17;
1049 self.0
1050 }
1051
1052 fn below(&mut self, bound: u64) -> u64 {
1053 self.next() % bound
1054 }
1055 }
1056
1057 #[test]
1058 fn an_ordinary_comparison_is_null_when_either_side_is() {
1059 assert_eq!(compared(Comparison::Equal, Value::Integer(1), Value::Null), Value::Null);
1060 assert_eq!(compared(Comparison::Less, Value::Null, Value::Integer(1)), Value::Null);
1061 }
1062
1063 #[test]
1064 fn a_total_comparison_is_never_null() {
1065 assert_eq!(
1066 compared(Comparison::NotDistinctFrom, Value::Null, Value::Null),
1067 Value::Boolean(true)
1068 );
1069 assert_eq!(
1070 compared(Comparison::NotDistinctFrom, Value::Integer(1), Value::Null),
1071 Value::Boolean(false)
1072 );
1073 assert_eq!(
1074 compared(Comparison::DistinctFrom, Value::Integer(1), Value::Null),
1075 Value::Boolean(true)
1076 );
1077 }
1078
1079 #[test]
1080 fn a_string_compares_by_bytes() {
1081 assert_eq!(
1082 compared(Comparison::Less, Value::Varchar("a".into()), Value::Varchar("b".into())),
1083 Value::Boolean(true)
1084 );
1085 assert_eq!(
1086 compared(Comparison::Less, Value::Varchar("Z".into()), Value::Varchar("a".into())),
1087 Value::Boolean(true)
1088 );
1089 }
1090
1091 #[test]
1094 fn two_nans_are_one_value_and_they_sort_above_the_numbers() {
1095 assert_eq!(
1096 compared(Comparison::Equal, Value::Double(f64::NAN), Value::Double(f64::NAN)),
1097 Value::Boolean(true)
1098 );
1099 assert_eq!(
1100 compared(Comparison::Greater, Value::Double(f64::NAN), Value::Double(1e300)),
1101 Value::Boolean(true)
1102 );
1103 }
1104
1105 #[test]
1106 fn zero_has_one_value_however_it_is_signed() {
1107 assert_eq!(
1108 compared(Comparison::Equal, Value::Double(0.0), Value::Double(-0.0)),
1109 Value::Boolean(true)
1110 );
1111 }
1112
1113 #[test]
1118 fn two_intervals_of_the_same_length_are_one_value() {
1119 let day = Value::Interval { months: 0, days: 1, micros: 0 };
1120 let hours = Value::Interval { months: 0, days: 0, micros: 86_400_000_000 };
1121 let month = Value::Interval { months: 1, days: 0, micros: 0 };
1122 let thirty = Value::Interval { months: 0, days: 30, micros: 0 };
1123 let long_day = Value::Interval { months: 0, days: 0, micros: 90_000_000_000 };
1124 assert_eq!(compared(Comparison::Equal, day.clone(), hours), Value::Boolean(true));
1125 assert_eq!(compared(Comparison::Equal, month, thirty), Value::Boolean(true));
1126 assert_eq!(compared(Comparison::Greater, long_day, day), Value::Boolean(true));
1127 }
1128
1129 #[test]
1130 fn a_number_compares_the_same_however_it_is_stored() {
1131 assert_eq!(
1132 compared(Comparison::Equal, Value::Integer(3), Value::BigInt(3)),
1133 Value::Boolean(true)
1134 );
1135 assert_eq!(
1136 compared(Comparison::Less, Value::Integer(3), Value::Double(3.5)),
1137 Value::Boolean(true)
1138 );
1139 }
1140
1141 #[test]
1142 fn nulls_go_where_the_query_asked_for_them() {
1143 assert_eq!(
1144 order_with_nulls(&Value::Null, &Value::Integer(1), true).expect("orders"),
1145 Ordering::Less
1146 );
1147 assert_eq!(
1148 order_with_nulls(&Value::Null, &Value::Integer(1), false).expect("orders"),
1149 Ordering::Greater
1150 );
1151 }
1152
1153 #[test]
1154 fn two_constant_vectors_cost_one_comparison() {
1155 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 512);
1156 let right = Vector::constant(LogicalType::Integer, Value::Integer(2), 512);
1157 let result = compare(Comparison::Less, &left, &right).expect("compares");
1158 assert_eq!(result.form(), Form::Constant);
1159 assert_eq!(result.value_at(500), Value::Boolean(true));
1160 }
1161
1162 #[test]
1163 fn a_comparison_of_two_vectors_is_one_answer_per_row() {
1164 let left = Vector::from_values(
1165 LogicalType::Integer,
1166 &[Value::Integer(1), Value::Integer(5), Value::Null],
1167 )
1168 .expect("three rows");
1169 let right = Vector::constant(LogicalType::Integer, Value::Integer(3), 3);
1170 let result = compare(Comparison::Greater, &left, &right).expect("compares");
1171 assert_eq!(result.value_at(0), Value::Boolean(false));
1172 assert_eq!(result.value_at(1), Value::Boolean(true));
1173 assert_eq!(result.value_at(2), Value::Null);
1174 }
1175
1176 #[test]
1177 fn two_vectors_of_different_lengths_are_caught() {
1178 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1179 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 5);
1180 let error = compare(Comparison::Equal, &left, &right).expect_err("ragged");
1181 assert!(error.message().contains("4 row vector"), "{error}");
1182 }
1183
1184 #[test]
1185 fn turning_a_comparison_around_is_what_the_other_side_would_have_said() {
1186 for op in EVERY {
1187 let left = Value::Integer(3);
1188 let right = Value::Integer(7);
1189 assert_eq!(
1190 compare_values(op, &left, &right).expect("compares"),
1191 compare_values(op.swapped(), &right, &left).expect("compares"),
1192 "{op:?}"
1193 );
1194 }
1195 }
1196
1197 #[test]
1200 fn every_specialized_path_agrees_with_the_row_at_a_time_path() {
1201 let mut rng = Rng(0x5eed_1234_9876_4321);
1202 let types: [LogicalType; 11] = [
1203 LogicalType::Boolean,
1204 LogicalType::TinyInt,
1205 LogicalType::SmallInt,
1206 LogicalType::Integer,
1207 LogicalType::BigInt,
1208 LogicalType::HugeInt,
1209 LogicalType::UInteger,
1210 LogicalType::Float,
1211 LogicalType::Double,
1212 LogicalType::Varchar,
1213 LogicalType::Interval,
1214 ];
1215 for ty in &types {
1216 for nulls in [0u64, 1, 3] {
1217 let len = 37;
1218 let make = |rng: &mut Rng| {
1219 let values: Vec<Value> = (0..len)
1220 .map(|_| {
1221 if nulls > 0 && rng.below(nulls + 1) == 0 {
1222 Value::Null
1223 } else {
1224 sample(ty, rng)
1225 }
1226 })
1227 .collect();
1228 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1229 };
1230 let left = make(&mut rng);
1231 let right = make(&mut rng);
1232 let literal = sample(ty, &mut rng);
1233 let constant = Vector::constant(ty.clone(), literal, len);
1234 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1235 let codes: Vec<u32> =
1236 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1237 let dictionary =
1238 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1239 let ends: Vec<u32> = (1..=left.len())
1242 .map(|run| ((run * len) / left.len()).max(run) as u32)
1243 .collect();
1244 let runs = Vector::runs(ends, left.clone()).expect("one value for each run");
1245
1246 for op in EVERY {
1247 agrees(op, &left, &right);
1248 agrees(op, &left, &constant);
1249 agrees(op, &constant, &left);
1250 agrees(op, &left, &null_constant);
1251 agrees(op, &null_constant, &left);
1252 agrees(op, &dictionary, &constant);
1253 agrees(op, &constant, &dictionary);
1254 agrees(op, &dictionary, &right);
1258 agrees(op, &right, &dictionary);
1259 agrees(op, &runs, &constant);
1263 agrees(op, &constant, &runs);
1264 agrees(op, &runs, &right);
1265 agrees(op, &right, &runs);
1266 }
1267 }
1268 }
1269 }
1270
1271 fn refined(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) -> Selection {
1273 let mut out = Vec::new();
1274 for &row in kept.indices() {
1275 let index = row as usize;
1276 let answer = compare_values(op, &left.value_at(index), &right.value_at(index))
1277 .expect("the oracle is only asked about types that compare");
1278 if is_true(&answer) {
1279 out.push(row);
1280 }
1281 }
1282 Selection::from_indices(out)
1283 }
1284
1285 fn threads(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) {
1286 let fast = refine(op, left, right, kept).expect("compares");
1287 assert_eq!(
1288 fast,
1289 refined(op, left, right, kept),
1290 "{op:?} on a {:?} against a {:?} over {} rows",
1291 left.form(),
1292 right.form(),
1293 kept.len()
1294 );
1295 }
1296
1297 #[test]
1301 fn a_threaded_comparison_keeps_what_the_row_at_a_time_path_keeps() {
1302 let mut rng = Rng(0x5eed_4321_1234_9876);
1303 let types = [LogicalType::Integer, LogicalType::Double, LogicalType::Varchar];
1304 for ty in &types {
1305 for nulls in [0u64, 1, 3] {
1306 let len = 37;
1307 let make = |rng: &mut Rng| {
1308 let values: Vec<Value> = (0..len)
1309 .map(|_| {
1310 if nulls > 0 && rng.below(nulls + 1) == 0 {
1311 Value::Null
1312 } else {
1313 sample(ty, rng)
1314 }
1315 })
1316 .collect();
1317 Vector::from_values(ty.clone(), &values).expect("a flat vector")
1318 };
1319 let left = make(&mut rng);
1320 let right = make(&mut rng);
1321 let constant = Vector::constant(ty.clone(), sample(ty, &mut rng), len);
1322 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
1323 let codes: Vec<u32> =
1324 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
1325 let dictionary =
1326 Vector::dictionary(codes, left.clone()).expect("codes are in range");
1327
1328 let selections = [
1332 Selection::identity(len),
1333 Selection::from_indices((0..len as u32).filter(|row| row % 3 == 0).collect()),
1334 Selection::from_indices(vec![2, 5, 6, 17, 36]),
1335 Selection::empty(),
1336 ];
1337 for op in EVERY {
1338 for kept in &selections {
1339 threads(op, &left, &right, kept);
1340 threads(op, &left, &constant, kept);
1341 threads(op, &constant, &left, kept);
1342 threads(op, &left, &null_constant, kept);
1343 threads(op, &null_constant, &left, kept);
1344 threads(op, &constant, &null_constant, kept);
1345 threads(op, &dictionary, &constant, kept);
1346 threads(op, &constant, &dictionary, kept);
1347 threads(op, &dictionary, &right, kept);
1348 threads(op, &right, &dictionary, kept);
1349 }
1350 }
1351 }
1352 }
1353 }
1354
1355 #[test]
1359 fn a_second_conjunct_reads_only_what_the_first_one_left() {
1360 let numbers: Vec<Value> = (0..64).map(|row| Value::Integer(row % 10)).collect();
1361 let column = Vector::from_values(LogicalType::Integer, &numbers).expect("a flat vector");
1362 let three = Vector::constant(LogicalType::Integer, Value::Integer(3), 64);
1363 let seven = Vector::constant(LogicalType::Integer, Value::Integer(7), 64);
1364
1365 let first = refine(Comparison::Greater, &column, &three, &Selection::identity(64))
1366 .expect("compares");
1367 let both = refine(Comparison::Less, &column, &seven, &first).expect("compares");
1368
1369 let expected: Vec<u32> = (0..64)
1370 .filter(|row| {
1371 let value = row % 10;
1372 value > 3 && value < 7
1373 })
1374 .collect();
1375 assert_eq!(both.indices(), expected.as_slice());
1376 assert!(both.len() < first.len(), "the second conjunct narrowed the selection");
1377 }
1378
1379 #[test]
1383 fn a_null_row_is_not_kept_by_an_ordinary_comparison_and_is_by_a_total_one() {
1384 let column = Vector::from_values(
1385 LogicalType::Integer,
1386 &[Value::Integer(1), Value::Null, Value::Integer(3), Value::Null],
1387 )
1388 .expect("four rows");
1389 let cut = Vector::constant(LogicalType::Integer, Value::Integer(2), 4);
1390 let all = Selection::identity(4);
1391 assert_eq!(
1392 refine(Comparison::Less, &column, &cut, &all).expect("compares").indices(),
1393 &[0]
1394 );
1395 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 4);
1397 assert_eq!(
1398 refine(Comparison::NotDistinctFrom, &column, &nulls, &all).expect("compares").indices(),
1399 &[1, 3]
1400 );
1401 }
1402
1403 #[test]
1404 fn a_selection_past_the_end_is_caught() {
1405 let column = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
1406 let past = Selection::from_indices(vec![0, 4]);
1407 let error = refine(Comparison::Equal, &column, &column, &past).expect_err("out of range");
1408 assert!(error.message().contains("4 row vector"), "{error}");
1409 }
1410
1411 fn sample(ty: &LogicalType, rng: &mut Rng) -> Value {
1413 match ty {
1414 LogicalType::Boolean => Value::Boolean(rng.below(2) == 1),
1415 LogicalType::TinyInt => Value::TinyInt(rng.below(7) as i8 - 3),
1416 LogicalType::SmallInt => Value::SmallInt(rng.below(11) as i16 - 5),
1417 LogicalType::Integer => Value::Integer(rng.below(9) as i32 - 4),
1418 LogicalType::BigInt => Value::BigInt(rng.below(9) as i64 - 4),
1419 LogicalType::HugeInt => Value::HugeInt(i128::from(rng.below(9)) - 4),
1420 LogicalType::UInteger => Value::UInteger(rng.below(9) as u32),
1421 LogicalType::Float => Value::Float(match rng.below(5) {
1424 0 => f32::NAN,
1425 1 => -0.0,
1426 other => other as f32 - 2.0,
1427 }),
1428 LogicalType::Double => Value::Double(match rng.below(5) {
1429 0 => f64::NAN,
1430 1 => -0.0,
1431 other => other as f64 - 2.0,
1432 }),
1433 LogicalType::Interval => match rng.below(6) {
1437 0 => Value::Interval { months: 0, days: 1, micros: 0 },
1438 1 => Value::Interval { months: 0, days: 0, micros: 86_400_000_000 },
1439 2 => Value::Interval { months: 1, days: -29, micros: 86_400_000_000 },
1440 3 => Value::Interval { months: 1, days: 0, micros: 0 },
1441 4 => Value::Interval { months: 0, days: 0, micros: 90_000_000_000 },
1442 _ => Value::Interval { months: -1, days: 0, micros: 0 },
1443 },
1444 LogicalType::Varchar => Value::Varchar(
1447 match rng.below(6) {
1448 0 => "",
1449 1 => "ab",
1450 2 => "abc",
1451 3 => "abcdefghijkl",
1452 4 => "abcdefghijklm",
1453 _ => "abcdefghijklmnopqrstuvwxyz",
1454 }
1455 .to_owned(),
1456 ),
1457 other => panic!("the generator has no values for {other}"),
1458 }
1459 }
1460
1461 #[test]
1465 fn prefix_order_is_byte_order_whenever_the_prefixes_differ() {
1466 let words =
1467 ["", "a", "ab", "abc", "abcd", "abcde", "b", "abcdefghijklmnop", "abcdefghijklmnoq"];
1468 let mut column = StringColumn::new();
1469 for word in words {
1470 column.push(word);
1471 }
1472 for (i, one) in words.iter().enumerate() {
1473 for (j, other) in words.iter().enumerate() {
1474 assert_eq!(
1475 string_order(&column, i, &column, j),
1476 one.as_bytes().cmp(other.as_bytes()),
1477 "{one:?} against {other:?}"
1478 );
1479 }
1480 }
1481 }
1482
1483 #[test]
1486 fn a_dictionary_against_a_constant_reads_its_nulls_from_the_values() {
1487 let values = Vector::from_values(
1488 LogicalType::Integer,
1489 &[Value::Integer(1), Value::Null, Value::Integer(9)],
1490 )
1491 .expect("three values");
1492 let dictionary =
1493 Vector::dictionary(vec![0, 1, 2, 1, 0], values).expect("codes are in range");
1494 let constant = Vector::constant(LogicalType::Integer, Value::Integer(5), 5);
1495 let result = compare(Comparison::Less, &dictionary, &constant).expect("compares");
1496 assert_eq!(result.value_at(0), Value::Boolean(true));
1497 assert_eq!(result.value_at(1), Value::Null);
1498 assert_eq!(result.value_at(2), Value::Boolean(false));
1499 assert_eq!(result.value_at(3), Value::Null);
1500 assert_eq!(result.value_at(4), Value::Boolean(true));
1501 }
1502
1503 #[test]
1506 fn a_form_pair_with_no_loop_is_still_right_and_says_so() {
1507 let before = fallback::count(Kernel::Compare, Form::Sequence, Form::Flat);
1509 let sequence = Vector::sequence(10, 1, 4);
1510 let flat = Vector::from_values(
1511 LogicalType::BigInt,
1512 &[Value::BigInt(9), Value::BigInt(11), Value::BigInt(12), Value::Null],
1513 )
1514 .expect("four rows");
1515 let result = compare(Comparison::Less, &sequence, &flat).expect("compares");
1516 assert_eq!(result.value_at(0), Value::Boolean(false));
1517 assert_eq!(result.value_at(1), Value::Boolean(false));
1518 assert_eq!(result.value_at(2), Value::Boolean(false));
1519 assert_eq!(result.value_at(3), Value::Null);
1520 assert!(fallback::count(Kernel::Compare, Form::Sequence, Form::Flat) > before);
1521 }
1522
1523 #[test]
1533 fn a_second_level_of_codes_does_not_turn_the_loops_off() {
1534 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
1535 let values = Vector::from_values(
1536 LogicalType::Integer,
1537 &[Value::Integer(1), Value::Integer(5), Value::Integer(9)],
1538 )
1539 .expect("three rows");
1540 let once = Vector::dictionary(vec![2, 1, 0], values).expect("codes are in range");
1541 let twice = Vector::dictionary(vec![1, 2], once).expect("codes are in range");
1542 let cut = Vector::constant(LogicalType::Integer, Value::Integer(4), 2);
1543 let result = compare(Comparison::Greater, &twice, &cut).expect("compares");
1544 assert_eq!(result.value_at(0), Value::Boolean(true));
1545 assert_eq!(result.value_at(1), Value::Boolean(false));
1546 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
1547 }
1548
1549 #[test]
1553 fn a_side_that_is_entirely_null_answers_without_reading_the_other() {
1554 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 6);
1555 let flat = Vector::from_values(
1556 LogicalType::Integer,
1557 &[
1558 Value::Integer(1),
1559 Value::Integer(2),
1560 Value::Integer(3),
1561 Value::Integer(4),
1562 Value::Integer(5),
1563 Value::Integer(6),
1564 ],
1565 )
1566 .expect("six rows");
1567 agrees(Comparison::Less, &nulls, &flat);
1568 agrees(Comparison::Equal, &flat, &nulls);
1569 assert_eq!(
1570 compare(Comparison::Less, &nulls, &flat).expect("compares").validity(),
1571 &Validity::AllInvalid
1572 );
1573 }
1574
1575 #[test]
1578 fn an_empty_comparison_is_an_empty_answer() {
1579 let left = Vector::from_values(LogicalType::Integer, &[]).expect("no rows");
1580 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 0);
1581 let result = compare(Comparison::Equal, &left, &right).expect("compares");
1582 assert_eq!(result.len(), 0);
1583 }
1584
1585 fn words() -> Vector {
1588 Vector::from_values(
1589 LogicalType::Varchar,
1590 &[
1591 Value::Varchar("http://a".into()),
1592 Value::Varchar("http://b".into()),
1593 Value::Null,
1594 Value::Varchar("ab".into()),
1595 Value::Varchar("http://a".into()),
1596 Value::Varchar("z".into()),
1597 ],
1598 )
1599 .expect("six rows")
1600 }
1601
1602 #[test]
1608 fn a_literal_built_early_answers_what_one_built_here_answers() {
1609 let column = words();
1610 let value = Value::Varchar("http://b".into());
1611 let constant = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
1612 let held = Held::of(&LogicalType::Varchar, &value).expect("a varchar has a column");
1613 let kept = Selection::from_indices(vec![0, 1, 3, 5]);
1614 for op in [
1615 Comparison::Equal,
1616 Comparison::NotEqual,
1617 Comparison::Less,
1618 Comparison::LessOrEqual,
1619 Comparison::Greater,
1620 Comparison::GreaterOrEqual,
1621 Comparison::DistinctFrom,
1622 Comparison::NotDistinctFrom,
1623 ] {
1624 let prepared = compare_prepared(op, &column, &constant, Some(&held)).expect("compares");
1625 assert_eq!(prepared, compare(op, &column, &constant).expect("compares"), "{op:?}");
1626 let flipped = compare_prepared(op, &constant, &column, Some(&held)).expect("compares");
1628 assert_eq!(flipped, compare(op, &constant, &column).expect("compares"), "{op:?}");
1629 let refined =
1630 refine_prepared(op, &column, &constant, &kept, Some(&held)).expect("refines");
1631 assert_eq!(refined, refine(op, &column, &constant, &kept).expect("refines"), "{op:?}");
1632 }
1633 }
1634
1635 #[test]
1642 fn a_literal_built_for_another_value_is_ignored() {
1643 let column = words();
1644 let constant = Vector::constant(LogicalType::Varchar, Value::Varchar("z".into()), 6);
1645 let wrong = Held::of(&LogicalType::Varchar, &Value::Varchar("ab".into()))
1646 .expect("a varchar has a column");
1647 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&wrong))
1648 .expect("compares");
1649 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1650 let other = Held::of(&LogicalType::Integer, &Value::Integer(1)).expect("an integer column");
1653 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&other))
1654 .expect("compares");
1655 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
1656 }
1657
1658 #[test]
1661 fn a_packed_column_against_a_constant_answers_what_the_oracle_answers() {
1662 let values: Vec<i32> = (0..64).map(|row| 1000 + (row * 37) % 500).collect();
1663 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1664 .expect("integers are an i32 layout");
1665 let packed = flat.bit_packed().expect("a five hundred wide range packs");
1666 assert_eq!(packed.form(), Form::BitPacked);
1667 for literal in [999, 1000, 1200, 1499, 1500, 2000] {
1668 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 64);
1669 for op in EVERY {
1670 agrees(op, &packed, &constant);
1671 agrees(op, &constant, &packed);
1672 }
1673 }
1674 }
1675
1676 #[test]
1680 fn a_packed_column_with_nulls_answers_what_the_oracle_answers() {
1681 let values: Vec<i32> = (0..32).map(|row| 40 + row * 3).collect();
1682 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1683 .expect("integers are an i32 layout")
1684 .with_validity(Validity::from_iter(32, |row| row % 5 != 0));
1685 let packed = flat.bit_packed().expect("packs");
1686 let constant = Vector::constant(LogicalType::Integer, Value::Integer(80), 32);
1687 for op in EVERY {
1688 agrees(op, &packed, &constant);
1689 }
1690 }
1691
1692 #[test]
1695 fn a_literal_outside_the_packed_range_answers_the_whole_vector_at_once() {
1696 let before = fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant);
1697 let values: Vec<i32> = (0..16).map(|row| 500 + row).collect();
1698 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
1699 .expect("integers are an i32 layout");
1700 let packed = flat.bit_packed().expect("packs");
1701 let literals = [-1, 0, 499, 516, 100_000];
1702 for literal in literals {
1703 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 16);
1704 for op in EVERY {
1705 agrees(op, &packed, &constant);
1706 }
1707 }
1708 let total = EVERY.iter().filter(|op| op.is_total()).count();
1713 assert_eq!(
1714 fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant) - before,
1715 (literals.len() * total) as u64,
1716 "only the two total comparisons fall through"
1717 );
1718 }
1719
1720 #[test]
1723 fn refining_a_selection_over_a_packed_column_keeps_the_same_rows() {
1724 let values: Vec<i32> = (0..64).map(|row| 200 + (row * 11) % 128).collect();
1725 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.clone().into()))
1726 .expect("integers are an i32 layout");
1727 let packed = flat.bit_packed().expect("packs");
1728 let kept = Selection::from_predicate(64, |row| row % 3 == 0);
1729 let constant = Vector::constant(LogicalType::Integer, Value::Integer(260), 64);
1730 let packed_rows = refine(Comparison::Greater, &packed, &constant, &kept).expect("refines");
1731 let flat_rows = refine(Comparison::Greater, &flat, &constant, &kept).expect("refines");
1732 assert_eq!(packed_rows.indices(), flat_rows.indices());
1733 assert!(!packed_rows.is_empty(), "the literal is inside the range");
1734 }
1735
1736 fn urls(count: usize) -> Vector {
1739 let mut rng = Rng(0x5eed_1234);
1740 let values: Vec<Value> = (0..count)
1741 .map(|_| {
1742 let host = rng.below(6);
1743 let path = rng.below(40);
1744 Value::Varchar(format!("http://example{host}.test/a/rather/long/path/{path}"))
1745 })
1746 .collect();
1747 Vector::from_values(LogicalType::Varchar, &values).expect("strings")
1748 }
1749
1750 #[test]
1751 fn a_string_view_column_against_a_literal_answers_what_the_oracle_answers() {
1752 let before = fallback::count(Kernel::Compare, Form::StringView, Form::Constant);
1753 let shared = urls(64).shared_text().expect("shares");
1754 assert_eq!(shared.form(), Form::StringView);
1755 let literals = ["http://example3.test/a/rather/long/path/7", "a", "zzz", ""];
1756 for literal in literals {
1757 let value = Value::Varchar(literal.to_owned());
1758 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1759 for op in EVERY {
1760 agrees(op, &shared, &constant);
1761 agrees(op, &constant, &shared);
1762 }
1763 }
1764 assert_eq!(
1765 fallback::count(Kernel::Compare, Form::StringView, Form::Constant),
1766 before,
1767 "the form has a loop of its own for every comparison"
1768 );
1769 }
1770
1771 #[test]
1772 fn a_string_view_column_against_another_one_answers_what_the_oracle_answers() {
1773 let shared = urls(48).shared_text().expect("shares");
1774 let other = urls(48).shared_text().expect("shares");
1775 let flat = urls(48);
1776 for op in EVERY {
1777 agrees(op, &shared, &other);
1778 agrees(op, &shared, &flat);
1779 agrees(op, &flat, &shared);
1780 }
1781 }
1782
1783 #[test]
1784 fn the_nulls_of_a_string_view_column_are_the_nulls_the_oracle_sees() {
1785 let shared = urls(32)
1786 .with_validity(Validity::from_iter(32, |row| row % 4 != 1))
1787 .shared_text()
1788 .expect("shares");
1789 let constant =
1790 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 32);
1791 for op in EVERY {
1792 agrees(op, &shared, &constant);
1793 }
1794 }
1795
1796 #[test]
1797 fn a_compressed_column_against_a_literal_answers_what_the_oracle_answers() {
1798 let before = fallback::count(Kernel::Compare, Form::Fsst, Form::Constant);
1799 let flat = urls(64);
1800 let coded = flat.clone().compressed().expect("compresses");
1801 assert_eq!(coded.form(), Form::Fsst);
1802 let present = match coded.value_at(9) {
1803 Value::Varchar(text) => text,
1804 other => panic!("a string column reads back strings, not {other:?}"),
1805 };
1806 for literal in [present.as_str(), "http://example3.test/nothing/like/it", ""] {
1807 let value = Value::Varchar(literal.to_owned());
1808 let constant = Vector::constant(LogicalType::Varchar, value, 64);
1809 for op in EVERY {
1810 agrees(op, &coded, &constant);
1811 agrees(op, &constant, &coded);
1812 }
1813 }
1814 let ordered = EVERY.len() - 2;
1818 assert_eq!(
1819 fallback::count(Kernel::Compare, Form::Fsst, Form::Constant) - before,
1820 (3 * ordered) as u64,
1821 "only the comparisons that need an order fall through"
1822 );
1823 }
1824
1825 #[test]
1828 fn every_row_of_a_compressed_column_matches_itself_and_nothing_else() {
1829 let flat = urls(48);
1830 let coded = flat.clone().compressed().expect("compresses");
1831 for row in 0..48 {
1832 let constant = Vector::constant(LogicalType::Varchar, flat.value_at(row), 48);
1833 let equal = compare(Comparison::Equal, &coded, &constant).expect("compares");
1834 for other in 0..48 {
1835 let want = flat.value_at(other) == flat.value_at(row);
1836 assert_eq!(
1837 equal.value_at(other),
1838 Value::Boolean(want),
1839 "row {row} against {other}"
1840 );
1841 }
1842 }
1843 }
1844
1845 #[test]
1846 fn the_nulls_of_a_compressed_column_are_the_nulls_the_oracle_sees() {
1847 let coded = urls(32)
1848 .with_validity(Validity::from_iter(32, |row| row % 3 != 0))
1849 .compressed()
1850 .expect("compresses");
1851 let value = coded.value_at(1);
1852 let constant = Vector::constant(LogicalType::Varchar, value, 32);
1853 for op in EVERY {
1854 agrees(op, &coded, &constant);
1855 }
1856 }
1857
1858 #[test]
1862 fn a_filter_over_either_string_form_keeps_the_same_rows() {
1863 let flat = urls(96);
1864 let shared = flat.clone().shared_text().expect("shares");
1865 let constant =
1866 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 96);
1867 let kept = Selection::from_predicate(96, |row| row % 5 != 0);
1868 for op in EVERY {
1869 let over_flat = refine(op, &flat, &constant, &kept).expect("refines");
1870 let over_shared = refine(op, &shared, &constant, &kept).expect("refines");
1871 assert_eq!(over_shared.indices(), over_flat.indices(), "{op:?}");
1872 }
1873 }
1874}