1use std::borrow::Cow;
72use std::cell::RefCell;
73use std::cmp::Ordering;
74use std::sync::Arc;
75
76use rudb_common::{Error, LogicalType, Result, Value, interval_micros};
77use rudb_vector::{
78 Coded, Data, Form, Packed, Selection, StringColumn, StringView, Validity, Vector,
79};
80
81use crate::fallback::{self, Kernel};
82use crate::logic::is_true;
83use crate::number::{approximate, integral};
84use crate::peel::{self, Found};
85use crate::prepare::Held;
86use crate::shape::{first, identity, nulls_of, single};
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
90pub enum Comparison {
91 Equal,
93 NotEqual,
95 Less,
97 LessOrEqual,
99 Greater,
101 GreaterOrEqual,
103 DistinctFrom,
105 NotDistinctFrom,
107}
108
109impl Comparison {
110 #[must_use]
112 pub fn is_total(self) -> bool {
113 matches!(self, Self::DistinctFrom | Self::NotDistinctFrom)
114 }
115
116 #[must_use]
123 pub fn swapped(self) -> Self {
124 match self {
125 Self::Less => Self::Greater,
126 Self::LessOrEqual => Self::GreaterOrEqual,
127 Self::Greater => Self::Less,
128 Self::GreaterOrEqual => Self::LessOrEqual,
129 same => same,
130 }
131 }
132
133 #[must_use]
139 fn holds(self, order: Ordering) -> bool {
140 match self {
141 Self::Equal => order == Ordering::Equal,
142 Self::NotEqual => order != Ordering::Equal,
143 Self::Less => order == Ordering::Less,
144 Self::LessOrEqual => order != Ordering::Greater,
145 Self::Greater => order == Ordering::Greater,
146 Self::GreaterOrEqual => order != Ordering::Less,
147 Self::DistinctFrom | Self::NotDistinctFrom => false,
148 }
149 }
150}
151
152pub fn compare(op: Comparison, left: &Vector, right: &Vector) -> Result<Vector> {
158 compare_prepared(op, left, right, None)
159}
160
161pub fn compare_prepared(
171 op: Comparison,
172 left: &Vector,
173 right: &Vector,
174 held: Option<&Held>,
175) -> Result<Vector> {
176 if left.len() != right.len() {
177 return Err(Error::internal(format!(
178 "a comparison of a {} row vector with a {} row one",
179 left.len(),
180 right.len()
181 )));
182 }
183 let len = left.len();
184 if left.form() == Form::Constant && right.form() == Form::Constant && len > 0 {
185 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
186 return Ok(Vector::constant(LogicalType::Boolean, single, len));
187 }
188
189 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
190 if !op.is_total()
194 && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
195 && len > 0
196 {
197 return boolean(vec![false; len], Validity::AllInvalid, len);
198 }
199
200 if let Some(answers) = external_text_literal(op, left, right, len, identity, held)? {
201 let validity = left_valid.and(&right_valid, len);
202 return boolean(blank_the_nulls(answers, &validity), validity, len);
203 }
204 if let Some(answers) =
205 specialized(op, left, right, &left_valid, &right_valid, len, identity, held)
206 {
207 let validity =
208 if op.is_total() { Validity::AllValid } else { left_valid.and(&right_valid, len) };
209 return boolean(blank_the_nulls(answers, &validity), validity, len);
210 }
211
212 fallback::record(Kernel::Compare, left.form(), right.form());
213 let mut values = Vec::with_capacity(len);
214 for index in 0..len {
217 values.push(compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?);
218 }
219 Vector::from_values(LogicalType::Boolean, &values)
220}
221
222pub fn select_prepared(
236 op: Comparison,
237 left: &Vector,
238 right: &Vector,
239 held: Option<&Held>,
240) -> Result<Selection> {
241 if left.len() != right.len() {
242 return Err(Error::internal(format!(
243 "a comparison of a {} row vector with a {} row one",
244 left.len(),
245 right.len()
246 )));
247 }
248 let len = left.len();
249 if len == 0 {
250 return Ok(Selection::empty());
251 }
252 if left.form() == Form::Constant && right.form() == Form::Constant {
253 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
254 return Ok(if is_true(&single) { Selection::identity(len) } else { Selection::empty() });
255 }
256 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
257 if !op.is_total() && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
258 {
259 return Ok(Selection::empty());
260 }
261 if u32::try_from(len).is_ok() {
264 if let Some(answers) = external_text_literal(op, left, right, len, identity, held)? {
265 return Ok(crate::select::picked_flat(
266 &answers[..len],
267 &left_valid.and(&right_valid, len),
268 ));
269 }
270 if left_valid == Validity::AllValid && right_valid == Validity::AllValid {
271 if let Some(kept) = flat_kept(op, left, right, None, held) {
272 return Ok(kept);
273 }
274 if let Some(kept) = packed_kept(op, left, right, None) {
275 return Ok(kept);
276 }
277 }
278 if let Some(answers) =
279 specialized(op, left, right, &left_valid, &right_valid, len, identity, held)
280 {
281 let validity =
282 if op.is_total() { Validity::AllValid } else { left_valid.and(&right_valid, len) };
283 return Ok(crate::select::picked_flat(&answers[..len], &validity));
284 }
285 }
286 Ok(crate::select::selection(&compare_prepared(op, left, right, held)?, len))
287}
288
289fn flat_kept(
301 op: Comparison,
302 left: &Vector,
303 right: &Vector,
304 rows: Option<&[u32]>,
305 held: Option<&Held>,
306) -> Option<Selection> {
307 if op.is_total() || left.logical_type() != right.logical_type() {
308 return None;
309 }
310 let len = left.len();
311 let data = left.data()?;
312 macro_rules! ordered {
313 ($values:expr, $side:expr) => {{
314 let (values, side) = ($values, $side);
315 match op {
316 Comparison::Equal => flat_where(rows, values, side, |a, b| a == b),
317 Comparison::NotEqual => flat_where(rows, values, side, |a, b| a != b),
318 Comparison::Less => flat_where(rows, values, side, |a, b| a < b),
319 Comparison::LessOrEqual => flat_where(rows, values, side, |a, b| a <= b),
320 Comparison::Greater => flat_where(rows, values, side, |a, b| a > b),
321 Comparison::GreaterOrEqual => flat_where(rows, values, side, |a, b| a >= b),
322 Comparison::DistinctFrom | Comparison::NotDistinctFrom => return None,
323 }
324 }};
325 }
326 macro_rules! layouts {
327 ($($variant:ident),+ $(,)?) => {
328 if let Some(others) = right.data() {
329 match (data, others) {
330 $(
331 (Data::$variant(values), Data::$variant(others)) => {
332 let (values, others) = (values.get(..len)?, others.get(..len)?);
333 Some(ordered!(values, Side::Column(others)))
334 }
335 )+
336 _ => None,
337 }
338 } else {
339 let column = readied(held, left.logical_type(), right.constant_value()?)?;
340 match (data, column.data()?) {
341 $(
342 (Data::$variant(values), Data::$variant(wanted)) => {
343 let (values, wanted) = (values.get(..len)?, *wanted.first()?);
344 Some(ordered!(values, Side::Constant(wanted)))
345 }
346 )+
347 _ => None,
348 }
349 }
350 };
351 }
352 layouts!(Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UInt128)
353}
354
355#[derive(Clone, Copy)]
357enum Side<'a, T> {
358 Column(&'a [T]),
359 Constant(T),
360}
361
362fn flat_where<T: Copy>(
368 rows: Option<&[u32]>,
369 values: &[T],
370 side: Side<'_, T>,
371 test: impl Fn(T, T) -> bool,
372) -> Selection {
373 let len = values.len();
374 match (rows, side) {
375 (Some(rows), Side::Constant(wanted)) => {
376 kept_where(Some(rows), len, |row| test(values[row], wanted))
377 }
378 (Some(rows), Side::Column(others)) => {
379 kept_where(Some(rows), len, |row| test(values[row], others[row]))
380 }
381 (None, Side::Constant(wanted)) => kept_in_blocks(
382 len,
383 |base, flags| {
384 for (flag, &value) in flags.iter_mut().zip(&values[base..base + 64]) {
385 *flag = u8::from(test(value, wanted));
386 }
387 },
388 |row| test(values[row], wanted),
389 ),
390 (None, Side::Column(others)) => {
391 let others = &others[..len];
392 kept_in_blocks(
393 len,
394 |base, flags| {
395 let pairs = values[base..base + 64].iter().zip(&others[base..base + 64]);
396 for (flag, (&value, &other)) in flags.iter_mut().zip(pairs) {
397 *flag = u8::from(test(value, other));
398 }
399 },
400 |row| test(values[row], others[row]),
401 )
402 }
403 }
404}
405
406fn packed_kept(
421 op: Comparison,
422 left: &Vector,
423 right: &Vector,
424 rows: Option<&[u32]>,
425) -> Option<Selection> {
426 if op.is_total() || left.logical_type() != right.logical_type() {
427 return None;
428 }
429 let (one, other) = (left.packed_parts()?, right.packed_parts()?);
430 if one.width() > 61 || other.width() > 61 {
431 return None;
432 }
433 if one.ceiling() < other.base() || other.ceiling() < one.base() {
434 return None;
435 }
436 let shift = i64::try_from(other.base() - one.base()).ok()?;
438 if shift.unsigned_abs() > 1 << 61 {
439 return None;
440 }
441 let len = left.len();
442 let dense = rows.is_none_or(|rows| rows.len() * 8 >= len);
443 macro_rules! ordered {
444 ($at:expr, $rows:expr) => {{
445 let at = $at;
446 match op {
447 Comparison::Equal => kept_where($rows, len, |row| {
448 let (a, b) = at(row);
449 a == b
450 }),
451 Comparison::NotEqual => kept_where($rows, len, |row| {
452 let (a, b) = at(row);
453 a != b
454 }),
455 Comparison::Less => kept_where($rows, len, |row| {
456 let (a, b) = at(row);
457 a < b
458 }),
459 Comparison::LessOrEqual => kept_where($rows, len, |row| {
460 let (a, b) = at(row);
461 a <= b
462 }),
463 Comparison::Greater => kept_where($rows, len, |row| {
464 let (a, b) = at(row);
465 a > b
466 }),
467 Comparison::GreaterOrEqual => kept_where($rows, len, |row| {
468 let (a, b) = at(row);
469 a >= b
470 }),
471 Comparison::DistinctFrom | Comparison::NotDistinctFrom => return None,
472 }
473 }};
474 }
475 #[expect(
476 clippy::cast_possible_wrap,
477 reason = "both widths are at most 61 bits, so a code is well inside an i64"
478 )]
479 let kept = if dense {
480 if one.width() <= 30 && other.width() <= 30 && shift.unsigned_abs() < 1 << 30 {
491 #[expect(
492 clippy::cast_possible_truncation,
493 reason = "a code is below 2^30 and the shift is below 2^30 either way"
494 )]
495 let (a, b) = {
496 let (mut a, mut b) = (Vec::new(), Vec::new());
497 one.unpack_mapped(0, len, &mut a, |code| code as i32);
498 other.unpack_mapped(0, len, &mut b, |code| (code as i64 + shift) as i32);
499 (a, b)
500 };
501 flat_by(op, rows, &a, &b)?
502 } else {
503 let (mut a, mut b) = (Vec::new(), Vec::new());
504 one.unpack_mapped(0, len, &mut a, |code| code as i64);
505 other.unpack_mapped(0, len, &mut b, |code| code as i64 + shift);
506 flat_by(op, rows, &a, &b)?
507 }
508 } else {
509 ordered!(|row: usize| (one.code(row) as i64, other.code(row) as i64 + shift), rows)
510 };
511 Some(kept)
512}
513
514#[derive(Clone, Copy, Debug)]
517pub struct Bound<'a> {
518 pub op: Comparison,
520 pub value: &'a Value,
522 pub held: Option<&'a Held>,
524}
525
526#[must_use]
541pub fn select_range(
542 column: &Vector,
543 low: Bound<'_>,
544 high: Bound<'_>,
545 live: Option<&[u32]>,
546) -> Option<Selection> {
547 let len = column.len();
548 if len == 0 || u32::try_from(len).is_err() || nulls_of(column) != Validity::AllValid {
549 return None;
550 }
551 let integral = column.packed_parts().is_some()
553 || matches!(
554 column.data(),
555 Some(
556 Data::Int8(_)
557 | Data::Int16(_)
558 | Data::Int32(_)
559 | Data::Int64(_)
560 | Data::UInt8(_)
561 | Data::UInt16(_)
562 | Data::UInt32(_)
563 | Data::UInt64(_)
564 )
565 );
566 if !integral {
567 return None;
568 }
569 let ty = column.logical_type();
570 let literal = |bound: Bound<'_>| -> Option<i128> {
571 if bound.value.is_null() {
572 return None;
573 }
574 let single = readied(bound.held, ty, bound.value)?;
575 if single.logical_type() != ty {
576 return None;
577 }
578 Some(match single.data()? {
579 Data::Int8(values) => i128::from(*values.first()?),
580 Data::Int16(values) => i128::from(*values.first()?),
581 Data::Int32(values) => i128::from(*values.first()?),
582 Data::Int64(values) => i128::from(*values.first()?),
583 Data::UInt8(values) => i128::from(*values.first()?),
584 Data::UInt16(values) => i128::from(*values.first()?),
585 Data::UInt32(values) => i128::from(*values.first()?),
586 Data::UInt64(values) => i128::from(*values.first()?),
587 _ => return None,
588 })
589 };
590 let low = match low.op {
592 Comparison::GreaterOrEqual => literal(low)?,
593 Comparison::Greater => literal(low)? + 1,
594 _ => return None,
595 };
596 let high = match high.op {
597 Comparison::LessOrEqual => literal(high)?,
598 Comparison::Less => literal(high)? - 1,
599 _ => return None,
600 };
601 if let Some(packed) = column.packed_parts() {
602 return packed_range(&packed, len, low, high, live);
603 }
604 macro_rules! flat {
605 ($($variant:ident: $signed:ty => $unsigned:ty),+ $(,)?) => {
606 match column.data()? {
607 $(
608 Data::$variant(values) => {
609 let values = values.get(..len)?;
610 let low = low.max(i128::from(<$signed>::MIN));
611 let high = high.min(i128::from(<$signed>::MAX));
612 if low > high {
613 return Some(Selection::empty());
614 }
615 #[expect(
616 clippy::cast_possible_truncation,
617 clippy::cast_sign_loss,
618 reason = "both ends were clamped to the type, and the distance is read \
619 unsigned on purpose"
620 )]
621 let (low, span) = (low as $signed, (high - low) as $unsigned);
622 #[allow(clippy::cast_sign_loss, reason = "the distance is read unsigned")]
624 let within = |value: $signed| value.wrapping_sub(low) as $unsigned <= span;
625 Some(match live {
626 Some(rows) => kept_where(Some(rows), len, |row| within(values[row])),
627 None => kept_in_blocks(
628 len,
629 |base, flags| {
630 for (flag, &value) in
631 flags.iter_mut().zip(&values[base..base + 64])
632 {
633 *flag = u8::from(within(value));
634 }
635 },
636 |row| within(values[row]),
637 ),
638 })
639 }
640 )+
641 _ => None,
642 }
643 };
644 }
645 flat!(
646 Int8: i8 => u8,
647 Int16: i16 => u16,
648 Int32: i32 => u32,
649 Int64: i64 => u64,
650 UInt8: u8 => u8,
651 UInt16: u16 => u16,
652 UInt32: u32 => u32,
653 UInt64: u64 => u64,
654 )
655}
656
657fn packed_range(
661 packed: &Packed<'_>,
662 len: usize,
663 low: i128,
664 high: i128,
665 live: Option<&[u32]>,
666) -> Option<Selection> {
667 let (low, high) = (low.max(packed.base()), high.min(ceiling_of(packed)?));
668 if low > high {
669 return Some(Selection::empty());
670 }
671 #[expect(
672 clippy::cast_possible_truncation,
673 clippy::cast_sign_loss,
674 reason = "both ends are inside the codes the width holds, so both differences fit a u64"
675 )]
676 let (from, span) = ((low - packed.base()) as u64, (high - low) as u64);
677 let within = |code: u64| code.wrapping_sub(from) <= span;
678 Some(match live {
679 Some(rows) => kept_where(Some(rows), len, |row| within(packed.code(row))),
680 None => kept_in_blocks(
681 len,
682 |base, flags| {
683 let mut codes = [0_u64; 64];
684 packed.unpack(base, &mut codes);
685 for (flag, &code) in flags.iter_mut().zip(&codes) {
686 *flag = u8::from(within(code));
687 }
688 },
689 |row| within(packed.code(row)),
690 ),
691 })
692}
693
694fn flat_by<T: Copy + PartialOrd>(
697 op: Comparison,
698 rows: Option<&[u32]>,
699 a: &[T],
700 b: &[T],
701) -> Option<Selection> {
702 let side = Side::Column(b);
703 Some(match op {
704 Comparison::Equal => flat_where(rows, a, side, |x, y| x == y),
705 Comparison::NotEqual => flat_where(rows, a, side, |x, y| x != y),
706 Comparison::Less => flat_where(rows, a, side, |x, y| x < y),
707 Comparison::LessOrEqual => flat_where(rows, a, side, |x, y| x <= y),
708 Comparison::Greater => flat_where(rows, a, side, |x, y| x > y),
709 Comparison::GreaterOrEqual => flat_where(rows, a, side, |x, y| x >= y),
710 Comparison::DistinctFrom | Comparison::NotDistinctFrom => return None,
711 })
712}
713
714#[inline]
717fn kept_where(rows: Option<&[u32]>, len: usize, held: impl Fn(usize) -> bool) -> Selection {
718 let Some(rows) = rows else {
719 let fill = |base: usize, flags: &mut [u8; 64]| {
720 for (bit, flag) in flags.iter_mut().enumerate() {
721 *flag = u8::from(held(base + bit));
722 }
723 };
724 return kept_in_blocks(len, fill, &held);
725 };
726 let mut kept = 0;
727 let mut out = vec![0_u32; rows.len()];
728 for &row in rows {
729 out[kept] = row;
730 kept += usize::from(held(row as usize));
731 }
732 out.truncate(kept);
733 Selection::from_indices(out)
734}
735
736#[expect(
747 clippy::cast_possible_truncation,
748 reason = "the caller checked that the row count fits in a u32 before getting here"
749)]
750#[inline]
751pub(crate) fn kept_in_blocks(
752 len: usize,
753 fill: impl Fn(usize, &mut [u8; 64]),
754 held: impl Fn(usize) -> bool,
755) -> Selection {
756 let mut out = Vec::with_capacity(len);
757 let mut base = 0;
758 while base + 64 <= len {
759 let mut flags = [0_u8; 64];
760 fill(base, &mut flags);
761 let mut mask = 0_u64;
762 for (lane, eight) in flags.chunks_exact(8).enumerate() {
763 let bytes = u64::from_le_bytes(eight.try_into().unwrap_or_default());
764 mask |= (bytes.wrapping_mul(0x0102_0408_1020_4080) >> 56) << (lane * 8);
766 }
767 if mask == u64::MAX {
768 out.extend(base as u32..(base + 64) as u32);
769 } else {
770 while mask != 0 {
771 out.push((base + mask.trailing_zeros() as usize) as u32);
772 mask &= mask - 1;
773 }
774 }
775 base += 64;
776 }
777 out.extend((base..len).filter(|&index| held(index)).map(|index| index as u32));
778 Selection::from_indices(out)
779}
780
781pub fn refine(
799 op: Comparison,
800 left: &Vector,
801 right: &Vector,
802 kept: &Selection,
803) -> Result<Selection> {
804 refine_prepared(op, left, right, kept, None)
805}
806
807pub fn refine_prepared(
817 op: Comparison,
818 left: &Vector,
819 right: &Vector,
820 kept: &Selection,
821 held: Option<&Held>,
822) -> Result<Selection> {
823 if left.len() != right.len() {
824 return Err(Error::internal(format!(
825 "a comparison of a {} row vector with a {} row one",
826 left.len(),
827 right.len()
828 )));
829 }
830 let len = left.len();
831 if !rudb_vector::below(kept.indices(), len) {
835 return Err(Error::internal(format!("a selection past the end of a {len} row vector")));
836 }
837 if kept.is_empty() {
838 return Ok(Selection::empty());
839 }
840 if left.form() == Form::Constant && right.form() == Form::Constant {
841 let single = compare_values(op, &left.try_value_at(0)?, &right.try_value_at(0)?)?;
842 return Ok(if is_true(&single) { kept.clone() } else { Selection::empty() });
843 }
844
845 let (left_valid, right_valid) = (nulls_of(left), nulls_of(right));
846 if !op.is_total() && (left_valid == Validity::AllInvalid || right_valid == Validity::AllInvalid)
847 {
848 return Ok(Selection::empty());
849 }
850
851 let rows = kept.indices();
852 if left_valid == Validity::AllValid && right_valid == Validity::AllValid {
853 if let Some(kept) = flat_kept(op, left, right, Some(rows), held) {
854 return Ok(kept);
855 }
856 if let Some(kept) = packed_kept(op, left, right, Some(rows)) {
857 return Ok(kept);
858 }
859 }
860 let map = |slot: usize| rows[slot] as usize;
861 if let Some(answers) = external_text_literal(op, left, right, kept.len(), map, held)? {
862 return Ok(narrowed(&answers, rows, |slot| {
863 let row = rows[slot] as usize;
864 left_valid.is_valid(row) && right_valid.is_valid(row)
865 }));
866 }
867 if let Some(answers) =
868 specialized(op, left, right, &left_valid, &right_valid, kept.len(), map, held)
869 {
870 if op.is_total() || (left_valid == Validity::AllValid && right_valid == Validity::AllValid)
873 {
874 return Ok(narrowed(&answers, rows, |_| true));
875 }
876 return Ok(narrowed(&answers, rows, |slot| {
880 let row = rows[slot] as usize;
881 left_valid.is_valid(row) && right_valid.is_valid(row)
882 }));
883 }
884
885 fallback::record(Kernel::Compare, left.form(), right.form());
886 let mut out = Vec::with_capacity(kept.len());
887 for &row in rows {
890 let index = row as usize;
891 if is_true(&compare_values(op, &left.try_value_at(index)?, &right.try_value_at(index)?)?) {
892 out.push(row);
893 }
894 }
895 Ok(Selection::from_indices(out))
896}
897
898fn external_text_literal<M>(
914 op: Comparison,
915 left: &Vector,
916 right: &Vector,
917 len: usize,
918 map: M,
919 held: Option<&Held>,
920) -> Result<Option<Vec<bool>>>
921where
922 M: Fn(usize) -> usize + Copy,
923{
924 if op.is_total()
925 || left.logical_type() != &LogicalType::Varchar
926 || right.logical_type() != &LogicalType::Varchar
927 {
928 return Ok(None);
929 }
930 let (column, literal, swapped) = match (left.constant_value(), right.constant_value()) {
931 (None, Some(Value::Varchar(literal))) if left.positions().is_some() => {
932 (left, literal.as_bytes(), false)
933 }
934 (Some(Value::Varchar(literal)), None) if right.positions().is_some() => {
935 (right, literal.as_bytes(), true)
936 }
937 _ => return Ok(None),
938 };
939 let op = if swapped { op.swapped() } else { op };
942 let same = op == Comparison::Equal;
943 if matches!(op, Comparison::Equal | Comparison::NotEqual) {
944 if let Some(held) = held.filter(|held| held.text() == Some(literal)) {
948 if let Some(found) = held.lookup().find(column, literal) {
951 return Ok(Some(against_code(column, found?, len, map, same)?));
952 }
953 let decide = |dictionary: &Vector, code: usize| -> Result<bool> {
954 let found = if literal.is_empty() {
955 dictionary.try_bytes_len_at(code)?.is_some_and(|length| length == 0)
956 } else {
957 dictionary.try_bytes_at(code)?.is_some_and(|bytes| bytes == literal)
958 };
959 Ok(found)
960 };
961 if let Some(answers) = held.peel().answer(column, len, map, decide) {
962 let mut answers = answers?;
963 if !same {
964 for answer in &mut answers {
965 *answer = !*answer;
966 }
967 }
968 return Ok(Some(answers));
969 }
970 }
971 let mut answers = Vec::with_capacity(len);
972 for slot in 0..len {
973 let row = map(slot);
974 let equal = if literal.is_empty() {
977 column.try_bytes_len_at(row)?.is_some_and(|length| length == 0)
978 } else {
979 column.try_bytes_at(row)?.is_some_and(|bytes| bytes == literal)
980 };
981 answers.push(equal == same);
982 }
983 return Ok(Some(answers));
984 }
985 if let Some(answers) = by_rank(op, column, literal, len, map)? {
986 return Ok(Some(answers));
987 }
988 let mut answers = Vec::with_capacity(len);
989 for slot in 0..len {
990 let row = map(slot);
991 let order = match column.try_bytes_at(row)? {
995 Some(bytes) => bytes.cmp(literal),
996 None => Ordering::Equal,
997 };
998 answers.push(op.holds(order));
999 }
1000 Ok(Some(answers))
1001}
1002
1003fn by_rank<M>(
1025 op: Comparison,
1026 column: &Vector,
1027 literal: &[u8],
1028 len: usize,
1029 map: M,
1030) -> Result<Option<Vec<bool>>>
1031where
1032 M: Fn(usize) -> usize,
1033{
1034 let Some((codes, dictionary)) = column.shared_dictionary_parts() else { return Ok(None) };
1035 let Some(ranks) = dictionary.ranks() else { return Ok(None) };
1036 let Some(order) = dictionary.code_ranks() else { return Ok(None) };
1037 let (below, equal) = peel::below(dictionary, ranks, literal)?;
1038 let cut = match op {
1041 Comparison::Less | Comparison::GreaterOrEqual => below,
1042 _ => below + usize::from(equal),
1043 };
1044 let under = matches!(op, Comparison::Less | Comparison::LessOrEqual);
1045 let mut answers = Vec::with_capacity(len);
1046 for slot in 0..len {
1048 let code = *codes
1049 .get(map(slot))
1050 .ok_or_else(|| Error::internal("a ranked row is past the end of its codes"))?;
1051 let rank = *order
1052 .get(code as usize)
1053 .ok_or_else(|| Error::internal("a ranked code is past the end of its dictionary"))?;
1054 answers.push(((rank as usize) < cut) == under);
1055 }
1056 Ok(Some(answers))
1057}
1058
1059#[must_use]
1081pub fn select_against_rank(
1082 op: Comparison,
1083 column: &Vector,
1084 dictionary: &Arc<Vector>,
1085 rank: u32,
1086 rows: usize,
1087) -> Option<Selection> {
1088 let (codes, values) = column.shared_dictionary_parts()?;
1089 if !Arc::ptr_eq(values, dictionary) {
1090 return None;
1091 }
1092 let order = values.code_ranks()?;
1093 let validity = column.validity();
1094 let live = !validity.has_nulls(rows);
1095 let rows = rows.min(codes.len());
1096 let mut kept = vec![0_u32; rows];
1097 let mut count = 0;
1098 for (row, &code) in codes.iter().enumerate().take(rows) {
1102 let at = *order.get(code as usize)?;
1103 let held = match op {
1104 Comparison::Less => at < rank,
1105 Comparison::LessOrEqual => at <= rank,
1106 Comparison::Greater => at > rank,
1107 Comparison::GreaterOrEqual => at >= rank,
1108 _ => return None,
1109 };
1110 kept[count] = u32::try_from(row).ok()?;
1111 count += usize::from(held & (live || validity.is_valid(row)));
1113 }
1114 kept.truncate(count);
1115 Some(Selection::from_indices(kept))
1116}
1117
1118#[must_use]
1127pub fn rank_at(column: &Vector, row: usize) -> Option<(Arc<Vector>, u32)> {
1128 let (codes, values) = column.shared_dictionary_parts()?;
1129 if !column.validity().is_valid(row) {
1130 return None;
1131 }
1132 let order = values.code_ranks()?;
1133 let code = *codes.get(row)?;
1134 let rank = *order.get(code as usize)?;
1135 Some((Arc::clone(values), rank))
1136}
1137
1138#[must_use]
1152pub fn rank_within(column: &Vector, row: usize, dictionary: &Arc<Vector>) -> Option<u32> {
1153 let (codes, values) = column.shared_dictionary_parts()?;
1154 if !Arc::ptr_eq(values, dictionary) || !column.validity().is_valid(row) {
1155 return None;
1156 }
1157 let order = values.code_ranks()?;
1158 let code = *codes.get(row)?;
1159 Some(*order.get(code as usize)?)
1160}
1161
1162fn against_code<M>(
1170 column: &Vector,
1171 found: Found,
1172 len: usize,
1173 map: M,
1174 same: bool,
1175) -> Result<Vec<bool>>
1176where
1177 M: Fn(usize) -> usize,
1178{
1179 let Found::At(wanted) = found else { return Ok(vec![!same; len]) };
1180 let (codes, _) = column
1181 .shared_dictionary_parts()
1182 .ok_or_else(|| Error::internal("a resolved literal lost the codes it was resolved for"))?;
1183 if codes.len() < column.len() {
1188 return Err(Error::internal("a compared column is longer than its codes"));
1189 }
1190 Ok((0..len).map(|slot| (codes[map(slot)] == wanted) == same).collect())
1192}
1193
1194fn narrowed<L: Fn(usize) -> bool>(answers: &[bool], rows: &[u32], live: L) -> Selection {
1201 let mut out = vec![0_u32; answers.len()];
1202 let mut count = 0;
1203 for (slot, &answer) in answers.iter().enumerate() {
1204 out[count] = rows[slot];
1205 count += usize::from(answer & live(slot));
1207 }
1208 out.truncate(count);
1209 Selection::from_indices(out)
1210}
1211
1212fn boolean(answers: Vec<bool>, validity: Validity, len: usize) -> Result<Vector> {
1214 let validity = if len == 0 { Validity::AllValid } else { validity.normalize(len) };
1218 Ok(Vector::flat(LogicalType::Boolean, Data::Bool(answers.into()))?.with_validity(validity))
1219}
1220
1221fn blank_the_nulls(mut answers: Vec<bool>, validity: &Validity) -> Vec<bool> {
1229 if let Validity::Mask(mask) = validity {
1230 for (index, answer) in answers.iter_mut().enumerate() {
1231 if !mask.get(index) {
1232 *answer = false;
1233 }
1234 }
1235 }
1236 answers
1237}
1238
1239#[expect(
1251 clippy::too_many_arguments,
1252 reason = "two sides, two validities, the operator, the length, the index mapping and the \
1253 literal that was built early, all of which the branches below need"
1254)]
1255fn specialized<M>(
1256 op: Comparison,
1257 left: &Vector,
1258 right: &Vector,
1259 left_valid: &Validity,
1260 right_valid: &Validity,
1261 len: usize,
1262 map: M,
1263 held: Option<&Held>,
1264) -> Option<Vec<bool>>
1265where
1266 M: Fn(usize) -> usize + Copy,
1267{
1268 if left.logical_type() != right.logical_type() {
1272 return None;
1273 }
1274 let equality = matches!(
1278 op,
1279 Comparison::Equal
1280 | Comparison::NotEqual
1281 | Comparison::DistinctFrom
1282 | Comparison::NotDistinctFrom
1283 );
1284 if *left.logical_type() == LogicalType::Bit && !equality {
1285 return None;
1286 }
1287
1288 let (one, other) = (through(left), through(right));
1291
1292 if let (Some(one), Some(other)) = (&one, &other) {
1293 return match (one, other) {
1294 (Through::Direct(a), Through::Direct(b)) => {
1295 dispatch(op, len, a, map, b, map, left_valid, right_valid, map)
1296 }
1297 (Through::Coded(codes, a), Through::Direct(b)) => dispatch(
1298 op,
1299 len,
1300 a,
1301 |slot| codes[map(slot)] as usize,
1302 b,
1303 map,
1304 left_valid,
1305 right_valid,
1306 map,
1307 ),
1308 (Through::Direct(a), Through::Coded(codes, b)) => dispatch(
1309 op,
1310 len,
1311 a,
1312 map,
1313 b,
1314 |slot| codes[map(slot)] as usize,
1315 left_valid,
1316 right_valid,
1317 map,
1318 ),
1319 (Through::Coded(left_codes, a), Through::Coded(right_codes, b)) => dispatch(
1320 op,
1321 len,
1322 a,
1323 |slot| left_codes[map(slot)] as usize,
1324 b,
1325 |slot| right_codes[map(slot)] as usize,
1326 left_valid,
1327 right_valid,
1328 map,
1329 ),
1330 };
1331 }
1332 if !op.is_total() {
1338 if let (Some(packed), Some(value)) = (left.packed_parts(), right.constant_value()) {
1339 let wanted = exact(held, left.logical_type(), value)?;
1340 return Some(packed_against(op, &packed, wanted, len, map));
1341 }
1342 if let (Some(value), Some(packed)) = (left.constant_value(), right.packed_parts()) {
1343 let wanted = exact(held, right.logical_type(), value)?;
1344 return Some(packed_against(op.swapped(), &packed, wanted, len, map));
1345 }
1346 if let (Some(one), Some(other)) = (packing(left), packing(right)) {
1347 return packings_against_each_other(op, &one, &other, len, map);
1348 }
1349 if let (Some(one), Some(other)) = (packing(left), &other) {
1357 return packing_against_run(op, &one, other, len, map);
1358 }
1359 if let (Some(one), Some(other)) = (&one, packing(right)) {
1360 return packing_against_run(op.swapped(), &other, one, len, map);
1361 }
1362 }
1363 if let (Some(one), Some(value)) = (&one, right.constant_value()) {
1364 let column = readied(held, left.logical_type(), value)?;
1365 let other = column.data()?;
1366 return match one {
1367 Through::Direct(a) => {
1368 dispatch(op, len, a, map, other, first, left_valid, right_valid, map)
1369 }
1370 Through::Coded(codes, a) => dispatch(
1371 op,
1372 len,
1373 a,
1374 |slot| codes[map(slot)] as usize,
1375 other,
1376 first,
1377 left_valid,
1378 right_valid,
1379 map,
1380 ),
1381 };
1382 }
1383 if let (Some(value), Some(other)) = (left.constant_value(), &other) {
1384 let column = readied(held, right.logical_type(), value)?;
1386 let one = column.data()?;
1387 return match other {
1388 Through::Direct(b) => {
1389 dispatch(op.swapped(), len, b, map, one, first, right_valid, left_valid, map)
1390 }
1391 Through::Coded(codes, b) => dispatch(
1392 op.swapped(),
1393 len,
1394 b,
1395 |slot| codes[map(slot)] as usize,
1396 one,
1397 first,
1398 right_valid,
1399 left_valid,
1400 map,
1401 ),
1402 };
1403 }
1404 if matches!(op, Comparison::Equal | Comparison::NotEqual) {
1409 if let (Some(coded), Some(value)) = (left.coded_parts(), right.constant_value()) {
1410 let wanted = encoded(&coded, held, left.logical_type(), value)?;
1411 return Some(coded_against(op, &coded, &wanted, len, map));
1412 }
1413 if let (Some(value), Some(coded)) = (left.constant_value(), right.coded_parts()) {
1414 let wanted = encoded(&coded, held, right.logical_type(), value)?;
1415 return Some(coded_against(op, &coded, &wanted, len, map));
1416 }
1417 }
1418 if let (Some((one, one_arena)), Some((other, other_arena))) =
1424 (left.text_parts(), right.text_parts())
1425 {
1426 return Some(sweep(
1427 op,
1428 len,
1429 |index| view_order(one.get(map(index)), one_arena, other.get(map(index)), other_arena),
1430 left_valid,
1431 right_valid,
1432 map,
1433 ));
1434 }
1435 if let (Some((one, one_arena)), Some(value)) = (left.text_parts(), right.constant_value()) {
1439 let column = readied(held, left.logical_type(), value)?;
1440 let (other, other_arena) = column.text_parts()?;
1441 let wanted = other.first();
1442 return Some(sweep(
1443 op,
1444 len,
1445 |index| view_order(one.get(map(index)), one_arena, wanted, other_arena),
1446 left_valid,
1447 right_valid,
1448 map,
1449 ));
1450 }
1451 if let (Some(value), Some((other, other_arena))) = (left.constant_value(), right.text_parts()) {
1452 let column = readied(held, right.logical_type(), value)?;
1454 let (one, one_arena) = column.text_parts()?;
1455 let wanted = one.first();
1456 return Some(sweep(
1457 op.swapped(),
1458 len,
1459 |index| view_order(other.get(map(index)), other_arena, wanted, one_arena),
1460 right_valid,
1461 left_valid,
1462 map,
1463 ));
1464 }
1465 if let (Some((codes, values)), Some(value)) = (left.positions(), right.constant_value()) {
1466 let one = values.data()?;
1467 let column = readied(held, left.logical_type(), value)?;
1468 let other = column.data()?;
1469 let at = |index: usize| codes[map(index)] as usize;
1470 return dispatch(op, len, one, at, other, first, left_valid, right_valid, map);
1471 }
1472 if let (Some(value), Some((codes, values))) = (left.constant_value(), right.positions()) {
1473 let other = values.data()?;
1474 let column = readied(held, right.logical_type(), value)?;
1475 let one = column.data()?;
1476 let at = |index: usize| codes[map(index)] as usize;
1477 return dispatch(op.swapped(), len, other, at, one, first, right_valid, left_valid, map);
1478 }
1479 if let (Some((codes, values)), Some(other)) = (left.positions(), right.data()) {
1485 let one = values.data()?;
1486 let at = |index: usize| codes[map(index)] as usize;
1487 return dispatch(op, len, one, at, other, map, left_valid, right_valid, map);
1488 }
1489 if let (Some(one), Some((codes, values))) = (left.data(), right.positions()) {
1490 let other = values.data()?;
1491 let at = |index: usize| codes[map(index)] as usize;
1492 return dispatch(op.swapped(), len, other, at, one, map, right_valid, left_valid, map);
1493 }
1494 None
1495}
1496
1497fn exact(held: Option<&Held>, ty: &LogicalType, value: &Value) -> Option<i128> {
1504 let column = readied(held, ty, value)?;
1505 let data = column.data()?;
1506 data.signed_at(0).or_else(|| data.unsigned_at(0).and_then(|value| i128::try_from(value).ok()))
1507}
1508
1509fn encoded(
1515 coded: &Coded<'_>,
1516 held: Option<&Held>,
1517 ty: &LogicalType,
1518 value: &Value,
1519) -> Option<Vec<u8>> {
1520 let column = readied(held, ty, value)?;
1521 let (views, arena) = column.text_parts()?;
1522 Some(coded.encode(views.first()?.bytes_in(arena)?))
1523}
1524
1525fn coded_against<M>(
1531 op: Comparison,
1532 coded: &Coded<'_>,
1533 wanted: &[u8],
1534 len: usize,
1535 map: M,
1536) -> Vec<bool>
1537where
1538 M: Fn(usize) -> usize + Copy,
1539{
1540 let same = op == Comparison::Equal;
1541 let mut answers = Vec::with_capacity(len);
1542 for row in 0..len {
1543 answers.push((coded.row(map(row)) == Some(wanted)) == same);
1544 }
1545 answers
1546}
1547
1548fn packed_against<M>(
1566 op: Comparison,
1567 packed: &Packed<'_>,
1568 wanted: i128,
1569 len: usize,
1570 map: M,
1571) -> Vec<bool>
1572where
1573 M: Fn(usize) -> usize + Copy,
1574{
1575 let Some(code) = packed.code_of(wanted) else {
1576 let above = wanted > packed.ceiling();
1579 let same = match op {
1580 Comparison::Equal | Comparison::NotDistinctFrom => false,
1581 Comparison::NotEqual | Comparison::DistinctFrom => true,
1582 Comparison::Less | Comparison::LessOrEqual => above,
1583 Comparison::Greater | Comparison::GreaterOrEqual => !above,
1584 };
1585 return vec![same; len];
1586 };
1587 thread_local! {
1588 static CODES: RefCell<Vec<u64>> = const { RefCell::new(Vec::new()) };
1589 }
1590 let mut held = CODES.with_borrow_mut(std::mem::take);
1594 packed.codes_into(map, len, &mut held);
1597 let codes = &held[..len];
1598 macro_rules! sweep {
1600 ($test:expr) => {{
1601 let test = $test;
1602 codes.iter().map(|&found| test(found, code)).collect()
1603 }};
1604 }
1605 let answers: Vec<bool> = match op {
1606 Comparison::Equal | Comparison::NotDistinctFrom => sweep!(|found, want| found == want),
1607 Comparison::NotEqual | Comparison::DistinctFrom => sweep!(|found, want| found != want),
1608 Comparison::Less => sweep!(|found, want| found < want),
1609 Comparison::LessOrEqual => sweep!(|found, want| found <= want),
1610 Comparison::Greater => sweep!(|found, want| found > want),
1611 Comparison::GreaterOrEqual => sweep!(|found, want| found >= want),
1612 };
1613 CODES.with_borrow_mut(|slot| *slot = held);
1614 answers
1615}
1616
1617fn packed_against_packed<L, R, M>(
1641 op: Comparison,
1642 left: &Packed<'_>,
1643 at_left: L,
1644 right: &Packed<'_>,
1645 at_right: R,
1646 len: usize,
1647 map: M,
1648) -> Option<Vec<bool>>
1649where
1650 L: Fn(usize) -> usize,
1651 R: Fn(usize) -> usize,
1652 M: Fn(usize) -> usize + Copy,
1653{
1654 let (low, high) = (left.base(), ceiling_of(left)?);
1655 let (other_low, other_high) = (right.base(), ceiling_of(right)?);
1656 if high < other_low || other_high < low {
1657 let below = high < other_low;
1660 let same = match op {
1661 Comparison::Equal | Comparison::NotDistinctFrom => false,
1662 Comparison::NotEqual | Comparison::DistinctFrom => true,
1663 Comparison::Less | Comparison::LessOrEqual => below,
1664 Comparison::Greater | Comparison::GreaterOrEqual => !below,
1665 };
1666 return Some(vec![same; len]);
1667 }
1668 let mut answers = vec![false; len];
1671 macro_rules! sweep {
1673 ($test:expr) => {{
1674 let test = $test;
1675 for (slot, answer) in answers.iter_mut().enumerate() {
1676 let row = map(slot);
1677 *answer = test(
1678 low + i128::from(left.code(at_left(row))),
1679 other_low + i128::from(right.code(at_right(row))),
1680 );
1681 }
1682 }};
1683 }
1684 match op {
1685 Comparison::Equal | Comparison::NotDistinctFrom => sweep!(|one, other| one == other),
1686 Comparison::NotEqual | Comparison::DistinctFrom => sweep!(|one, other| one != other),
1687 Comparison::Less => sweep!(|one, other| one < other),
1688 Comparison::LessOrEqual => sweep!(|one, other| one <= other),
1689 Comparison::Greater => sweep!(|one, other| one > other),
1690 Comparison::GreaterOrEqual => sweep!(|one, other| one >= other),
1691 }
1692 Some(answers)
1693}
1694
1695enum Packing<'a> {
1701 Straight(Packed<'a>),
1703 Coded(Cow<'a, [u32]>, Packed<'a>),
1705}
1706
1707fn packing(vector: &Vector) -> Option<Packing<'_>> {
1709 if let Some(packed) = vector.packed_parts() {
1710 return Some(Packing::Straight(packed));
1711 }
1712 let (codes, values) = vector.positions()?;
1713 Some(Packing::Coded(codes, values.packed_parts()?))
1714}
1715
1716fn packings_against_each_other<M>(
1719 op: Comparison,
1720 left: &Packing<'_>,
1721 right: &Packing<'_>,
1722 len: usize,
1723 map: M,
1724) -> Option<Vec<bool>>
1725where
1726 M: Fn(usize) -> usize + Copy,
1727{
1728 match (left, right) {
1729 (Packing::Straight(one), Packing::Straight(other)) => {
1730 packed_against_packed(op, one, identity, other, identity, len, map)
1731 }
1732 (Packing::Straight(one), Packing::Coded(codes, other)) => {
1733 packed_against_packed(op, one, identity, other, |row| codes[row] as usize, len, map)
1734 }
1735 (Packing::Coded(codes, one), Packing::Straight(other)) => {
1736 packed_against_packed(op, one, |row| codes[row] as usize, other, identity, len, map)
1737 }
1738 (Packing::Coded(codes, one), Packing::Coded(others, other)) => packed_against_packed(
1739 op,
1740 one,
1741 |row| codes[row] as usize,
1742 other,
1743 |row| others[row] as usize,
1744 len,
1745 map,
1746 ),
1747 }
1748}
1749
1750fn packing_against_run<M>(
1757 op: Comparison,
1758 packed: &Packing<'_>,
1759 run: &Through<'_>,
1760 len: usize,
1761 map: M,
1762) -> Option<Vec<bool>>
1763where
1764 M: Fn(usize) -> usize + Copy,
1765{
1766 match (packed, run) {
1767 (Packing::Straight(one), Through::Direct(other)) => {
1768 packed_against_flat(op, one, identity, other, identity, len, map)
1769 }
1770 (Packing::Straight(one), Through::Coded(codes, other)) => {
1771 packed_against_flat(op, one, identity, other, |row| codes[row] as usize, len, map)
1772 }
1773 (Packing::Coded(codes, one), Through::Direct(other)) => {
1774 packed_against_flat(op, one, |row| codes[row] as usize, other, identity, len, map)
1775 }
1776 (Packing::Coded(codes, one), Through::Coded(others, other)) => packed_against_flat(
1777 op,
1778 one,
1779 |row| codes[row] as usize,
1780 other,
1781 |row| others[row] as usize,
1782 len,
1783 map,
1784 ),
1785 }
1786}
1787
1788fn packed_against_flat<L, R, M>(
1802 op: Comparison,
1803 packed: &Packed<'_>,
1804 at_packed: L,
1805 flat: &Data,
1806 at_flat: R,
1807 len: usize,
1808 map: M,
1809) -> Option<Vec<bool>>
1810where
1811 L: Fn(usize) -> usize,
1812 R: Fn(usize) -> usize,
1813 M: Fn(usize) -> usize + Copy,
1814{
1815 ceiling_of(packed)?;
1816 let base = packed.base();
1817 macro_rules! layouts {
1818 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1819 match flat {
1820 $(
1821 Data::$variant(run) => Some(numbers_compared(op, len, |slot| {
1822 let row = map(slot);
1823 (
1824 base + i128::from(packed.code(at_packed(row))),
1825 i128::from(run[at_flat(row)]),
1826 )
1827 })),
1828 )+
1829 _ => None,
1832 }
1833 };
1834 }
1835 rudb_vector::for_each_layout!(exact, layouts)
1836}
1837
1838fn numbers_compared<P>(op: Comparison, len: usize, pair: P) -> Vec<bool>
1844where
1845 P: Fn(usize) -> (i128, i128),
1846{
1847 let mut answers = vec![false; len];
1848 macro_rules! sweep {
1850 ($test:expr) => {{
1851 let test = $test;
1852 for (slot, answer) in answers.iter_mut().enumerate() {
1853 let (one, other) = pair(slot);
1854 *answer = test(one, other);
1855 }
1856 }};
1857 }
1858 match op {
1859 Comparison::Equal | Comparison::NotDistinctFrom => sweep!(|one, other| one == other),
1860 Comparison::NotEqual | Comparison::DistinctFrom => sweep!(|one, other| one != other),
1861 Comparison::Less => sweep!(|one, other| one < other),
1862 Comparison::LessOrEqual => sweep!(|one, other| one <= other),
1863 Comparison::Greater => sweep!(|one, other| one > other),
1864 Comparison::GreaterOrEqual => sweep!(|one, other| one >= other),
1865 }
1866 answers
1867}
1868
1869fn ceiling_of(packed: &Packed<'_>) -> Option<i128> {
1875 let mask = u64::MAX >> (u64::BITS - packed.width());
1876 packed.base().checked_add(i128::from(mask))
1877}
1878
1879enum Through<'a> {
1893 Direct(&'a Data),
1895 Coded(Cow<'a, [u32]>, &'a Data),
1897}
1898
1899fn through(vector: &Vector) -> Option<Through<'_>> {
1906 if let Some(data) = vector.data() {
1907 return Some(Through::Direct(data));
1908 }
1909 let (codes, values) = vector.positions()?;
1910 Some(Through::Coded(codes, values.data()?))
1911}
1912
1913#[expect(
1919 clippy::too_many_arguments,
1920 reason = "two sides with an index each, the operator, the length and two validities, all of \
1921 which the loop needs and none of which is worth a struct that exists for one call"
1922)]
1923fn dispatch<L, R, V>(
1924 op: Comparison,
1925 len: usize,
1926 left: &Data,
1927 at_left: L,
1928 right: &Data,
1929 at_right: R,
1930 left_valid: &Validity,
1931 right_valid: &Validity,
1932 at_valid: V,
1933) -> Option<Vec<bool>>
1934where
1935 L: Fn(usize) -> usize,
1936 R: Fn(usize) -> usize,
1937 V: Fn(usize) -> usize,
1938{
1939 macro_rules! layouts {
1940 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
1941 match (left, right) {
1942 $(
1943 (Data::$variant(one), Data::$variant(other)) => Some(sweep(
1944 op,
1945 len,
1946 |index| one[at_left(index)].cmp(&other[at_right(index)]),
1947 left_valid,
1948 right_valid,
1949 &at_valid,
1950 )),
1951 )+
1952 (Data::Float32(one), Data::Float32(other)) => Some(sweep(
1955 op,
1956 len,
1957 |index| {
1958 float_order(
1959 f64::from(one[at_left(index)]),
1960 f64::from(other[at_right(index)]),
1961 )
1962 },
1963 left_valid,
1964 right_valid,
1965 &at_valid,
1966 )),
1967 (Data::Float64(one), Data::Float64(other)) => Some(sweep(
1968 op,
1969 len,
1970 |index| float_order(one[at_left(index)], other[at_right(index)]),
1971 left_valid,
1972 right_valid,
1973 &at_valid,
1974 )),
1975 (Data::Interval(one), Data::Interval(other)) => Some(sweep(
1978 op,
1979 len,
1980 |index| {
1981 let (months, days, micros) = one[at_left(index)];
1982 let (bm, bd, bu) = other[at_right(index)];
1983 interval_micros(months, days, micros).cmp(&interval_micros(bm, bd, bu))
1984 },
1985 left_valid,
1986 right_valid,
1987 &at_valid,
1988 )),
1989 (Data::Varlen(one), Data::Varlen(other)) => Some(sweep(
1990 op,
1991 len,
1992 |index| string_order(one, at_left(index), other, at_right(index)),
1993 left_valid,
1994 right_valid,
1995 &at_valid,
1996 )),
1997 _ => None,
1998 }
1999 };
2000 }
2001 rudb_vector::for_each_layout!(ordered, layouts)
2002}
2003
2004fn readied<'a>(held: Option<&'a Held>, ty: &LogicalType, value: &Value) -> Option<Cow<'a, Vector>> {
2010 match held {
2011 Some(held) if held.matches(ty, value) => Some(Cow::Borrowed(held.single())),
2012 _ => Some(Cow::Owned(single(ty, value)?)),
2013 }
2014}
2015
2016fn string_order(
2024 left: &StringColumn,
2025 at_left: usize,
2026 right: &StringColumn,
2027 at_right: usize,
2028) -> Ordering {
2029 view_order(left.views().get(at_left), left.arena(), right.views().get(at_right), right.arena())
2030}
2031
2032fn view_order(
2038 one: Option<&StringView>,
2039 one_arena: &[u8],
2040 other: Option<&StringView>,
2041 other_arena: &[u8],
2042) -> Ordering {
2043 let (Some(one), Some(other)) = (one, other) else {
2044 return Ordering::Equal;
2045 };
2046 let (prefix, against) = (one.prefix(), other.prefix());
2047 if prefix != against {
2048 return prefix.cmp(&against);
2049 }
2050 let bytes = one.bytes_in(one_arena).unwrap_or_default();
2055 let against_bytes = other.bytes_in(other_arena).unwrap_or_default();
2056 bytes.cmp(against_bytes)
2057}
2058
2059fn sweep<O, V>(
2065 op: Comparison,
2066 len: usize,
2067 order_at: O,
2068 left_valid: &Validity,
2069 right_valid: &Validity,
2070 at_valid: V,
2071) -> Vec<bool>
2072where
2073 O: Fn(usize) -> Ordering,
2074 V: Fn(usize) -> usize,
2075{
2076 let mut answers = vec![false; len];
2077 match op {
2078 Comparison::Equal => fill(&mut answers, order_at, |o| o == Ordering::Equal),
2079 Comparison::NotEqual => fill(&mut answers, order_at, |o| o != Ordering::Equal),
2080 Comparison::Less => fill(&mut answers, order_at, |o| o == Ordering::Less),
2081 Comparison::LessOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Greater),
2082 Comparison::Greater => fill(&mut answers, order_at, |o| o == Ordering::Greater),
2083 Comparison::GreaterOrEqual => fill(&mut answers, order_at, |o| o != Ordering::Less),
2084 Comparison::DistinctFrom => {
2085 total(&mut answers, order_at, left_valid, right_valid, at_valid);
2086 for answer in &mut answers {
2087 *answer = !*answer;
2088 }
2089 }
2090 Comparison::NotDistinctFrom => {
2091 total(&mut answers, order_at, left_valid, right_valid, at_valid);
2092 }
2093 }
2094 answers
2095}
2096
2097#[inline]
2099fn fill<O, H>(answers: &mut [bool], order_at: O, held: H)
2100where
2101 O: Fn(usize) -> Ordering,
2102 H: Fn(Ordering) -> bool,
2103{
2104 for (index, answer) in answers.iter_mut().enumerate() {
2105 *answer = held(order_at(index));
2106 }
2107}
2108
2109fn total<O, V>(
2116 answers: &mut [bool],
2117 order_at: O,
2118 left_valid: &Validity,
2119 right_valid: &Validity,
2120 at_valid: V,
2121) where
2122 O: Fn(usize) -> Ordering,
2123 V: Fn(usize) -> usize,
2124{
2125 if *left_valid == Validity::AllValid && *right_valid == Validity::AllValid {
2126 fill(answers, order_at, |o| o == Ordering::Equal);
2127 return;
2128 }
2129 for (index, answer) in answers.iter_mut().enumerate() {
2130 let row = at_valid(index);
2131 *answer = match (left_valid.is_valid(row), right_valid.is_valid(row)) {
2132 (true, true) => order_at(index) == Ordering::Equal,
2133 (false, false) => true,
2134 _ => false,
2135 };
2136 }
2137}
2138
2139pub fn compare_values(op: Comparison, left: &Value, right: &Value) -> Result<Value> {
2145 if op.is_total() {
2146 let same = match (left.is_null(), right.is_null()) {
2147 (true, true) => true,
2148 (true, false) | (false, true) => false,
2149 (false, false) => order(left, right)? == Ordering::Equal,
2150 };
2151 return Ok(Value::Boolean(match op {
2152 Comparison::NotDistinctFrom => same,
2153 _ => !same,
2154 }));
2155 }
2156 if left.is_null() || right.is_null() {
2157 return Ok(Value::Null);
2158 }
2159 let ordering = order(left, right)?;
2160 let held = match op {
2161 Comparison::Equal => ordering == Ordering::Equal,
2162 Comparison::NotEqual => ordering != Ordering::Equal,
2163 Comparison::Less => ordering == Ordering::Less,
2164 Comparison::LessOrEqual => ordering != Ordering::Greater,
2165 Comparison::Greater => ordering == Ordering::Greater,
2166 Comparison::GreaterOrEqual => ordering != Ordering::Less,
2167 Comparison::DistinctFrom | Comparison::NotDistinctFrom => {
2168 return Err(Error::internal("a total comparison reached the ordered path"));
2169 }
2170 };
2171 Ok(Value::Boolean(held))
2172}
2173
2174pub fn order(left: &Value, right: &Value) -> Result<Ordering> {
2185 match (left, right) {
2186 (Value::Null, _) | (_, Value::Null) => {
2187 Err(Error::internal("a null reached the ordering path"))
2188 }
2189 (Value::Boolean(a), Value::Boolean(b)) => Ok(a.cmp(b)),
2190 (Value::Varchar(a), Value::Varchar(b)) => Ok(a.as_bytes().cmp(b.as_bytes())),
2191 (Value::Blob(a), Value::Blob(b)) => Ok(a.cmp(b)),
2192 (Value::Bit(a), Value::Bit(b)) => Ok(rudb_common::bit::cmp(a, b)),
2193 (Value::Date(a), Value::Date(b)) => Ok(a.cmp(b)),
2194 (Value::Time(a), Value::Time(b))
2197 | (Value::TimeTz(a), Value::TimeTz(b))
2198 | (Value::Timestamp(a), Value::Timestamp(b))
2199 | (Value::TimestampTz(a), Value::TimestampTz(b)) => Ok(a.cmp(b)),
2200 (
2201 Value::Interval { months: am, days: ad, micros: au },
2202 Value::Interval { months: bm, days: bd, micros: bu },
2203 ) => Ok(interval_micros(*am, *ad, *au).cmp(&interval_micros(*bm, *bd, *bu))),
2204 (Value::List { values: a, .. }, Value::List { values: b, .. }) => list_order(a, b),
2205 (Value::Struct(a), Value::Struct(b)) => {
2208 for ((_, one), (_, other)) in a.iter().zip(b) {
2209 let ordering = order_with_nulls(one, other, false)?;
2210 if ordering != Ordering::Equal {
2211 return Ok(ordering);
2212 }
2213 }
2214 Ok(a.len().cmp(&b.len()))
2215 }
2216 (Value::Map { entries: a, .. }, Value::Map { entries: b, .. }) => {
2219 for ((key, value), (other_key, other_value)) in a.iter().zip(b) {
2220 let ordering = order_with_nulls(key, other_key, false)?.then(order_with_nulls(
2221 value,
2222 other_value,
2223 false,
2224 )?);
2225 if ordering != Ordering::Equal {
2226 return Ok(ordering);
2227 }
2228 }
2229 Ok(a.len().cmp(&b.len()))
2230 }
2231 _ => numeric_order(left, right),
2232 }
2233}
2234
2235fn list_order(left: &[Value], right: &[Value]) -> Result<Ordering> {
2250 for (one, other) in left.iter().zip(right) {
2251 let ordering = order_with_nulls(one, other, false)?;
2252 if ordering != Ordering::Equal {
2253 return Ok(ordering);
2254 }
2255 }
2256 Ok(left.len().cmp(&right.len()))
2257}
2258
2259fn numeric_order(left: &Value, right: &Value) -> Result<Ordering> {
2261 if let (Some(a), Some(b)) = (integral(left), integral(right)) {
2262 return Ok(a.cmp(&b));
2263 }
2264 if let (
2265 Value::Decimal { unscaled: a, scale: sa, .. },
2266 Value::Decimal { unscaled: b, scale: sb, .. },
2267 ) = (left, right)
2268 && sa == sb
2269 {
2270 return Ok(a.cmp(b));
2271 }
2272 match (approximate(left), approximate(right)) {
2273 (Some(a), Some(b)) => Ok(float_order(a, b)),
2274 _ => Err(Error::not_implemented(format!(
2275 "comparing {} with {}",
2276 left.logical_type(),
2277 right.logical_type()
2278 ))),
2279 }
2280}
2281
2282pub(crate) fn float_order(left: f64, right: f64) -> Ordering {
2284 if left == right {
2285 return Ordering::Equal;
2286 }
2287 match (left.is_nan(), right.is_nan()) {
2288 (true, true) => Ordering::Equal,
2289 (true, false) => Ordering::Greater,
2290 (false, true) => Ordering::Less,
2291 (false, false) => left.partial_cmp(&right).unwrap_or(Ordering::Equal),
2292 }
2293}
2294
2295pub fn order_with_nulls(left: &Value, right: &Value, nulls_first: bool) -> Result<Ordering> {
2304 match (left.is_null(), right.is_null()) {
2305 (true, true) => Ok(Ordering::Equal),
2306 (true, false) => Ok(if nulls_first { Ordering::Less } else { Ordering::Greater }),
2307 (false, true) => Ok(if nulls_first { Ordering::Greater } else { Ordering::Less }),
2308 (false, false) => order(left, right),
2309 }
2310}
2311
2312#[cfg(test)]
2313mod tests {
2314 use super::*;
2315
2316 fn compared(op: Comparison, left: Value, right: Value) -> Value {
2317 compare_values(op, &left, &right).expect("these types compare")
2318 }
2319
2320 const EVERY: [Comparison; 8] = [
2322 Comparison::Equal,
2323 Comparison::NotEqual,
2324 Comparison::Less,
2325 Comparison::LessOrEqual,
2326 Comparison::Greater,
2327 Comparison::GreaterOrEqual,
2328 Comparison::DistinctFrom,
2329 Comparison::NotDistinctFrom,
2330 ];
2331
2332 fn oracle(op: Comparison, left: &Vector, right: &Vector) -> Vector {
2338 let values: Vec<Value> = (0..left.len())
2339 .map(|index| {
2340 compare_values(op, &left.value_at(index), &right.value_at(index))
2341 .expect("the oracle is only asked about types that compare")
2342 })
2343 .collect();
2344 Vector::from_values(LogicalType::Boolean, &values).expect("booleans")
2345 }
2346
2347 fn agrees(op: Comparison, left: &Vector, right: &Vector) {
2351 let fast = compare(op, left, right).expect("compares");
2352 let slow = oracle(op, left, right);
2353 assert_eq!(fast, slow, "{op:?} on a {:?} against a {:?}", left.form(), right.form());
2354 }
2355
2356 #[test]
2359 fn rows_kept_in_blocks_are_the_rows_a_plain_filter_keeps() {
2360 let shapes: [fn(usize) -> bool; 5] = [
2361 |_| false,
2362 |_| true,
2363 |row| row % 7 == 3,
2364 |row| (row / 64) % 3 == 1,
2365 |row| (row / 64) % 2 == 0 || row % 61 == 0,
2366 ];
2367 for len in [0, 1, 63, 64, 65, 128, 1000, 2048] {
2368 for held in shapes {
2369 let blocks = kept_where(None, len, held);
2370 let plain: Vec<u32> = (0..len)
2371 .filter(|&row| held(row))
2372 .map(|row| u32::try_from(row).expect("small"))
2373 .collect();
2374 assert_eq!(blocks.indices(), plain.as_slice(), "{len} rows");
2375 }
2376 }
2377 let values: Vec<Value> =
2378 (0..2000).map(|row| Value::SmallInt(if row % 50 == 0 { 3 } else { 0 })).collect();
2379 let column = Vector::from_values(LogicalType::SmallInt, &values).expect("smallints");
2380 let zero = Vector::constant(LogicalType::SmallInt, Value::SmallInt(0), 2000);
2381 let others: Vec<Value> = (0..2000).map(|row| Value::SmallInt(row % 5)).collect();
2382 let others = Vector::from_values(LogicalType::SmallInt, &others).expect("smallints");
2383 for op in [Comparison::NotEqual, Comparison::Equal, Comparison::Less] {
2384 agrees_and_selects(op, &column, &zero);
2385 agrees_and_selects(op, &column, &others);
2386 }
2387 }
2388
2389 fn agrees_and_selects(op: Comparison, left: &Vector, right: &Vector) {
2393 agrees(op, left, right);
2394 let slow = oracle(op, left, right);
2395 let picked = select_prepared(op, left, right, None).expect("selects");
2396 assert_eq!(
2397 picked.indices(),
2398 crate::select::selection(&slow, slow.len()).indices(),
2399 "{op:?} selected on a {:?} against a {:?}",
2400 left.form(),
2401 right.form()
2402 );
2403 }
2404
2405 struct Rng(u64);
2408
2409 impl Rng {
2410 fn next(&mut self) -> u64 {
2411 self.0 ^= self.0 << 13;
2412 self.0 ^= self.0 >> 7;
2413 self.0 ^= self.0 << 17;
2414 self.0
2415 }
2416
2417 fn below(&mut self, bound: u64) -> u64 {
2418 self.next() % bound
2419 }
2420 }
2421
2422 #[test]
2423 fn an_ordinary_comparison_is_null_when_either_side_is() {
2424 assert_eq!(compared(Comparison::Equal, Value::Integer(1), Value::Null), Value::Null);
2425 assert_eq!(compared(Comparison::Less, Value::Null, Value::Integer(1)), Value::Null);
2426 }
2427
2428 #[test]
2429 fn a_total_comparison_is_never_null() {
2430 assert_eq!(
2431 compared(Comparison::NotDistinctFrom, Value::Null, Value::Null),
2432 Value::Boolean(true)
2433 );
2434 assert_eq!(
2435 compared(Comparison::NotDistinctFrom, Value::Integer(1), Value::Null),
2436 Value::Boolean(false)
2437 );
2438 assert_eq!(
2439 compared(Comparison::DistinctFrom, Value::Integer(1), Value::Null),
2440 Value::Boolean(true)
2441 );
2442 }
2443
2444 #[test]
2445 fn a_string_compares_by_bytes() {
2446 assert_eq!(
2447 compared(Comparison::Less, Value::Varchar("a".into()), Value::Varchar("b".into())),
2448 Value::Boolean(true)
2449 );
2450 assert_eq!(
2451 compared(Comparison::Less, Value::Varchar("Z".into()), Value::Varchar("a".into())),
2452 Value::Boolean(true)
2453 );
2454 }
2455
2456 #[test]
2459 fn two_nans_are_one_value_and_they_sort_above_the_numbers() {
2460 assert_eq!(
2461 compared(Comparison::Equal, Value::Double(f64::NAN), Value::Double(f64::NAN)),
2462 Value::Boolean(true)
2463 );
2464 assert_eq!(
2465 compared(Comparison::Greater, Value::Double(f64::NAN), Value::Double(1e300)),
2466 Value::Boolean(true)
2467 );
2468 }
2469
2470 #[test]
2471 fn zero_has_one_value_however_it_is_signed() {
2472 assert_eq!(
2473 compared(Comparison::Equal, Value::Double(0.0), Value::Double(-0.0)),
2474 Value::Boolean(true)
2475 );
2476 }
2477
2478 #[test]
2483 fn two_intervals_of_the_same_length_are_one_value() {
2484 let day = Value::Interval { months: 0, days: 1, micros: 0 };
2485 let hours = Value::Interval { months: 0, days: 0, micros: 86_400_000_000 };
2486 let month = Value::Interval { months: 1, days: 0, micros: 0 };
2487 let thirty = Value::Interval { months: 0, days: 30, micros: 0 };
2488 let long_day = Value::Interval { months: 0, days: 0, micros: 90_000_000_000 };
2489 assert_eq!(compared(Comparison::Equal, day.clone(), hours), Value::Boolean(true));
2490 assert_eq!(compared(Comparison::Equal, month, thirty), Value::Boolean(true));
2491 assert_eq!(compared(Comparison::Greater, long_day, day), Value::Boolean(true));
2492 }
2493
2494 #[test]
2495 fn a_number_compares_the_same_however_it_is_stored() {
2496 assert_eq!(
2497 compared(Comparison::Equal, Value::Integer(3), Value::BigInt(3)),
2498 Value::Boolean(true)
2499 );
2500 assert_eq!(
2501 compared(Comparison::Less, Value::Integer(3), Value::Double(3.5)),
2502 Value::Boolean(true)
2503 );
2504 }
2505
2506 #[test]
2507 fn nulls_go_where_the_query_asked_for_them() {
2508 assert_eq!(
2509 order_with_nulls(&Value::Null, &Value::Integer(1), true).expect("orders"),
2510 Ordering::Less
2511 );
2512 assert_eq!(
2513 order_with_nulls(&Value::Null, &Value::Integer(1), false).expect("orders"),
2514 Ordering::Greater
2515 );
2516 }
2517
2518 #[test]
2519 fn two_constant_vectors_cost_one_comparison() {
2520 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 512);
2521 let right = Vector::constant(LogicalType::Integer, Value::Integer(2), 512);
2522 let result = compare(Comparison::Less, &left, &right).expect("compares");
2523 assert_eq!(result.form(), Form::Constant);
2524 assert_eq!(result.value_at(500), Value::Boolean(true));
2525 }
2526
2527 #[test]
2528 fn a_comparison_of_two_vectors_is_one_answer_per_row() {
2529 let left = Vector::from_values(
2530 LogicalType::Integer,
2531 &[Value::Integer(1), Value::Integer(5), Value::Null],
2532 )
2533 .expect("three rows");
2534 let right = Vector::constant(LogicalType::Integer, Value::Integer(3), 3);
2535 let result = compare(Comparison::Greater, &left, &right).expect("compares");
2536 assert_eq!(result.value_at(0), Value::Boolean(false));
2537 assert_eq!(result.value_at(1), Value::Boolean(true));
2538 assert_eq!(result.value_at(2), Value::Null);
2539 }
2540
2541 #[test]
2542 fn two_vectors_of_different_lengths_are_caught() {
2543 let left = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
2544 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 5);
2545 let error = compare(Comparison::Equal, &left, &right).expect_err("ragged");
2546 assert!(error.message().contains("4 row vector"), "{error}");
2547 }
2548
2549 #[test]
2550 fn turning_a_comparison_around_is_what_the_other_side_would_have_said() {
2551 for op in EVERY {
2552 let left = Value::Integer(3);
2553 let right = Value::Integer(7);
2554 assert_eq!(
2555 compare_values(op, &left, &right).expect("compares"),
2556 compare_values(op.swapped(), &right, &left).expect("compares"),
2557 "{op:?}"
2558 );
2559 }
2560 }
2561
2562 #[test]
2565 fn every_specialized_path_agrees_with_the_row_at_a_time_path() {
2566 let mut rng = Rng(0x5eed_1234_9876_4321);
2567 let types: [LogicalType; 11] = [
2568 LogicalType::Boolean,
2569 LogicalType::TinyInt,
2570 LogicalType::SmallInt,
2571 LogicalType::Integer,
2572 LogicalType::BigInt,
2573 LogicalType::HugeInt,
2574 LogicalType::UInteger,
2575 LogicalType::Float,
2576 LogicalType::Double,
2577 LogicalType::Varchar,
2578 LogicalType::Interval,
2579 ];
2580 for ty in &types {
2581 for nulls in [0u64, 1, 3] {
2582 let len = 37;
2583 let make = |rng: &mut Rng| {
2584 let values: Vec<Value> = (0..len)
2585 .map(|_| {
2586 if nulls > 0 && rng.below(nulls + 1) == 0 {
2587 Value::Null
2588 } else {
2589 sample(ty, rng)
2590 }
2591 })
2592 .collect();
2593 Vector::from_values(ty.clone(), &values).expect("a flat vector")
2594 };
2595 let left = make(&mut rng);
2596 let right = make(&mut rng);
2597 let literal = sample(ty, &mut rng);
2598 let constant = Vector::constant(ty.clone(), literal, len);
2599 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
2600 let codes: Vec<u32> =
2601 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
2602 let dictionary =
2603 Vector::dictionary(codes, left.clone()).expect("codes are in range");
2604 let ends: Vec<u32> = (1..=left.len())
2607 .map(|run| ((run * len) / left.len()).max(run) as u32)
2608 .collect();
2609 let runs =
2610 Vector::runs(ends.clone(), left.clone()).expect("one value for each run");
2611 let other_codes: Vec<u32> =
2615 (0..len).map(|_| rng.below(right.len() as u64) as u32).collect();
2616 let other_dictionary =
2617 Vector::dictionary(other_codes, right.clone()).expect("codes are in range");
2618 let other_runs = Vector::runs(ends, right.clone()).expect("one value for each run");
2619
2620 for op in EVERY {
2621 agrees_and_selects(op, &left, &right);
2622 agrees_and_selects(op, &left, &constant);
2623 agrees_and_selects(op, &constant, &left);
2624 agrees_and_selects(op, &left, &null_constant);
2625 agrees_and_selects(op, &null_constant, &left);
2626 agrees_and_selects(op, &dictionary, &constant);
2627 agrees_and_selects(op, &constant, &dictionary);
2628 agrees_and_selects(op, &dictionary, &right);
2632 agrees_and_selects(op, &right, &dictionary);
2633 agrees_and_selects(op, &runs, &constant);
2637 agrees_and_selects(op, &constant, &runs);
2638 agrees_and_selects(op, &runs, &right);
2639 agrees_and_selects(op, &right, &runs);
2640 agrees_and_selects(op, &dictionary, &other_dictionary);
2646 agrees_and_selects(op, &runs, &other_runs);
2647 agrees_and_selects(op, &dictionary, &other_runs);
2648 agrees_and_selects(op, &runs, &other_dictionary);
2649 }
2650 }
2651 }
2652 }
2653
2654 fn refined(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) -> Selection {
2656 let mut out = Vec::new();
2657 for &row in kept.indices() {
2658 let index = row as usize;
2659 let answer = compare_values(op, &left.value_at(index), &right.value_at(index))
2660 .expect("the oracle is only asked about types that compare");
2661 if is_true(&answer) {
2662 out.push(row);
2663 }
2664 }
2665 Selection::from_indices(out)
2666 }
2667
2668 fn threads(op: Comparison, left: &Vector, right: &Vector, kept: &Selection) {
2669 let fast = refine(op, left, right, kept).expect("compares");
2670 assert_eq!(
2671 fast,
2672 refined(op, left, right, kept),
2673 "{op:?} on a {:?} against a {:?} over {} rows",
2674 left.form(),
2675 right.form(),
2676 kept.len()
2677 );
2678 }
2679
2680 #[test]
2684 fn a_threaded_comparison_keeps_what_the_row_at_a_time_path_keeps() {
2685 let mut rng = Rng(0x5eed_4321_1234_9876);
2686 let types = [LogicalType::Integer, LogicalType::Double, LogicalType::Varchar];
2687 for ty in &types {
2688 for nulls in [0u64, 1, 3] {
2689 let len = 37;
2690 let make = |rng: &mut Rng| {
2691 let values: Vec<Value> = (0..len)
2692 .map(|_| {
2693 if nulls > 0 && rng.below(nulls + 1) == 0 {
2694 Value::Null
2695 } else {
2696 sample(ty, rng)
2697 }
2698 })
2699 .collect();
2700 Vector::from_values(ty.clone(), &values).expect("a flat vector")
2701 };
2702 let left = make(&mut rng);
2703 let right = make(&mut rng);
2704 let constant = Vector::constant(ty.clone(), sample(ty, &mut rng), len);
2705 let null_constant = Vector::constant(ty.clone(), Value::Null, len);
2706 let codes: Vec<u32> =
2707 (0..len).map(|_| rng.below(left.len() as u64) as u32).collect();
2708 let dictionary =
2709 Vector::dictionary(codes, left.clone()).expect("codes are in range");
2710
2711 let selections = [
2715 Selection::identity(len),
2716 Selection::from_indices((0..len as u32).filter(|row| row % 3 == 0).collect()),
2717 Selection::from_indices(vec![2, 5, 6, 17, 36]),
2718 Selection::empty(),
2719 ];
2720 for op in EVERY {
2721 for kept in &selections {
2722 threads(op, &left, &right, kept);
2723 threads(op, &left, &constant, kept);
2724 threads(op, &constant, &left, kept);
2725 threads(op, &left, &null_constant, kept);
2726 threads(op, &null_constant, &left, kept);
2727 threads(op, &constant, &null_constant, kept);
2728 threads(op, &dictionary, &constant, kept);
2729 threads(op, &constant, &dictionary, kept);
2730 threads(op, &dictionary, &right, kept);
2731 threads(op, &right, &dictionary, kept);
2732 }
2733 }
2734 }
2735 }
2736 }
2737
2738 #[test]
2742 fn a_second_conjunct_reads_only_what_the_first_one_left() {
2743 let numbers: Vec<Value> = (0..64).map(|row| Value::Integer(row % 10)).collect();
2744 let column = Vector::from_values(LogicalType::Integer, &numbers).expect("a flat vector");
2745 let three = Vector::constant(LogicalType::Integer, Value::Integer(3), 64);
2746 let seven = Vector::constant(LogicalType::Integer, Value::Integer(7), 64);
2747
2748 let first = refine(Comparison::Greater, &column, &three, &Selection::identity(64))
2749 .expect("compares");
2750 let both = refine(Comparison::Less, &column, &seven, &first).expect("compares");
2751
2752 let expected: Vec<u32> = (0..64)
2753 .filter(|row| {
2754 let value = row % 10;
2755 value > 3 && value < 7
2756 })
2757 .collect();
2758 assert_eq!(both.indices(), expected.as_slice());
2759 assert!(both.len() < first.len(), "the second conjunct narrowed the selection");
2760 }
2761
2762 #[test]
2766 fn a_null_row_is_not_kept_by_an_ordinary_comparison_and_is_by_a_total_one() {
2767 let column = Vector::from_values(
2768 LogicalType::Integer,
2769 &[Value::Integer(1), Value::Null, Value::Integer(3), Value::Null],
2770 )
2771 .expect("four rows");
2772 let cut = Vector::constant(LogicalType::Integer, Value::Integer(2), 4);
2773 let all = Selection::identity(4);
2774 assert_eq!(
2775 refine(Comparison::Less, &column, &cut, &all).expect("compares").indices(),
2776 &[0]
2777 );
2778 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 4);
2780 assert_eq!(
2781 refine(Comparison::NotDistinctFrom, &column, &nulls, &all).expect("compares").indices(),
2782 &[1, 3]
2783 );
2784 }
2785
2786 #[test]
2787 fn a_selection_past_the_end_is_caught() {
2788 let column = Vector::constant(LogicalType::Integer, Value::Integer(1), 4);
2789 let past = Selection::from_indices(vec![0, 4]);
2790 let error = refine(Comparison::Equal, &column, &column, &past).expect_err("out of range");
2791 assert!(error.message().contains("4 row vector"), "{error}");
2792 }
2793
2794 fn sample(ty: &LogicalType, rng: &mut Rng) -> Value {
2796 match ty {
2797 LogicalType::Boolean => Value::Boolean(rng.below(2) == 1),
2798 LogicalType::TinyInt => Value::TinyInt(rng.below(7) as i8 - 3),
2799 LogicalType::SmallInt => Value::SmallInt(rng.below(11) as i16 - 5),
2800 LogicalType::Integer => Value::Integer(rng.below(9) as i32 - 4),
2801 LogicalType::BigInt => Value::BigInt(rng.below(9) as i64 - 4),
2802 LogicalType::HugeInt => Value::HugeInt(i128::from(rng.below(9)) - 4),
2803 LogicalType::UInteger => Value::UInteger(rng.below(9) as u32),
2804 LogicalType::Float => Value::Float(match rng.below(5) {
2807 0 => f32::NAN,
2808 1 => -0.0,
2809 other => other as f32 - 2.0,
2810 }),
2811 LogicalType::Double => Value::Double(match rng.below(5) {
2812 0 => f64::NAN,
2813 1 => -0.0,
2814 other => other as f64 - 2.0,
2815 }),
2816 LogicalType::Interval => match rng.below(6) {
2820 0 => Value::Interval { months: 0, days: 1, micros: 0 },
2821 1 => Value::Interval { months: 0, days: 0, micros: 86_400_000_000 },
2822 2 => Value::Interval { months: 1, days: -29, micros: 86_400_000_000 },
2823 3 => Value::Interval { months: 1, days: 0, micros: 0 },
2824 4 => Value::Interval { months: 0, days: 0, micros: 90_000_000_000 },
2825 _ => Value::Interval { months: -1, days: 0, micros: 0 },
2826 },
2827 LogicalType::Varchar => Value::Varchar(
2830 match rng.below(6) {
2831 0 => "",
2832 1 => "ab",
2833 2 => "abc",
2834 3 => "abcdefghijkl",
2835 4 => "abcdefghijklm",
2836 _ => "abcdefghijklmnopqrstuvwxyz",
2837 }
2838 .to_owned(),
2839 ),
2840 other => panic!("the generator has no values for {other}"),
2841 }
2842 }
2843
2844 #[test]
2848 fn prefix_order_is_byte_order_whenever_the_prefixes_differ() {
2849 let words =
2850 ["", "a", "ab", "abc", "abcd", "abcde", "b", "abcdefghijklmnop", "abcdefghijklmnoq"];
2851 let mut column = StringColumn::new();
2852 for word in words {
2853 column.push(word);
2854 }
2855 for (i, one) in words.iter().enumerate() {
2856 for (j, other) in words.iter().enumerate() {
2857 assert_eq!(
2858 string_order(&column, i, &column, j),
2859 one.as_bytes().cmp(other.as_bytes()),
2860 "{one:?} against {other:?}"
2861 );
2862 }
2863 }
2864 }
2865
2866 #[test]
2869 fn a_dictionary_against_a_constant_reads_its_nulls_from_the_values() {
2870 let values = Vector::from_values(
2871 LogicalType::Integer,
2872 &[Value::Integer(1), Value::Null, Value::Integer(9)],
2873 )
2874 .expect("three values");
2875 let dictionary =
2876 Vector::dictionary(vec![0, 1, 2, 1, 0], values).expect("codes are in range");
2877 let constant = Vector::constant(LogicalType::Integer, Value::Integer(5), 5);
2878 let result = compare(Comparison::Less, &dictionary, &constant).expect("compares");
2879 assert_eq!(result.value_at(0), Value::Boolean(true));
2880 assert_eq!(result.value_at(1), Value::Null);
2881 assert_eq!(result.value_at(2), Value::Boolean(false));
2882 assert_eq!(result.value_at(3), Value::Null);
2883 assert_eq!(result.value_at(4), Value::Boolean(true));
2884 }
2885
2886 #[test]
2895 fn an_ordering_on_text_against_a_literal_does_not_fall_back() {
2896 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
2897 let values = Vector::from_values(
2898 LogicalType::Varchar,
2899 &[Value::Varchar("apple".into()), Value::Null, Value::Varchar("pear".into())],
2900 )
2901 .expect("three values");
2902 let column = Vector::dictionary(vec![0, 1, 2, 0], values).expect("codes are in range");
2903 let cut = Vector::constant(LogicalType::Varchar, Value::Varchar("melon".into()), 4);
2904 let result = compare(Comparison::Less, &column, &cut).expect("compares");
2905 assert_eq!(result.value_at(0), Value::Boolean(true));
2906 assert_eq!(result.value_at(1), Value::Null);
2907 assert_eq!(result.value_at(2), Value::Boolean(false));
2908 assert_eq!(result.value_at(3), Value::Boolean(true));
2909 let other = compare(Comparison::Greater, &cut, &column).expect("compares");
2912 assert_eq!(other.value_at(0), Value::Boolean(true));
2913 assert_eq!(other.value_at(1), Value::Null);
2914 assert_eq!(other.value_at(2), Value::Boolean(false));
2915 let kept = refine(Comparison::GreaterOrEqual, &column, &cut, &Selection::identity(4))
2917 .expect("refines");
2918 assert_eq!(kept.indices(), [2]);
2919 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
2920 }
2921
2922 #[test]
2930 fn two_dictionary_columns_compared_with_each_other_do_not_fall_back() {
2931 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Dictionary);
2932 let dates = |values: &[Value]| {
2933 Vector::from_values(LogicalType::Date, values).expect("a flat date column")
2934 };
2935 let committed = Vector::dictionary(
2937 vec![0, 1, 0, 2],
2938 dates(&[Value::Date(10), Value::Date(20), Value::Date(30)]),
2939 )
2940 .expect("codes are in range");
2941 let received = Vector::dictionary(
2942 vec![0, 1, 2, 0],
2943 dates(&[Value::Date(15), Value::Null, Value::Date(5)]),
2944 )
2945 .expect("codes are in range");
2946 let result = compare(Comparison::Less, &committed, &received).expect("compares");
2947 assert_eq!(result.value_at(0), Value::Boolean(true), "10 < 15");
2948 assert_eq!(result.value_at(1), Value::Null, "20 against a null");
2949 assert_eq!(result.value_at(2), Value::Boolean(false), "10 against 5");
2950 assert_eq!(result.value_at(3), Value::Boolean(false), "30 against 15");
2951 let kept = refine(Comparison::Less, &committed, &received, &Selection::identity(4))
2953 .expect("refines");
2954 assert_eq!(kept.indices(), [0]);
2955 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Dictionary), before);
2956 }
2957
2958 #[test]
2961 fn a_form_pair_with_no_loop_is_still_right_and_says_so() {
2962 let before = fallback::count(Kernel::Compare, Form::Sequence, Form::Flat);
2964 let sequence = Vector::sequence(10, 1, 4);
2965 let flat = Vector::from_values(
2966 LogicalType::BigInt,
2967 &[Value::BigInt(9), Value::BigInt(11), Value::BigInt(12), Value::Null],
2968 )
2969 .expect("four rows");
2970 let result = compare(Comparison::Less, &sequence, &flat).expect("compares");
2971 assert_eq!(result.value_at(0), Value::Boolean(false));
2972 assert_eq!(result.value_at(1), Value::Boolean(false));
2973 assert_eq!(result.value_at(2), Value::Boolean(false));
2974 assert_eq!(result.value_at(3), Value::Null);
2975 assert!(fallback::count(Kernel::Compare, Form::Sequence, Form::Flat) > before);
2976 }
2977
2978 #[test]
2988 fn a_second_level_of_codes_does_not_turn_the_loops_off() {
2989 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant);
2990 let values = Vector::from_values(
2991 LogicalType::Integer,
2992 &[Value::Integer(1), Value::Integer(5), Value::Integer(9)],
2993 )
2994 .expect("three rows");
2995 let once = Vector::dictionary(vec![2, 1, 0], values).expect("codes are in range");
2996 let twice = Vector::dictionary(vec![1, 2], once).expect("codes are in range");
2997 let cut = Vector::constant(LogicalType::Integer, Value::Integer(4), 2);
2998 let result = compare(Comparison::Greater, &twice, &cut).expect("compares");
2999 assert_eq!(result.value_at(0), Value::Boolean(true));
3000 assert_eq!(result.value_at(1), Value::Boolean(false));
3001 assert_eq!(fallback::count(Kernel::Compare, Form::Dictionary, Form::Constant), before);
3002 }
3003
3004 #[test]
3008 fn a_side_that_is_entirely_null_answers_without_reading_the_other() {
3009 let nulls = Vector::constant(LogicalType::Integer, Value::Null, 6);
3010 let flat = Vector::from_values(
3011 LogicalType::Integer,
3012 &[
3013 Value::Integer(1),
3014 Value::Integer(2),
3015 Value::Integer(3),
3016 Value::Integer(4),
3017 Value::Integer(5),
3018 Value::Integer(6),
3019 ],
3020 )
3021 .expect("six rows");
3022 agrees(Comparison::Less, &nulls, &flat);
3023 agrees(Comparison::Equal, &flat, &nulls);
3024 assert_eq!(
3025 compare(Comparison::Less, &nulls, &flat).expect("compares").validity(),
3026 &Validity::AllInvalid
3027 );
3028 }
3029
3030 #[test]
3033 fn an_empty_comparison_is_an_empty_answer() {
3034 let left = Vector::from_values(LogicalType::Integer, &[]).expect("no rows");
3035 let right = Vector::constant(LogicalType::Integer, Value::Integer(1), 0);
3036 let result = compare(Comparison::Equal, &left, &right).expect("compares");
3037 assert_eq!(result.len(), 0);
3038 }
3039
3040 fn words() -> Vector {
3043 Vector::from_values(
3044 LogicalType::Varchar,
3045 &[
3046 Value::Varchar("http://a".into()),
3047 Value::Varchar("http://b".into()),
3048 Value::Null,
3049 Value::Varchar("ab".into()),
3050 Value::Varchar("http://a".into()),
3051 Value::Varchar("z".into()),
3052 ],
3053 )
3054 .expect("six rows")
3055 }
3056
3057 #[test]
3063 fn a_literal_built_early_answers_what_one_built_here_answers() {
3064 let column = words();
3065 let value = Value::Varchar("http://b".into());
3066 let constant = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
3067 let held = Held::of(&LogicalType::Varchar, &value).expect("a varchar has a column");
3068 let kept = Selection::from_indices(vec![0, 1, 3, 5]);
3069 for op in [
3070 Comparison::Equal,
3071 Comparison::NotEqual,
3072 Comparison::Less,
3073 Comparison::LessOrEqual,
3074 Comparison::Greater,
3075 Comparison::GreaterOrEqual,
3076 Comparison::DistinctFrom,
3077 Comparison::NotDistinctFrom,
3078 ] {
3079 let prepared = compare_prepared(op, &column, &constant, Some(&held)).expect("compares");
3080 assert_eq!(prepared, compare(op, &column, &constant).expect("compares"), "{op:?}");
3081 let flipped = compare_prepared(op, &constant, &column, Some(&held)).expect("compares");
3083 assert_eq!(flipped, compare(op, &constant, &column).expect("compares"), "{op:?}");
3084 let refined =
3085 refine_prepared(op, &column, &constant, &kept, Some(&held)).expect("refines");
3086 assert_eq!(refined, refine(op, &column, &constant, &kept).expect("refines"), "{op:?}");
3087 }
3088 }
3089
3090 #[test]
3097 fn a_literal_built_for_another_value_is_ignored() {
3098 let column = words();
3099 let constant = Vector::constant(LogicalType::Varchar, Value::Varchar("z".into()), 6);
3100 let wrong = Held::of(&LogicalType::Varchar, &Value::Varchar("ab".into()))
3101 .expect("a varchar has a column");
3102 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&wrong))
3103 .expect("compares");
3104 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
3105 let other = Held::of(&LogicalType::Integer, &Value::Integer(1)).expect("an integer column");
3108 let answer = compare_prepared(Comparison::Equal, &column, &constant, Some(&other))
3109 .expect("compares");
3110 assert_eq!(answer, compare(Comparison::Equal, &column, &constant).expect("compares"));
3111 }
3112
3113 #[test]
3117 fn a_range_keeps_the_rows_its_two_comparisons_keep() {
3118 let values: Vec<i32> = (0..1000).map(|row| 700 + (row * 37) % 600).collect();
3119 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
3120 .expect("integers are an i32 layout");
3121 let packed = flat.bit_packed().expect("packs");
3122 let some = Selection::from_predicate(1000, |row| row % 3 != 1);
3123 let ends = [i32::MIN, -5, 699, 700, 701, 900, 1299, 1300, 5000, i32::MAX];
3124 for column in [&flat, &packed] {
3125 for low in ends {
3126 for high in ends {
3127 for (lower, upper) in [
3128 (Comparison::GreaterOrEqual, Comparison::LessOrEqual),
3129 (Comparison::Greater, Comparison::Less),
3130 ] {
3131 let (low, high) = (Value::Integer(low), Value::Integer(high));
3132 let at = |value: &Value| {
3133 Vector::constant(LogicalType::Integer, value.clone(), 1000)
3134 };
3135 let (one, other) = (at(&low), at(&high));
3136 let bounds = (
3137 Bound { op: lower, value: &low, held: None },
3138 Bound { op: upper, value: &high, held: None },
3139 );
3140 let first = select_prepared(lower, column, &one, None).expect("compares");
3141 let both = refine(upper, column, &other, &first).expect("refines");
3142 let ranged = select_range(column, bounds.0, bounds.1, None)
3143 .expect("a column with no nulls has a range");
3144 assert_eq!(
3145 ranged.indices(),
3146 both.indices(),
3147 "{low} {lower:?}, {high} {upper:?}"
3148 );
3149 let first = refine(lower, column, &one, &some).expect("refines");
3150 let both = refine(upper, column, &other, &first).expect("refines");
3151 let ranged = select_range(column, bounds.0, bounds.1, Some(some.indices()))
3152 .expect("a column with no nulls has a range");
3153 assert_eq!(
3154 ranged.indices(),
3155 both.indices(),
3156 "{low} {lower:?}, {high} {upper:?} of some"
3157 );
3158 }
3159 }
3160 }
3161 }
3162 }
3163
3164 #[test]
3166 fn a_range_it_has_no_loop_for_is_none() {
3167 let low = Value::Integer(1);
3168 let high = Value::Integer(5);
3169 fn bound(op: Comparison, value: &Value) -> Bound<'_> {
3170 Bound { op, value, held: None }
3171 }
3172 let nulls = Vector::from_values(LogicalType::Integer, &[Value::Integer(2), Value::Null])
3173 .expect("integers");
3174 let range = |column: &Vector, low: &Value, high: &Value| {
3175 select_range(
3176 column,
3177 bound(Comparison::GreaterOrEqual, low),
3178 bound(Comparison::Less, high),
3179 None,
3180 )
3181 };
3182 assert!(range(&nulls, &low, &high).is_none());
3183 let plain =
3184 Vector::from_values(LogicalType::Integer, &[Value::Integer(2), Value::Integer(9)])
3185 .expect("integers");
3186 assert_eq!(range(&plain, &low, &high).expect("a range").indices(), &[0]);
3187 assert!(range(&plain, &Value::Null, &high).is_none());
3188 assert!(range(&words(), &low, &high).is_none());
3189 let wrong = select_range(
3190 &plain,
3191 bound(Comparison::Less, &low),
3192 bound(Comparison::Less, &high),
3193 None,
3194 );
3195 assert!(wrong.is_none(), "a low end has to be > or >=");
3196 }
3197
3198 #[test]
3201 fn a_packed_column_against_a_constant_answers_what_the_oracle_answers() {
3202 let values: Vec<i32> = (0..64).map(|row| 1000 + (row * 37) % 500).collect();
3203 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
3204 .expect("integers are an i32 layout");
3205 let packed = flat.bit_packed().expect("a five hundred wide range packs");
3206 assert_eq!(packed.form(), Form::BitPacked);
3207 for literal in [999, 1000, 1200, 1499, 1500, 2000] {
3208 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 64);
3209 for op in EVERY {
3210 agrees(op, &packed, &constant);
3211 agrees(op, &constant, &packed);
3212 }
3213 }
3214 }
3215
3216 #[test]
3220 fn a_packed_column_with_nulls_answers_what_the_oracle_answers() {
3221 let values: Vec<i32> = (0..32).map(|row| 40 + row * 3).collect();
3222 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
3223 .expect("integers are an i32 layout")
3224 .with_validity(Validity::from_iter(32, |row| row % 5 != 0));
3225 let packed = flat.bit_packed().expect("packs");
3226 let constant = Vector::constant(LogicalType::Integer, Value::Integer(80), 32);
3227 for op in EVERY {
3228 agrees(op, &packed, &constant);
3229 }
3230 }
3231
3232 #[test]
3235 fn a_literal_outside_the_packed_range_answers_the_whole_vector_at_once() {
3236 let before = fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant);
3237 let values: Vec<i32> = (0..16).map(|row| 500 + row).collect();
3238 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
3239 .expect("integers are an i32 layout");
3240 let packed = flat.bit_packed().expect("packs");
3241 let literals = [-1, 0, 499, 516, 100_000];
3242 for literal in literals {
3243 let constant = Vector::constant(LogicalType::Integer, Value::Integer(literal), 16);
3244 for op in EVERY {
3245 agrees(op, &packed, &constant);
3246 }
3247 }
3248 let total = EVERY.iter().filter(|op| op.is_total()).count();
3253 assert_eq!(
3254 fallback::count(Kernel::Compare, Form::BitPacked, Form::Constant) - before,
3255 (literals.len() * total) as u64,
3256 "only the two total comparisons fall through"
3257 );
3258 }
3259
3260 #[test]
3263 fn refining_a_selection_over_a_packed_column_keeps_the_same_rows() {
3264 let values: Vec<i32> = (0..64).map(|row| 200 + (row * 11) % 128).collect();
3265 let flat = Vector::flat(LogicalType::Integer, Data::Int32(values.clone().into()))
3266 .expect("integers are an i32 layout");
3267 let packed = flat.bit_packed().expect("packs");
3268 let kept = Selection::from_predicate(64, |row| row % 3 == 0);
3269 let constant = Vector::constant(LogicalType::Integer, Value::Integer(260), 64);
3270 let packed_rows = refine(Comparison::Greater, &packed, &constant, &kept).expect("refines");
3271 let flat_rows = refine(Comparison::Greater, &flat, &constant, &kept).expect("refines");
3272 assert_eq!(packed_rows.indices(), flat_rows.indices());
3273 assert!(!packed_rows.is_empty(), "the literal is inside the range");
3274 }
3275
3276 #[test]
3280 fn two_packed_columns_against_each_other_answer_what_the_oracle_answers() {
3281 let before = fallback::count(Kernel::Compare, Form::BitPacked, Form::BitPacked);
3282 let one: Vec<i32> = (0..64).map(|row| 9000 + (row * 37) % 500).collect();
3283 let other: Vec<i32> = (0..64).map(|row| 9200 + (row * 53) % 400).collect();
3284 let left = Vector::flat(LogicalType::Integer, Data::Int32(one.into()))
3285 .expect("integers are an i32 layout")
3286 .bit_packed()
3287 .expect("a five hundred wide range packs");
3288 let right = Vector::flat(LogicalType::Integer, Data::Int32(other.into()))
3289 .expect("integers are an i32 layout")
3290 .bit_packed()
3291 .expect("a four hundred wide range packs");
3292 assert_eq!(left.form(), Form::BitPacked);
3293 assert_eq!(right.form(), Form::BitPacked);
3294 assert_ne!(
3295 left.packed_parts().expect("packed").base(),
3296 right.packed_parts().expect("packed").base(),
3297 "the two bases are the two column minimums and this test wants them apart"
3298 );
3299 for op in EVERY {
3300 agrees(op, &left, &right);
3301 agrees(op, &right, &left);
3302 }
3303 let total = EVERY.iter().filter(|op| op.is_total()).count();
3307 assert_eq!(
3308 fallback::count(Kernel::Compare, Form::BitPacked, Form::BitPacked) - before,
3309 (total * 2) as u64,
3310 "only the two total comparisons fall through"
3311 );
3312 }
3313
3314 #[test]
3315 fn two_long_packed_columns_sliced_off_a_word_answer_what_the_oracle_answers() {
3316 let one: Vec<i32> = (0..1000).map(|row| 9000 + (row * 37) % 500).collect();
3319 let other: Vec<i32> = (0..1000).map(|row| 9200 + (row * 53) % 400).collect();
3320 let packed = |values: Vec<i32>| {
3321 Vector::flat(LogicalType::Integer, Data::Int32(values.into()))
3322 .expect("integers are an i32 layout")
3323 .bit_packed()
3324 .expect("a narrow range packs")
3325 };
3326 let (left, right) = (packed(one), packed(other));
3327 for (at, len) in [(0, 1000), (7, 900), (70, 129)] {
3328 let (left, right) = (
3329 left.slice(at, len).expect("inside the vector"),
3330 right.slice(at, len).expect("inside the vector"),
3331 );
3332 for op in EVERY {
3333 agrees(op, &left, &right);
3334 agrees(op, &right, &left);
3335 }
3336 }
3337 }
3338
3339 fn wanted(op: Comparison, left: &Vector, right: &Vector, kept: Option<&Selection>) -> Vec<u32> {
3341 let flags = oracle(op, left, right);
3342 let every = crate::select::selection(&flags, flags.len());
3343 match kept {
3344 None => every.indices().to_vec(),
3345 Some(kept) => {
3346 kept.indices().iter().copied().filter(|row| every.indices().contains(row)).collect()
3347 }
3348 }
3349 }
3350
3351 #[test]
3356 fn two_columns_compared_in_one_pass_keep_the_rows_the_oracle_keeps() {
3357 let one: Vec<i32> = (0..1000).map(|row| 9000 + (row * 37) % 500).collect();
3358 let other: Vec<i32> = (0..1000).map(|row| 9200 + (row * 53) % 400).collect();
3359 let flat = |values: Vec<i32>| {
3360 Vector::flat(LogicalType::Date, Data::Int32(values.into())).expect("dates are i32")
3361 };
3362 let (left, right) = (flat(one), flat(other));
3363 let (packed_left, packed_right) =
3364 (left.bit_packed().expect("packs"), right.bit_packed().expect("packs"));
3365 assert_eq!(packed_left.form(), Form::BitPacked);
3366 assert_eq!(packed_right.form(), Form::BitPacked);
3367 let dense = Selection::from_predicate(1000, |row| row % 3 != 0);
3368 let sparse = Selection::from_predicate(1000, |row| row % 97 == 5);
3369 for op in EVERY {
3370 for (a, b) in [(&left, &right), (&right, &left), (&packed_left, &packed_right)] {
3371 let picked = select_prepared(op, a, b, None).expect("selects");
3372 assert_eq!(picked.indices(), wanted(op, a, b, None), "{op:?} {:?}", a.form());
3373 for kept in [&dense, &sparse] {
3374 let refined = refine(op, a, b, kept).expect("refines");
3375 assert_eq!(refined.indices(), wanted(op, a, b, Some(kept)), "{op:?}");
3376 }
3377 }
3378 }
3379 let refined = refine(Comparison::Less, &packed_left, &packed_right, &sparse).expect("ok");
3380 assert!(!refined.is_empty(), "the sparse rows reach both answers");
3381 }
3382
3383 #[test]
3386 fn a_flat_column_refined_against_a_literal_keeps_the_rows_the_oracle_keeps() {
3387 let values: Vec<i64> = (0..700).map(|row| (row * 7919) % 1000).collect();
3388 let column = Vector::flat(LogicalType::BigInt, Data::Int64(values.into())).expect("i64");
3389 let literal = Vector::constant(LogicalType::BigInt, Value::BigInt(500), 700);
3390 let kept = Selection::from_predicate(700, |row| row % 4 == 1);
3391 for op in EVERY {
3392 let refined = refine(op, &column, &literal, &kept).expect("refines");
3393 assert_eq!(refined.indices(), wanted(op, &column, &literal, Some(&kept)), "{op:?}");
3394 }
3395 }
3396
3397 #[test]
3400 fn two_packed_columns_whose_ranges_do_not_overlap_answer_the_whole_vector_at_once() {
3401 let one: Vec<i32> = (0..32).map(|row| 100 + row).collect();
3402 let other: Vec<i32> = (0..32).map(|row| 500 + row * 2).collect();
3403 let low = Vector::flat(LogicalType::Integer, Data::Int32(one.into()))
3404 .expect("integers are an i32 layout")
3405 .bit_packed()
3406 .expect("packs");
3407 let high = Vector::flat(LogicalType::Integer, Data::Int32(other.into()))
3408 .expect("integers are an i32 layout")
3409 .bit_packed()
3410 .expect("packs");
3411 for op in EVERY {
3412 agrees(op, &low, &high);
3413 agrees(op, &high, &low);
3414 }
3415 }
3416
3417 #[test]
3421 fn two_packed_columns_with_nulls_answer_what_the_oracle_answers() {
3422 let one: Vec<i32> = (0..32).map(|row| 40 + row * 3).collect();
3423 let other: Vec<i32> = (0..32).map(|row| 60 + row * 2).collect();
3424 let left = Vector::flat(LogicalType::Integer, Data::Int32(one.into()))
3425 .expect("integers are an i32 layout")
3426 .with_validity(Validity::from_iter(32, |row| row % 5 != 0))
3427 .bit_packed()
3428 .expect("packs");
3429 let right = Vector::flat(LogicalType::Integer, Data::Int32(other.into()))
3430 .expect("integers are an i32 layout")
3431 .with_validity(Validity::from_iter(32, |row| row % 3 != 0))
3432 .bit_packed()
3433 .expect("packs");
3434 for op in EVERY {
3435 agrees(op, &left, &right);
3436 }
3437 }
3438
3439 #[test]
3444 fn a_dictionary_over_a_packed_run_answers_what_the_oracle_answers() {
3445 let before = fallback::count(Kernel::Compare, Form::Dictionary, Form::Dictionary);
3446 let distinct = |start: i32, step: i32, nulls: usize| {
3447 let values: Vec<i32> = (0..24).map(|row| start + row * step).collect();
3448 Vector::flat(LogicalType::Date, Data::Int32(values.into()))
3449 .expect("dates are an i32 layout")
3450 .with_validity(Validity::from_iter(24, |row| row % nulls != 0))
3451 .bit_packed()
3452 .expect("packs")
3453 };
3454 let codes =
3455 |seed: usize| -> Vec<u32> { (0..64).map(|row| ((row * seed) % 24) as u32).collect() };
3456 let one = Vector::dictionary(codes(7), distinct(9_000, 3, 5)).expect("codes are in range");
3457 let other =
3458 Vector::dictionary(codes(5), distinct(9_020, 2, 7)).expect("codes are in range");
3459 let straight = Vector::flat(
3460 LogicalType::Date,
3461 Data::Int32((0..64).map(|row| 9_010 + row).collect::<Vec<i32>>().into()),
3462 )
3463 .expect("dates are an i32 layout")
3464 .bit_packed()
3465 .expect("packs");
3466 assert_eq!(one.form(), Form::Dictionary);
3467 assert_eq!(straight.form(), Form::BitPacked);
3468 for op in EVERY {
3469 agrees(op, &one, &other);
3470 agrees(op, &one, &straight);
3471 agrees(op, &straight, &other);
3472 }
3473 let total = EVERY.iter().filter(|op| op.is_total()).count();
3475 assert_eq!(
3476 fallback::count(Kernel::Compare, Form::Dictionary, Form::Dictionary) - before,
3477 total as u64,
3478 "only the two total comparisons fall through"
3479 );
3480 }
3481
3482 #[test]
3491 fn a_packed_column_against_a_flat_one_answers_what_the_oracle_answers() {
3492 let before = fallback::count(Kernel::Compare, Form::BitPacked, Form::Flat);
3493 let dates = |start: i32, step: i32, nulls: usize| {
3494 Vector::flat(
3495 LogicalType::Date,
3496 Data::Int32((0..64).map(|row| start + row * step).collect::<Vec<i32>>().into()),
3497 )
3498 .expect("dates are an i32 layout")
3499 .with_validity(Validity::from_iter(64, |row| row % nulls != 0))
3500 };
3501 let codes =
3502 |seed: usize| -> Vec<u32> { (0..64).map(|row| ((row * seed) % 64) as u32).collect() };
3503 let packed = dates(9_000, 3, 5).bit_packed().expect("packs");
3504 let flat = dates(9_040, 2, 7);
3505 let over_packed = Vector::dictionary(codes(7), packed.clone()).expect("codes are in range");
3506 let over_flat = Vector::dictionary(codes(11), flat.clone()).expect("codes are in range");
3507 assert_eq!(packed.form(), Form::BitPacked);
3508 assert_eq!(flat.form(), Form::Flat);
3509 assert!(packed.packed_parts().expect("packed").base() < 9_040 + 63 * 2);
3512 for op in EVERY {
3513 agrees(op, &packed, &flat);
3514 agrees(op, &flat, &packed);
3515 agrees(op, &packed, &over_flat);
3516 agrees(op, &over_packed, &flat);
3517 agrees(op, &over_packed, &over_flat);
3518 }
3519 let total = EVERY.iter().filter(|op| op.is_total()).count();
3522 assert_eq!(
3523 fallback::count(Kernel::Compare, Form::BitPacked, Form::Flat) - before,
3524 total as u64,
3525 "only the two total comparisons fall through"
3526 );
3527 }
3528
3529 #[test]
3533 fn refining_a_selection_over_two_packed_columns_keeps_the_same_rows() {
3534 let one: Vec<i32> = (0..64).map(|row| 200 + (row * 11) % 128).collect();
3535 let other: Vec<i32> = (0..64).map(|row| 240 + (row * 17) % 96).collect();
3536 let left = Vector::flat(LogicalType::Integer, Data::Int32(one.clone().into()))
3537 .expect("integers are an i32 layout");
3538 let right = Vector::flat(LogicalType::Integer, Data::Int32(other.clone().into()))
3539 .expect("integers are an i32 layout");
3540 let kept = Selection::from_predicate(64, |row| row % 3 == 0);
3541 let packed_rows = refine(
3542 Comparison::Less,
3543 &left.bit_packed().expect("packs"),
3544 &right.bit_packed().expect("packs"),
3545 &kept,
3546 )
3547 .expect("refines");
3548 let flat_rows = refine(Comparison::Less, &left, &right, &kept).expect("refines");
3549 assert_eq!(packed_rows.indices(), flat_rows.indices());
3550 assert!(!packed_rows.is_empty(), "the two ranges overlap");
3551 }
3552
3553 fn urls(count: usize) -> Vector {
3556 let mut rng = Rng(0x5eed_1234);
3557 let values: Vec<Value> = (0..count)
3558 .map(|_| {
3559 let host = rng.below(6);
3560 let path = rng.below(40);
3561 Value::Varchar(format!("http://example{host}.test/a/rather/long/path/{path}"))
3562 })
3563 .collect();
3564 Vector::from_values(LogicalType::Varchar, &values).expect("strings")
3565 }
3566
3567 #[test]
3568 fn a_string_view_column_against_a_literal_answers_what_the_oracle_answers() {
3569 let before = fallback::count(Kernel::Compare, Form::StringView, Form::Constant);
3570 let shared = urls(64).shared_text().expect("shares");
3571 assert_eq!(shared.form(), Form::StringView);
3572 let literals = ["http://example3.test/a/rather/long/path/7", "a", "zzz", ""];
3573 for literal in literals {
3574 let value = Value::Varchar(literal.to_owned());
3575 let constant = Vector::constant(LogicalType::Varchar, value, 64);
3576 for op in EVERY {
3577 agrees(op, &shared, &constant);
3578 agrees(op, &constant, &shared);
3579 }
3580 }
3581 assert_eq!(
3582 fallback::count(Kernel::Compare, Form::StringView, Form::Constant),
3583 before,
3584 "the form has a loop of its own for every comparison"
3585 );
3586 }
3587
3588 #[test]
3589 fn a_string_view_column_against_another_one_answers_what_the_oracle_answers() {
3590 let shared = urls(48).shared_text().expect("shares");
3591 let other = urls(48).shared_text().expect("shares");
3592 let flat = urls(48);
3593 for op in EVERY {
3594 agrees(op, &shared, &other);
3595 agrees(op, &shared, &flat);
3596 agrees(op, &flat, &shared);
3597 }
3598 }
3599
3600 #[test]
3601 fn the_nulls_of_a_string_view_column_are_the_nulls_the_oracle_sees() {
3602 let shared = urls(32)
3603 .with_validity(Validity::from_iter(32, |row| row % 4 != 1))
3604 .shared_text()
3605 .expect("shares");
3606 let constant =
3607 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 32);
3608 for op in EVERY {
3609 agrees(op, &shared, &constant);
3610 }
3611 }
3612
3613 #[test]
3614 fn a_compressed_column_against_a_literal_answers_what_the_oracle_answers() {
3615 let before = fallback::count(Kernel::Compare, Form::Fsst, Form::Constant);
3616 let flat = urls(64);
3617 let coded = flat.clone().compressed().expect("compresses");
3618 assert_eq!(coded.form(), Form::Fsst);
3619 let present = match coded.value_at(9) {
3620 Value::Varchar(text) => text,
3621 other => panic!("a string column reads back strings, not {other:?}"),
3622 };
3623 for literal in [present.as_str(), "http://example3.test/nothing/like/it", ""] {
3624 let value = Value::Varchar(literal.to_owned());
3625 let constant = Vector::constant(LogicalType::Varchar, value, 64);
3626 for op in EVERY {
3627 agrees(op, &coded, &constant);
3628 agrees(op, &constant, &coded);
3629 }
3630 }
3631 let ordered = EVERY.len() - 2;
3635 assert_eq!(
3636 fallback::count(Kernel::Compare, Form::Fsst, Form::Constant) - before,
3637 (3 * ordered) as u64,
3638 "only the comparisons that need an order fall through"
3639 );
3640 }
3641
3642 #[test]
3645 fn every_row_of_a_compressed_column_matches_itself_and_nothing_else() {
3646 let flat = urls(48);
3647 let coded = flat.clone().compressed().expect("compresses");
3648 for row in 0..48 {
3649 let constant = Vector::constant(LogicalType::Varchar, flat.value_at(row), 48);
3650 let equal = compare(Comparison::Equal, &coded, &constant).expect("compares");
3651 for other in 0..48 {
3652 let want = flat.value_at(other) == flat.value_at(row);
3653 assert_eq!(
3654 equal.value_at(other),
3655 Value::Boolean(want),
3656 "row {row} against {other}"
3657 );
3658 }
3659 }
3660 }
3661
3662 #[test]
3663 fn the_nulls_of_a_compressed_column_are_the_nulls_the_oracle_sees() {
3664 let coded = urls(32)
3665 .with_validity(Validity::from_iter(32, |row| row % 3 != 0))
3666 .compressed()
3667 .expect("compresses");
3668 let value = coded.value_at(1);
3669 let constant = Vector::constant(LogicalType::Varchar, value, 32);
3670 for op in EVERY {
3671 agrees(op, &coded, &constant);
3672 }
3673 }
3674
3675 #[test]
3679 fn a_filter_over_either_string_form_keeps_the_same_rows() {
3680 let flat = urls(96);
3681 let shared = flat.clone().shared_text().expect("shares");
3682 let constant =
3683 Vector::constant(LogicalType::Varchar, Value::Varchar("http://example3".into()), 96);
3684 let kept = Selection::from_predicate(96, |row| row % 5 != 0);
3685 for op in EVERY {
3686 let over_flat = refine(op, &flat, &constant, &kept).expect("refines");
3687 let over_shared = refine(op, &shared, &constant, &kept).expect("refines");
3688 assert_eq!(over_shared.indices(), over_flat.indices(), "{op:?}");
3689 }
3690 }
3691
3692 #[test]
3696 fn a_comparison_peeled_over_a_shared_dictionary_answers_what_the_oracle_answers() {
3697 let words = ["", "one", "two", "", "three"];
3698 let values: Vec<Value> = words.iter().map(|text| Value::Varchar((*text).into())).collect();
3699 let values =
3700 Arc::new(Vector::from_values(LogicalType::Varchar, &values).expect("a vector of text"));
3701 let codes = vec![0, 1, 3, 2, 0, 4, 1, 0];
3702 let column = Vector::stable_dictionary(codes.clone(), values).expect("codes are in range");
3703 same_as_the_oracle(&column);
3704 }
3705
3706 #[derive(Debug)]
3709 struct Filed {
3710 values: Vec<Vec<u8>>,
3711 order: Vec<u32>,
3712 ranked: std::sync::OnceLock<Option<Vec<u32>>>,
3714 }
3715
3716 impl rudb_vector::TextSource for Filed {
3717 fn len(&self) -> usize {
3718 self.values.len()
3719 }
3720
3721 fn bytes_at(&self, index: usize) -> Result<Option<&[u8]>> {
3722 Ok(self.values.get(index).map(Vec::as_slice))
3723 }
3724
3725 fn footprint(&self) -> usize {
3726 self.values.iter().map(Vec::len).sum()
3727 }
3728
3729 fn ranks(&self) -> Option<usize> {
3730 Some(self.order.len())
3731 }
3732
3733 fn compare_rank(&self, rank: usize, wanted: &[u8]) -> Result<Ordering> {
3734 Ok(self.values[self.order[rank] as usize].as_slice().cmp(wanted))
3737 }
3738
3739 fn code_at_rank(&self, rank: usize) -> Result<u32> {
3740 Ok(self.order[rank])
3741 }
3742
3743 fn code_ranks(&self) -> Option<&[u32]> {
3744 self.ranked
3745 .get_or_init(|| {
3746 let mut ranks = vec![0; self.order.len()];
3747 for (rank, &code) in self.order.iter().enumerate() {
3748 ranks[code as usize] = rank as u32;
3749 }
3750 Some(ranks)
3751 })
3752 .as_deref()
3753 }
3754 }
3755
3756 #[test]
3759 fn a_comparison_against_a_sorted_dictionary_answers_what_the_oracle_answers() {
3760 let (column, _) = filed(&["", "one", "two", "four", "three"], vec![0, 1, 3, 2, 0, 4, 1, 0]);
3763 same_as_the_oracle(&column);
3764 }
3765
3766 fn filed(words: &[&str], codes: Vec<u32>) -> (Vector, Arc<Vector>) {
3769 let values: Vec<Vec<u8>> = words.iter().map(|text| text.as_bytes().to_vec()).collect();
3770 let mut order = (0..values.len() as u32).collect::<Vec<_>>();
3771 order.sort_by(|&left, &right| values[left as usize].cmp(&values[right as usize]));
3772 let dictionary = Arc::new(
3773 Vector::external_text(
3774 LogicalType::Varchar,
3775 Arc::new(Filed { values, order, ranked: std::sync::OnceLock::new() }),
3776 )
3777 .expect("a filed vector"),
3778 );
3779 let column =
3780 Vector::stable_dictionary(codes, Arc::clone(&dictionary)).expect("codes are in range");
3781 (column, dictionary)
3782 }
3783
3784 #[test]
3787 fn a_comparison_against_a_known_rank_keeps_what_a_search_for_it_keeps() {
3788 let (column, dictionary) =
3789 filed(&["", "one", "two", "four", "three"], vec![0, 1, 3, 2, 0, 4, 1, 0]);
3790 let rows = column.len();
3791 for row in 0..rows {
3792 let (held, rank) = rank_at(&column, row).expect("a row of a ranked dictionary");
3793 assert!(Arc::ptr_eq(&held, &dictionary), "the dictionary it came from");
3794 let value = column.try_value_at(row).expect("a value");
3795 for op in [
3796 Comparison::Less,
3797 Comparison::LessOrEqual,
3798 Comparison::Greater,
3799 Comparison::GreaterOrEqual,
3800 ] {
3801 let against = Vector::constant(LogicalType::Varchar, value.clone(), rows);
3802 let flags = compare(op, &column, &against).expect("the search path answers");
3803 let wanted = crate::select::selection(&flags, rows);
3804 let got = select_against_rank(op, &column, &dictionary, rank, rows)
3805 .expect("the rank path answers");
3806 assert_eq!(got.indices(), wanted.indices(), "row {row} under {op:?}");
3807 }
3808 }
3809 }
3810
3811 #[test]
3814 fn a_rank_offered_against_another_dictionary_is_declined() {
3815 let (column, dictionary) = filed(&["one", "two"], vec![0, 1]);
3816 let (other, _) = filed(&["one", "two"], vec![1, 0]);
3817 assert!(select_against_rank(Comparison::Less, &column, &dictionary, 1, 2).is_some());
3818 assert!(select_against_rank(Comparison::Less, &other, &dictionary, 1, 2).is_none());
3819 let flat = Vector::constant(LogicalType::Varchar, Value::Varchar("one".into()), 2);
3820 assert!(select_against_rank(Comparison::Less, &flat, &dictionary, 1, 2).is_none());
3821 assert!(rank_at(&flat, 0).is_none(), "a column with no dictionary has no ranks");
3822 assert!(rank_within(&other, 0, &dictionary).is_none(), "another dictionary says nothing");
3823 assert!(rank_within(&flat, 0, &dictionary).is_none(), "no dictionary says nothing");
3824 }
3825
3826 #[test]
3829 fn two_ranks_in_one_dictionary_order_their_values() {
3830 let (column, dictionary) =
3831 filed(&["", "one", "two", "four", "three"], vec![0, 1, 3, 2, 0, 4, 1, 0]);
3832 let rows = column.len();
3833 for left in 0..rows {
3834 for right in 0..rows {
3835 let here = rank_within(&column, left, &dictionary).expect("a ranked row");
3836 let there = rank_within(&column, right, &dictionary).expect("a ranked row");
3837 let values = (
3838 column.try_value_at(left).expect("a value"),
3839 column.try_value_at(right).expect("a value"),
3840 );
3841 let wanted = order(&values.0, &values.1).expect("two strings compare");
3842 assert_eq!(here.cmp(&there), wanted, "rows {left} and {right}");
3843 let (held, rank) = rank_at(&column, left).expect("a ranked row");
3844 assert!(Arc::ptr_eq(&held, &dictionary), "the dictionary it came from");
3845 assert_eq!(rank, here, "the same rank whichever way it is asked for");
3846 }
3847 }
3848 }
3849
3850 fn same_as_the_oracle(column: &Vector) {
3854 for literal in ["", "one", "missing", "zzz"] {
3855 for op in [
3856 Comparison::Equal,
3857 Comparison::NotEqual,
3858 Comparison::Less,
3859 Comparison::LessOrEqual,
3860 Comparison::Greater,
3861 Comparison::GreaterOrEqual,
3862 ] {
3863 let value = Value::Varchar(literal.to_owned());
3864 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
3865 let right = Vector::constant(LogicalType::Varchar, value.clone(), column.len());
3866 let wanted = oracle(op, column, &right);
3867 let got = compare_prepared(op, column, &right, Some(&held))
3868 .expect("the peeled path answers");
3869 assert_eq!(got, wanted, "{literal:?} under {op:?}");
3870 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
3871 let picked = select_prepared(op, column, &right, Some(&held))
3872 .expect("the peeled path selects");
3873 assert_eq!(
3874 picked.indices(),
3875 crate::select::selection(&wanted, column.len()).indices(),
3876 "{literal:?} under {op:?}, selected"
3877 );
3878 let held = Held::of(&LogicalType::Varchar, &value).expect("text has a column");
3880 let kept = Selection::from_predicate(column.len(), |row| row % 3 != 1);
3881 let refined = refine_prepared(op, column, &right, &kept, Some(&held))
3882 .expect("the peeled path narrows");
3883 let wanted: Vec<u32> = kept
3884 .indices()
3885 .iter()
3886 .copied()
3887 .filter(|&row| is_true(&wanted.value_at(row as usize)))
3888 .collect();
3889 assert_eq!(refined.indices(), wanted, "{literal:?} under {op:?}, narrowed");
3890 }
3891 }
3892 }
3893}