From 7193235c0697bae6e70b018d5666f9dcb88aeb13 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Fri, 13 Feb 2026 16:58:32 +0000 Subject: [PATCH 1/8] break[array]: move like compute to lazy compute Signed-off-by: Joe Isaacs --- vortex-array/src/arrays/dict/compute/like.rs | 49 ---- vortex-array/src/arrays/dict/compute/mod.rs | 1 - vortex-array/src/compute/like.rs | 231 ------------------ vortex-array/src/compute/mod.rs | 3 - vortex-array/src/expr/expression.rs | 2 +- vortex-array/src/expr/exprs/like/kernel.rs | 108 ++++++++ .../src/expr/exprs/{like.rs => like/mod.rs} | 66 ++++- vortex-datafusion/src/convert/exprs.rs | 2 +- vortex-duckdb/src/convert/expr.rs | 2 +- vortex/public-api.lock | 21 ++ 10 files changed, 195 insertions(+), 290 deletions(-) delete mode 100644 vortex-array/src/arrays/dict/compute/like.rs delete mode 100644 vortex-array/src/compute/like.rs create mode 100644 vortex-array/src/expr/exprs/like/kernel.rs rename vortex-array/src/expr/exprs/{like.rs => like/mod.rs} (84%) diff --git a/vortex-array/src/arrays/dict/compute/like.rs b/vortex-array/src/arrays/dict/compute/like.rs deleted file mode 100644 index 8e6b329d624..00000000000 --- a/vortex-array/src/arrays/dict/compute/like.rs +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright the Vortex contributors - -use vortex_error::VortexResult; - -use super::DictArray; -use super::DictVTable; -use crate::Array; -use crate::ArrayRef; -use crate::IntoArray; -use crate::arrays::ConstantArray; -use crate::compute::LikeKernel; -use crate::compute::LikeKernelAdapter; -use crate::compute::LikeOptions; -use crate::compute::like; -use crate::register_kernel; - -impl LikeKernel for DictVTable { - fn like( - &self, - array: &DictArray, - pattern: &dyn Array, - options: LikeOptions, - ) -> VortexResult> { - // if we have more values than codes, it is faster to canonicalise first. - if array.values().len() > array.codes().len() { - return Ok(None); - } - if let Some(pattern) = pattern.as_constant() { - let pattern = ConstantArray::new(pattern, array.values().len()).into_array(); - let values = like(array.values(), &pattern, options)?; - - // SAFETY: LIKE preserves the len of the values, so codes are still pointing at - // valid positions. - // Preserve all_values_referenced since codes are unchanged - unsafe { - Ok(Some( - DictArray::new_unchecked(array.codes().clone(), values) - .set_all_values_referenced(array.has_all_values_referenced()) - .into_array(), - )) - } - } else { - Ok(None) - } - } -} - -register_kernel!(LikeKernelAdapter(DictVTable).lift()); diff --git a/vortex-array/src/arrays/dict/compute/mod.rs b/vortex-array/src/arrays/dict/compute/mod.rs index 056b151ec06..9e90f520a82 100644 --- a/vortex-array/src/arrays/dict/compute/mod.rs +++ b/vortex-array/src/arrays/dict/compute/mod.rs @@ -6,7 +6,6 @@ mod compare; mod fill_null; mod is_constant; mod is_sorted; -mod like; mod min_max; pub(crate) mod rules; mod slice; diff --git a/vortex-array/src/compute/like.rs b/vortex-array/src/compute/like.rs deleted file mode 100644 index b85aa8c4ebe..00000000000 --- a/vortex-array/src/compute/like.rs +++ /dev/null @@ -1,231 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright the Vortex contributors - -use std::any::Any; -use std::fmt::Display; -use std::fmt::Formatter; -use std::sync::LazyLock; - -use arcref::ArcRef; -use vortex_dtype::DType; -use vortex_error::VortexError; -use vortex_error::VortexExpect; -use vortex_error::VortexResult; -use vortex_error::vortex_bail; -use vortex_error::vortex_err; - -use crate::Array; -use crate::ArrayRef; -use crate::arrow::Datum; -use crate::arrow::from_arrow_array_with_len; -use crate::compute::ComputeFn; -use crate::compute::ComputeFnVTable; -use crate::compute::InvocationArgs; -use crate::compute::Kernel; -use crate::compute::Options; -use crate::compute::Output; -use crate::vtable::VTable; - -static LIKE_FN: LazyLock = LazyLock::new(|| { - let compute = ComputeFn::new("like".into(), ArcRef::new_ref(&Like)); - for kernel in inventory::iter:: { - compute.register_kernel(kernel.0.clone()); - } - compute -}); - -pub(crate) fn warm_up_vtable() -> usize { - LIKE_FN.kernels().len() -} - -/// Perform SQL left LIKE right -/// -/// There are two wildcards supported with the LIKE operator: -/// - %: matches zero or more characters -/// - _: matches exactly one character -pub fn like( - array: &dyn Array, - pattern: &dyn Array, - options: LikeOptions, -) -> VortexResult { - LIKE_FN - .invoke(&InvocationArgs { - inputs: &[array.into(), pattern.into()], - options: &options, - })? - .unwrap_array() -} - -pub struct LikeKernelRef(ArcRef); -inventory::collect!(LikeKernelRef); - -pub trait LikeKernel: VTable { - fn like( - &self, - array: &Self::Array, - pattern: &dyn Array, - options: LikeOptions, - ) -> VortexResult>; -} - -#[derive(Debug)] -pub struct LikeKernelAdapter(pub V); - -impl LikeKernelAdapter { - pub const fn lift(&'static self) -> LikeKernelRef { - LikeKernelRef(ArcRef::new_ref(self)) - } -} - -impl Kernel for LikeKernelAdapter { - fn invoke(&self, args: &InvocationArgs) -> VortexResult> { - let inputs = LikeArgs::try_from(args)?; - let Some(array) = inputs.array.as_opt::() else { - return Ok(None); - }; - Ok(V::like(&self.0, array, inputs.pattern, inputs.options)?.map(|array| array.into())) - } -} - -struct Like; - -impl ComputeFnVTable for Like { - fn invoke( - &self, - args: &InvocationArgs, - kernels: &[ArcRef], - ) -> VortexResult { - let LikeArgs { - array, - pattern, - options, - } = LikeArgs::try_from(args)?; - - for kernel in kernels { - if let Some(output) = kernel.invoke(args)? { - return Ok(output); - } - } - - // Otherwise, we fall back to the Arrow implementation - Ok(arrow_like(array, pattern, options)?.into()) - } - - fn return_dtype(&self, args: &InvocationArgs) -> VortexResult { - let LikeArgs { array, pattern, .. } = LikeArgs::try_from(args)?; - if !matches!(array.dtype(), DType::Utf8(..)) { - vortex_bail!("Expected utf8 array, got {}", array.dtype()); - } - if !matches!(pattern.dtype(), DType::Utf8(..)) { - vortex_bail!("Expected utf8 pattern, got {}", array.dtype()); - } - let nullability = array.dtype().is_nullable() || pattern.dtype().is_nullable(); - Ok(DType::Bool(nullability.into())) - } - - fn return_len(&self, args: &InvocationArgs) -> VortexResult { - let LikeArgs { array, pattern, .. } = LikeArgs::try_from(args)?; - if array.len() != pattern.len() { - vortex_bail!( - "Length mismatch lhs len {} ({}) != rhs len {} ({})", - array.len(), - array.encoding_id(), - pattern.len(), - pattern.encoding_id() - ); - } - Ok(array.len()) - } - - fn is_elementwise(&self) -> bool { - true - } -} - -/// Options for SQL LIKE function -#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct LikeOptions { - pub negated: bool, - pub case_insensitive: bool, -} - -impl Display for LikeOptions { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - if self.negated { - write!(f, "NOT ")?; - } - if self.case_insensitive { - write!(f, "ILIKE") - } else { - write!(f, "LIKE") - } - } -} - -impl Options for LikeOptions { - fn as_any(&self) -> &dyn Any { - self - } -} - -struct LikeArgs<'a> { - array: &'a dyn Array, - pattern: &'a dyn Array, - options: LikeOptions, -} - -impl<'a> TryFrom<&InvocationArgs<'a>> for LikeArgs<'a> { - type Error = VortexError; - - fn try_from(value: &InvocationArgs<'a>) -> Result { - if value.inputs.len() != 2 { - vortex_bail!("Expected 2 inputs, found {}", value.inputs.len()); - } - let array = value.inputs[0] - .array() - .ok_or_else(|| vortex_err!("Expected first input to be an array"))?; - let pattern = value.inputs[1] - .array() - .ok_or_else(|| vortex_err!("Expected second input to be an array"))?; - let options = *value - .options - .as_any() - .downcast_ref::() - .vortex_expect("Expected options to be LikeOptions"); - - Ok(LikeArgs { - array, - pattern, - options, - }) - } -} - -/// Implementation of `LikeFn` using the Arrow crate. -pub(crate) fn arrow_like( - array: &dyn Array, - pattern: &dyn Array, - options: LikeOptions, -) -> VortexResult { - let nullable = array.dtype().is_nullable() | pattern.dtype().is_nullable(); - let len = array.len(); - assert_eq!( - array.len(), - pattern.len(), - "Arrow Like: length mismatch for {}", - array.encoding_id() - ); - - // convert the pattern to the preferred array datatype - let lhs = Datum::try_new(array)?; - let rhs = Datum::try_new_with_target_datatype(pattern, lhs.data_type())?; - - let result = match (options.negated, options.case_insensitive) { - (false, false) => arrow_string::like::like(&lhs, &rhs)?, - (true, false) => arrow_string::like::nlike(&lhs, &rhs)?, - (false, true) => arrow_string::like::ilike(&lhs, &rhs)?, - (true, true) => arrow_string::like::nilike(&lhs, &rhs)?, - }; - - from_arrow_array_with_len(&result, len, nullable) -} diff --git a/vortex-array/src/compute/mod.rs b/vortex-array/src/compute/mod.rs index 8d603de9a24..2aed159bbc1 100644 --- a/vortex-array/src/compute/mod.rs +++ b/vortex-array/src/compute/mod.rs @@ -27,7 +27,6 @@ pub use invert::invert; pub use is_constant::*; pub use is_sorted::*; use itertools::Itertools; -pub use like::*; pub use list_contains::*; pub use mask::*; pub use min_max::*; @@ -73,7 +72,6 @@ mod filter; mod invert; mod is_constant; mod is_sorted; -mod like; mod list_contains; mod mask; mod min_max; @@ -99,7 +97,6 @@ pub fn warm_up_vtables() { compare::warm_up_vtable(); is_constant::warm_up_vtable(); is_sorted::warm_up_vtable(); - like::warm_up_vtable(); list_contains::warm_up_vtable(); mask::warm_up_vtable(); min_max::warm_up_vtable(); diff --git a/vortex-array/src/expr/expression.rs b/vortex-array/src/expr/expression.rs index ffdc361dde8..a08c67dcd2c 100644 --- a/vortex-array/src/expr/expression.rs +++ b/vortex-array/src/expr/expression.rs @@ -174,7 +174,7 @@ impl Expression { /// # Example /// /// ```rust - /// # use vortex_array::compute::LikeOptions; + /// # use vortex_array::expr::LikeOptions; /// # use vortex_array::expr::VTableExt; /// # use vortex_dtype::{DType, Nullability, PType}; /// # use vortex_array::expr::{and, cast, eq, get_item, gt, lit, not, root, select, Like}; diff --git a/vortex-array/src/expr/exprs/like/kernel.rs b/vortex-array/src/expr/exprs/like/kernel.rs new file mode 100644 index 00000000000..117a3dda912 --- /dev/null +++ b/vortex-array/src/expr/exprs/like/kernel.rs @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use vortex_error::VortexExpect; +use vortex_error::VortexResult; + +use crate::Array; +use crate::ArrayRef; +use crate::ExecutionCtx; +use crate::arrays::ExactScalarFn; +use crate::arrays::ScalarFnArrayView; +use crate::arrays::ScalarFnVTable; +use crate::expr::Like as LikeExpr; +use crate::expr::exprs::like::LikeOptions; +use crate::kernel::ExecuteParentKernel; +use crate::optimizer::rules::ArrayParentReduceRule; +use crate::vtable::VTable; + +/// Like pattern matching on an array without reading buffers. +/// +/// This trait is for like implementations that can operate purely on array metadata +/// and structure without needing to read or execute on the underlying buffers. +/// Implementations should return `None` if the operation requires buffer access. +/// +/// Dispatch is on child 0 (the input). The `pattern` and `options` are extracted from +/// the parent `ScalarFnArray`. +pub trait LikeReduce: VTable { + fn like( + array: &Self::Array, + pattern: &dyn Array, + options: LikeOptions, + ) -> VortexResult>; +} + +/// Like pattern matching on an array, potentially reading buffers. +/// +/// Unlike [`LikeReduce`], this trait is for like implementations that may need +/// to read and execute on the underlying buffers to produce the result. +/// +/// Dispatch is on child 0 (the input). The `pattern` and `options` are extracted from +/// the parent `ScalarFnArray`. +pub trait LikeKernel: VTable { + fn like( + array: &Self::Array, + pattern: &dyn Array, + options: LikeOptions, + ctx: &mut ExecutionCtx, + ) -> VortexResult>; +} + +/// Adaptor that wraps a [`LikeReduce`] impl as an [`ArrayParentReduceRule`]. +#[derive(Default, Debug)] +pub struct LikeReduceAdaptor(pub V); + +impl ArrayParentReduceRule for LikeReduceAdaptor +where + V: LikeReduce, +{ + type Parent = ExactScalarFn; + + fn reduce_parent( + &self, + array: &V::Array, + parent: ScalarFnArrayView<'_, LikeExpr>, + child_idx: usize, + ) -> VortexResult> { + if child_idx != 0 { + return Ok(None); + } + let scalar_fn_array = parent + .as_opt::() + .vortex_expect("ExactScalarFn matcher confirmed ScalarFnArray"); + let children = scalar_fn_array.children(); + let pattern = &*children[1]; + let options = *parent.options; + ::like(array, pattern, options) + } +} + +/// Adaptor that wraps a [`LikeKernel`] impl as an [`ExecuteParentKernel`]. +#[derive(Default, Debug)] +pub struct LikeExecuteAdaptor(pub V); + +impl ExecuteParentKernel for LikeExecuteAdaptor +where + V: LikeKernel, +{ + type Parent = ExactScalarFn; + + fn execute_parent( + &self, + array: &V::Array, + parent: ScalarFnArrayView<'_, LikeExpr>, + child_idx: usize, + ctx: &mut ExecutionCtx, + ) -> VortexResult> { + if child_idx != 0 { + return Ok(None); + } + let scalar_fn_array = parent + .as_opt::() + .vortex_expect("ExactScalarFn matcher confirmed ScalarFnArray"); + let children = scalar_fn_array.children(); + let pattern = &*children[1]; + let options = *parent.options; + ::like(array, pattern, options, ctx) + } +} diff --git a/vortex-array/src/expr/exprs/like.rs b/vortex-array/src/expr/exprs/like/mod.rs similarity index 84% rename from vortex-array/src/expr/exprs/like.rs rename to vortex-array/src/expr/exprs/like/mod.rs index e4cc85a3314..5454fa80dba 100644 --- a/vortex-array/src/expr/exprs/like.rs +++ b/vortex-array/src/expr/exprs/like/mod.rs @@ -1,8 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: Copyright the Vortex contributors +mod kernel; + +use std::fmt::Display; use std::fmt::Formatter; +pub use kernel::*; use prost::Message; use vortex_dtype::DType; use vortex_error::VortexResult; @@ -12,9 +16,10 @@ use vortex_proto::expr as pb; use vortex_scalar::StringLike; use vortex_session::VortexSession; +use crate::Array; use crate::ArrayRef; -use crate::compute::LikeOptions; -use crate::compute::like as like_compute; +use crate::arrow::Datum; +use crate::arrow::from_arrow_array_with_len; use crate::expr::Arity; use crate::expr::ChildName; use crate::expr::ExecutionArgs; @@ -31,6 +36,26 @@ use crate::expr::lit; use crate::expr::lt; use crate::expr::or; +/// Options for SQL LIKE function +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LikeOptions { + pub negated: bool, + pub case_insensitive: bool, +} + +impl Display for LikeOptions { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if self.negated { + write!(f, "NOT ")?; + } + if self.case_insensitive { + write!(f, "ILIKE") + } else { + write!(f, "LIKE") + } + } +} + /// Expression that performs SQL LIKE pattern matching. pub struct Like; @@ -118,7 +143,13 @@ impl VTable for Like { .try_into() .map_err(|_| vortex_err!("Wrong argument count"))?; - like_compute(&child, &pattern, *options)?.execute(args.ctx) + if !child.is_canonical() || !pattern.is_canonical() { + let child = child.execute::(args.ctx)?; + let pattern = pattern.execute::(args.ctx)?; + return arrow_like(&child, &pattern, *options); + } + + arrow_like(&child, &pattern, *options) } fn validity( @@ -174,6 +205,35 @@ impl VTable for Like { } } +/// Implementation of LIKE using the Arrow crate. +pub(crate) fn arrow_like( + array: &dyn Array, + pattern: &dyn Array, + options: LikeOptions, +) -> VortexResult { + let nullable = array.dtype().is_nullable() | pattern.dtype().is_nullable(); + let len = array.len(); + assert_eq!( + array.len(), + pattern.len(), + "Arrow Like: length mismatch for {}", + array.encoding_id() + ); + + // convert the pattern to the preferred array datatype + let lhs = Datum::try_new(array)?; + let rhs = Datum::try_new_with_target_datatype(pattern, lhs.data_type())?; + + let result = match (options.negated, options.case_insensitive) { + (false, false) => arrow_string::like::like(&lhs, &rhs)?, + (true, false) => arrow_string::like::nlike(&lhs, &rhs)?, + (false, true) => arrow_string::like::ilike(&lhs, &rhs)?, + (true, true) => arrow_string::like::nilike(&lhs, &rhs)?, + }; + + from_arrow_array_with_len(&result, len, nullable) +} + /// Variants of the LIKE filter that we know how to turn into a stats pruning predicate.s #[derive(Debug, PartialEq)] enum LikeVariant<'a> { diff --git a/vortex-datafusion/src/convert/exprs.rs b/vortex-datafusion/src/convert/exprs.rs index a3e8e9c21d2..fe3905f0129 100644 --- a/vortex-datafusion/src/convert/exprs.rs +++ b/vortex-datafusion/src/convert/exprs.rs @@ -19,13 +19,13 @@ use datafusion_physical_expr::utils::collect_columns; use datafusion_physical_expr_common::physical_expr::is_dynamic_physical_expr; use datafusion_physical_plan::expressions as df_expr; use itertools::Itertools; -use vortex::compute::LikeOptions; use vortex::dtype::DType; use vortex::dtype::Nullability; use vortex::dtype::arrow::FromArrowType; use vortex::expr::Binary; use vortex::expr::Expression; use vortex::expr::Like; +use vortex::expr::LikeOptions; use vortex::expr::Operator; use vortex::expr::VTableExt; use vortex::expr::and_collect; diff --git a/vortex-duckdb/src/convert/expr.rs b/vortex-duckdb/src/convert/expr.rs index 2ae3feccac2..02f3eb695bf 100644 --- a/vortex-duckdb/src/convert/expr.rs +++ b/vortex-duckdb/src/convert/expr.rs @@ -6,7 +6,6 @@ use std::sync::Arc; use itertools::Itertools; use tracing::debug; use vortex::compute::BetweenOptions; -use vortex::compute::LikeOptions; use vortex::compute::StrictComparison; use vortex::dtype::Nullability; use vortex::error::VortexError; @@ -18,6 +17,7 @@ use vortex::expr::Between; use vortex::expr::Binary; use vortex::expr::Expression; use vortex::expr::Like; +use vortex::expr::LikeOptions; use vortex::expr::Literal; use vortex::expr::Operator; use vortex::expr::VTableExt; diff --git a/vortex/public-api.lock b/vortex/public-api.lock index 6a7a137a0be..b98bd48e170 100644 --- a/vortex/public-api.lock +++ b/vortex/public-api.lock @@ -1,3 +1,24 @@ + Checking vortex-array v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-array) + Checking vortex-runend v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/runend) + Checking vortex-fastlanes v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/fastlanes) + Checking vortex-decimal-byte-parts v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/decimal-byte-parts) + Checking vortex-zigzag v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/zigzag) + Checking vortex-sparse v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/sparse) + Checking vortex-zstd v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/zstd) + Checking vortex-pco v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/pco) + Checking vortex-datetime-parts v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/datetime-parts) + Checking vortex-fsst v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/fsst) + Checking vortex-io v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-io) + Checking vortex-bytebool v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/bytebool) + Checking vortex-ipc v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-ipc) + Checking vortex-sequence v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/sequence) + Checking vortex-alp v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/alp) + Checking vortex-btrblocks v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-btrblocks) + Checking vortex-layout v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-layout) + Checking vortex-scan v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-scan) + Checking vortex-file v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-file) + Documenting vortex v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 7.33s pub mod vortex pub use vortex::compute From 76294cc01f5ab6296c2af7826842ff10a697e984 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Fri, 13 Feb 2026 18:02:40 +0000 Subject: [PATCH 2/8] u Signed-off-by: Joe Isaacs --- vortex-array/src/arrays/dict/compute/like.rs | 44 +++++++++++++++++++ vortex-array/src/arrays/dict/compute/mod.rs | 1 + vortex-array/src/arrays/dict/compute/rules.rs | 2 + 3 files changed, 47 insertions(+) create mode 100644 vortex-array/src/arrays/dict/compute/like.rs diff --git a/vortex-array/src/arrays/dict/compute/like.rs b/vortex-array/src/arrays/dict/compute/like.rs new file mode 100644 index 00000000000..9d3e046cb3a --- /dev/null +++ b/vortex-array/src/arrays/dict/compute/like.rs @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use vortex_error::VortexResult; + +use super::DictArray; +use super::DictVTable; +use crate::Array; +use crate::ArrayRef; +use crate::IntoArray; +use crate::arrays::ConstantArray; +use crate::expr::LikeOptions; +use crate::expr::LikeReduce; +use crate::expr::like::arrow_like; + +impl LikeReduce for DictVTable { + fn like( + array: &DictArray, + pattern: &dyn Array, + options: LikeOptions, + ) -> VortexResult> { + // If we have more values than codes, it is faster to canonicalize first. + if array.values().len() > array.codes().len() { + return Ok(None); + } + if let Some(pattern) = pattern.as_constant() { + let pattern = ConstantArray::new(pattern, array.values().len()).into_array(); + let values = arrow_like(array.values(), &pattern, options)?; + + // SAFETY: LIKE preserves the len of the values, so codes are still pointing at + // valid positions. + // Preserve all_values_referenced since codes are unchanged. + unsafe { + Ok(Some( + DictArray::new_unchecked(array.codes().clone(), values) + .set_all_values_referenced(array.has_all_values_referenced()) + .into_array(), + )) + } + } else { + Ok(None) + } + } +} diff --git a/vortex-array/src/arrays/dict/compute/mod.rs b/vortex-array/src/arrays/dict/compute/mod.rs index 9e90f520a82..056b151ec06 100644 --- a/vortex-array/src/arrays/dict/compute/mod.rs +++ b/vortex-array/src/arrays/dict/compute/mod.rs @@ -6,6 +6,7 @@ mod compare; mod fill_null; mod is_constant; mod is_sorted; +mod like; mod min_max; pub(crate) mod rules; mod slice; diff --git a/vortex-array/src/arrays/dict/compute/rules.rs b/vortex-array/src/arrays/dict/compute/rules.rs index cc6df43b650..583e52db2b4 100644 --- a/vortex-array/src/arrays/dict/compute/rules.rs +++ b/vortex-array/src/arrays/dict/compute/rules.rs @@ -19,6 +19,7 @@ use crate::arrays::SliceReduceAdaptor; use crate::builtins::ArrayBuiltins; use crate::compute::CastReduceAdaptor; use crate::expr::Cast; +use crate::expr::LikeReduceAdaptor; use crate::expr::Pack; use crate::optimizer::ArrayOptimizer; use crate::optimizer::rules::ArrayParentReduceRule; @@ -27,6 +28,7 @@ use crate::optimizer::rules::ParentRuleSet; pub(crate) const PARENT_RULES: ParentRuleSet = ParentRuleSet::new(&[ ParentRuleSet::lift(&FilterReduceAdaptor(DictVTable)), ParentRuleSet::lift(&CastReduceAdaptor(DictVTable)), + ParentRuleSet::lift(&LikeReduceAdaptor(DictVTable)), ParentRuleSet::lift(&DictionaryScalarFnValuesPushDownRule), ParentRuleSet::lift(&DictionaryScalarFnCodesPullUpRule), ParentRuleSet::lift(&SliceReduceAdaptor(DictVTable)), From 2dc7fa066d4f54819cf97397d1aa4fd80036c702 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Mon, 16 Feb 2026 09:48:01 +0000 Subject: [PATCH 3/8] u Signed-off-by: Joe Isaacs --- vortex-array/public-api.lock | 192 +++++++++++++++++++---------------- vortex/public-api.lock | 21 ---- 2 files changed, 104 insertions(+), 109 deletions(-) diff --git a/vortex-array/public-api.lock b/vortex-array/public-api.lock index c0d512c63ee..f963a9f25f9 100644 --- a/vortex-array/public-api.lock +++ b/vortex-array/public-api.lock @@ -112,10 +112,6 @@ pub fn vortex_array::arrays::DictVTable::is_sorted(&self, array: &vortex_array:: pub fn vortex_array::arrays::DictVTable::is_strict_sorted(&self, array: &vortex_array::arrays::DictArray) -> vortex_error::VortexResult> -impl vortex_array::compute::LikeKernel for vortex_array::arrays::DictVTable - -pub fn vortex_array::arrays::DictVTable::like(&self, array: &vortex_array::arrays::DictArray, pattern: &dyn vortex_array::Array, options: vortex_array::compute::LikeOptions) -> vortex_error::VortexResult> - impl vortex_array::compute::MinMaxKernel for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::min_max(&self, array: &vortex_array::arrays::DictArray) -> vortex_error::VortexResult> @@ -128,6 +124,10 @@ impl vortex_array::expr::FillNullKernel for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::fill_null(array: &vortex_array::arrays::DictArray, fill_value: &vortex_scalar::scalar::Scalar, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +impl vortex_array::expr::LikeReduce for vortex_array::arrays::DictVTable + +pub fn vortex_array::arrays::DictVTable::like(array: &vortex_array::arrays::DictArray, pattern: &dyn vortex_array::Array, options: vortex_array::expr::LikeOptions) -> vortex_error::VortexResult> + impl vortex_array::vtable::BaseArrayVTable for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::array_eq(array: &vortex_array::arrays::DictArray, other: &vortex_array::arrays::DictArray, precision: vortex_array::Precision) -> bool @@ -1128,10 +1128,6 @@ pub fn vortex_array::arrays::DictVTable::is_sorted(&self, array: &vortex_array:: pub fn vortex_array::arrays::DictVTable::is_strict_sorted(&self, array: &vortex_array::arrays::DictArray) -> vortex_error::VortexResult> -impl vortex_array::compute::LikeKernel for vortex_array::arrays::DictVTable - -pub fn vortex_array::arrays::DictVTable::like(&self, array: &vortex_array::arrays::DictArray, pattern: &dyn vortex_array::Array, options: vortex_array::compute::LikeOptions) -> vortex_error::VortexResult> - impl vortex_array::compute::MinMaxKernel for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::min_max(&self, array: &vortex_array::arrays::DictArray) -> vortex_error::VortexResult> @@ -1144,6 +1140,10 @@ impl vortex_array::expr::FillNullKernel for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::fill_null(array: &vortex_array::arrays::DictArray, fill_value: &vortex_scalar::scalar::Scalar, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +impl vortex_array::expr::LikeReduce for vortex_array::arrays::DictVTable + +pub fn vortex_array::arrays::DictVTable::like(array: &vortex_array::arrays::DictArray, pattern: &dyn vortex_array::Array, options: vortex_array::expr::LikeOptions) -> vortex_error::VortexResult> + impl vortex_array::vtable::BaseArrayVTable for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::array_eq(array: &vortex_array::arrays::DictArray, other: &vortex_array::arrays::DictArray, precision: vortex_array::Precision) -> bool @@ -5848,64 +5848,6 @@ pub struct vortex_array::compute::IsSortedKernelRef(_) impl inventory::Collect for vortex_array::compute::IsSortedKernelRef -pub struct vortex_array::compute::LikeKernelAdapter(pub V) - -impl vortex_array::compute::LikeKernelAdapter - -pub const fn vortex_array::compute::LikeKernelAdapter::lift(&'static self) -> vortex_array::compute::LikeKernelRef - -impl core::fmt::Debug for vortex_array::compute::LikeKernelAdapter - -pub fn vortex_array::compute::LikeKernelAdapter::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result - -impl vortex_array::compute::Kernel for vortex_array::compute::LikeKernelAdapter - -pub fn vortex_array::compute::LikeKernelAdapter::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>) -> vortex_error::VortexResult> - -pub struct vortex_array::compute::LikeKernelRef(_) - -impl inventory::Collect for vortex_array::compute::LikeKernelRef - -pub struct vortex_array::compute::LikeOptions - -pub vortex_array::compute::LikeOptions::case_insensitive: bool - -pub vortex_array::compute::LikeOptions::negated: bool - -impl core::clone::Clone for vortex_array::compute::LikeOptions - -pub fn vortex_array::compute::LikeOptions::clone(&self) -> vortex_array::compute::LikeOptions - -impl core::cmp::Eq for vortex_array::compute::LikeOptions - -impl core::cmp::PartialEq for vortex_array::compute::LikeOptions - -pub fn vortex_array::compute::LikeOptions::eq(&self, other: &vortex_array::compute::LikeOptions) -> bool - -impl core::default::Default for vortex_array::compute::LikeOptions - -pub fn vortex_array::compute::LikeOptions::default() -> vortex_array::compute::LikeOptions - -impl core::fmt::Debug for vortex_array::compute::LikeOptions - -pub fn vortex_array::compute::LikeOptions::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result - -impl core::fmt::Display for vortex_array::compute::LikeOptions - -pub fn vortex_array::compute::LikeOptions::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result - -impl core::hash::Hash for vortex_array::compute::LikeOptions - -pub fn vortex_array::compute::LikeOptions::hash<__H: core::hash::Hasher>(&self, state: &mut __H) - -impl core::marker::Copy for vortex_array::compute::LikeOptions - -impl core::marker::StructuralPartialEq for vortex_array::compute::LikeOptions - -impl vortex_array::compute::Options for vortex_array::compute::LikeOptions - -pub fn vortex_array::compute::LikeOptions::as_any(&self) -> &dyn core::any::Any - pub struct vortex_array::compute::ListContains impl vortex_array::compute::ComputeFnVTable for vortex_array::compute::ListContains @@ -6418,10 +6360,6 @@ impl vo pub fn vortex_array::compute::IsSortedKernelAdapter::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>) -> vortex_error::VortexResult> -impl vortex_array::compute::Kernel for vortex_array::compute::LikeKernelAdapter - -pub fn vortex_array::compute::LikeKernelAdapter::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>) -> vortex_error::VortexResult> - impl vortex_array::compute::Kernel for vortex_array::compute::ListContainsKernelAdapter pub fn vortex_array::compute::ListContainsKernelAdapter::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>) -> vortex_error::VortexResult> @@ -6442,14 +6380,6 @@ impl vortex_ pub fn vortex_array::compute::SumKernelAdapter::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>) -> vortex_error::VortexResult> -pub trait vortex_array::compute::LikeKernel: vortex_array::vtable::VTable - -pub fn vortex_array::compute::LikeKernel::like(&self, array: &Self::Array, pattern: &dyn vortex_array::Array, options: vortex_array::compute::LikeOptions) -> vortex_error::VortexResult> - -impl vortex_array::compute::LikeKernel for vortex_array::arrays::DictVTable - -pub fn vortex_array::arrays::DictVTable::like(&self, array: &vortex_array::arrays::DictArray, pattern: &dyn vortex_array::Array, options: vortex_array::compute::LikeOptions) -> vortex_error::VortexResult> - pub trait vortex_array::compute::ListContainsKernel: vortex_array::vtable::VTable pub fn vortex_array::compute::ListContainsKernel::list_contains(&self, list: &dyn vortex_array::Array, element: &Self::Array) -> vortex_error::VortexResult> @@ -6614,10 +6544,6 @@ impl vortex_array::compute::Options for vortex_array::compute::IsConstantOpts pub fn vortex_array::compute::IsConstantOpts::as_any(&self) -> &dyn core::any::Any -impl vortex_array::compute::Options for vortex_array::compute::LikeOptions - -pub fn vortex_array::compute::LikeOptions::as_any(&self) -> &dyn core::any::Any - impl vortex_array::compute::Options for vortex_array::compute::Operator pub fn vortex_array::compute::Operator::as_any(&self) -> &dyn core::any::Any @@ -6694,8 +6620,6 @@ pub fn vortex_array::compute::is_sorted_opts(array: &dyn vortex_array::Array, st pub fn vortex_array::compute::is_strict_sorted(array: &dyn vortex_array::Array) -> vortex_error::VortexResult> -pub fn vortex_array::compute::like(array: &dyn vortex_array::Array, pattern: &dyn vortex_array::Array, options: vortex_array::compute::LikeOptions) -> vortex_error::VortexResult - pub fn vortex_array::compute::list_contains(array: &dyn vortex_array::Array, value: &dyn vortex_array::Array) -> vortex_error::VortexResult pub fn vortex_array::compute::mask(array: &dyn vortex_array::Array, mask: &vortex_mask::Mask) -> vortex_error::VortexResult @@ -8476,7 +8400,7 @@ pub struct vortex_array::expr::Like impl vortex_array::expr::VTable for vortex_array::expr::Like -pub type vortex_array::expr::Like::Options = vortex_array::compute::LikeOptions +pub type vortex_array::expr::Like::Options = vortex_array::expr::LikeOptions pub fn vortex_array::expr::Like::arity(&self, _options: &Self::Options) -> vortex_array::expr::Arity @@ -8496,10 +8420,78 @@ pub fn vortex_array::expr::Like::return_dtype(&self, _options: &Self::Options, a pub fn vortex_array::expr::Like::serialize(&self, instance: &Self::Options) -> vortex_error::VortexResult>> -pub fn vortex_array::expr::Like::stat_falsification(&self, like_opts: &vortex_array::compute::LikeOptions, expr: &vortex_array::expr::Expression, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option +pub fn vortex_array::expr::Like::stat_falsification(&self, like_opts: &vortex_array::expr::LikeOptions, expr: &vortex_array::expr::Expression, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option pub fn vortex_array::expr::Like::validity(&self, _options: &Self::Options, expression: &vortex_array::expr::Expression) -> vortex_error::VortexResult> +pub struct vortex_array::expr::LikeExecuteAdaptor(pub V) + +impl core::default::Default for vortex_array::expr::LikeExecuteAdaptor + +pub fn vortex_array::expr::LikeExecuteAdaptor::default() -> vortex_array::expr::LikeExecuteAdaptor + +impl core::fmt::Debug for vortex_array::expr::LikeExecuteAdaptor + +pub fn vortex_array::expr::LikeExecuteAdaptor::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::kernel::ExecuteParentKernel for vortex_array::expr::LikeExecuteAdaptor where V: vortex_array::expr::LikeKernel + +pub type vortex_array::expr::LikeExecuteAdaptor::Parent = vortex_array::arrays::ExactScalarFn + +pub fn vortex_array::expr::LikeExecuteAdaptor::execute_parent(&self, array: &::Array, parent: vortex_array::arrays::ScalarFnArrayView<'_, vortex_array::expr::Like>, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> + +pub struct vortex_array::expr::LikeOptions + +pub vortex_array::expr::LikeOptions::case_insensitive: bool + +pub vortex_array::expr::LikeOptions::negated: bool + +impl core::clone::Clone for vortex_array::expr::LikeOptions + +pub fn vortex_array::expr::LikeOptions::clone(&self) -> vortex_array::expr::LikeOptions + +impl core::cmp::Eq for vortex_array::expr::LikeOptions + +impl core::cmp::PartialEq for vortex_array::expr::LikeOptions + +pub fn vortex_array::expr::LikeOptions::eq(&self, other: &vortex_array::expr::LikeOptions) -> bool + +impl core::default::Default for vortex_array::expr::LikeOptions + +pub fn vortex_array::expr::LikeOptions::default() -> vortex_array::expr::LikeOptions + +impl core::fmt::Debug for vortex_array::expr::LikeOptions + +pub fn vortex_array::expr::LikeOptions::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::fmt::Display for vortex_array::expr::LikeOptions + +pub fn vortex_array::expr::LikeOptions::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::hash::Hash for vortex_array::expr::LikeOptions + +pub fn vortex_array::expr::LikeOptions::hash<__H: core::hash::Hasher>(&self, state: &mut __H) + +impl core::marker::Copy for vortex_array::expr::LikeOptions + +impl core::marker::StructuralPartialEq for vortex_array::expr::LikeOptions + +pub struct vortex_array::expr::LikeReduceAdaptor(pub V) + +impl core::default::Default for vortex_array::expr::LikeReduceAdaptor + +pub fn vortex_array::expr::LikeReduceAdaptor::default() -> vortex_array::expr::LikeReduceAdaptor + +impl core::fmt::Debug for vortex_array::expr::LikeReduceAdaptor + +pub fn vortex_array::expr::LikeReduceAdaptor::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::optimizer::rules::ArrayParentReduceRule for vortex_array::expr::LikeReduceAdaptor where V: vortex_array::expr::LikeReduce + +pub type vortex_array::expr::LikeReduceAdaptor::Parent = vortex_array::arrays::ExactScalarFn + +pub fn vortex_array::expr::LikeReduceAdaptor::reduce_parent(&self, array: &::Array, parent: vortex_array::arrays::ScalarFnArrayView<'_, vortex_array::expr::Like>, child_idx: usize) -> vortex_error::VortexResult> + pub struct vortex_array::expr::ListContains impl vortex_array::expr::VTable for vortex_array::expr::ListContains @@ -9148,6 +9140,18 @@ impl vortex_array::expr::FillNullReduce for vortex_array::arrays::ConstantVTable pub fn vortex_array::arrays::ConstantVTable::fill_null(array: &vortex_array::arrays::ConstantArray, fill_value: &vortex_scalar::scalar::Scalar) -> vortex_error::VortexResult> +pub trait vortex_array::expr::LikeKernel: vortex_array::vtable::VTable + +pub fn vortex_array::expr::LikeKernel::like(array: &Self::Array, pattern: &dyn vortex_array::Array, options: vortex_array::expr::LikeOptions, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> + +pub trait vortex_array::expr::LikeReduce: vortex_array::vtable::VTable + +pub fn vortex_array::expr::LikeReduce::like(array: &Self::Array, pattern: &dyn vortex_array::Array, options: vortex_array::expr::LikeOptions) -> vortex_error::VortexResult> + +impl vortex_array::expr::LikeReduce for vortex_array::arrays::DictVTable + +pub fn vortex_array::arrays::DictVTable::like(array: &vortex_array::arrays::DictArray, pattern: &dyn vortex_array::Array, options: vortex_array::expr::LikeOptions) -> vortex_error::VortexResult> + pub trait vortex_array::expr::NotKernel: vortex_array::vtable::VTable pub fn vortex_array::expr::NotKernel::invert(array: &Self::Array, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> @@ -9444,7 +9448,7 @@ pub fn vortex_array::expr::IsNull::stat_falsification(&self, _options: &Self::Op impl vortex_array::expr::VTable for vortex_array::expr::Like -pub type vortex_array::expr::Like::Options = vortex_array::compute::LikeOptions +pub type vortex_array::expr::Like::Options = vortex_array::expr::LikeOptions pub fn vortex_array::expr::Like::arity(&self, _options: &Self::Options) -> vortex_array::expr::Arity @@ -9464,7 +9468,7 @@ pub fn vortex_array::expr::Like::return_dtype(&self, _options: &Self::Options, a pub fn vortex_array::expr::Like::serialize(&self, instance: &Self::Options) -> vortex_error::VortexResult>> -pub fn vortex_array::expr::Like::stat_falsification(&self, like_opts: &vortex_array::compute::LikeOptions, expr: &vortex_array::expr::Expression, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option +pub fn vortex_array::expr::Like::stat_falsification(&self, like_opts: &vortex_array::expr::LikeOptions, expr: &vortex_array::expr::Expression, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option pub fn vortex_array::expr::Like::validity(&self, _options: &Self::Options, expression: &vortex_array::expr::Expression) -> vortex_error::VortexResult> @@ -9954,6 +9958,12 @@ pub type vortex_array::expr::FillNullExecuteAdaptor::Parent = vortex_array::a pub fn vortex_array::expr::FillNullExecuteAdaptor::execute_parent(&self, array: &::Array, parent: vortex_array::arrays::ScalarFnArrayView<'_, vortex_array::expr::FillNull>, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> +impl vortex_array::kernel::ExecuteParentKernel for vortex_array::expr::LikeExecuteAdaptor where V: vortex_array::expr::LikeKernel + +pub type vortex_array::expr::LikeExecuteAdaptor::Parent = vortex_array::arrays::ExactScalarFn + +pub fn vortex_array::expr::LikeExecuteAdaptor::execute_parent(&self, array: &::Array, parent: vortex_array::arrays::ScalarFnArrayView<'_, vortex_array::expr::Like>, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> + impl vortex_array::kernel::ExecuteParentKernel for vortex_array::expr::NotExecuteAdaptor where V: vortex_array::expr::NotKernel pub type vortex_array::expr::NotExecuteAdaptor::Parent = vortex_array::arrays::ExactScalarFn @@ -10136,6 +10146,12 @@ pub type vortex_array::expr::FillNullReduceAdaptor::Parent = vortex_array::ar pub fn vortex_array::expr::FillNullReduceAdaptor::reduce_parent(&self, array: &::Array, parent: vortex_array::arrays::ScalarFnArrayView<'_, vortex_array::expr::FillNull>, child_idx: usize) -> vortex_error::VortexResult> +impl vortex_array::optimizer::rules::ArrayParentReduceRule for vortex_array::expr::LikeReduceAdaptor where V: vortex_array::expr::LikeReduce + +pub type vortex_array::expr::LikeReduceAdaptor::Parent = vortex_array::arrays::ExactScalarFn + +pub fn vortex_array::expr::LikeReduceAdaptor::reduce_parent(&self, array: &::Array, parent: vortex_array::arrays::ScalarFnArrayView<'_, vortex_array::expr::Like>, child_idx: usize) -> vortex_error::VortexResult> + impl vortex_array::optimizer::rules::ArrayParentReduceRule for vortex_array::expr::NotReduceAdaptor where V: vortex_array::expr::NotReduce pub type vortex_array::expr::NotReduceAdaptor::Parent = vortex_array::arrays::ExactScalarFn diff --git a/vortex/public-api.lock b/vortex/public-api.lock index b98bd48e170..6a7a137a0be 100644 --- a/vortex/public-api.lock +++ b/vortex/public-api.lock @@ -1,24 +1,3 @@ - Checking vortex-array v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-array) - Checking vortex-runend v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/runend) - Checking vortex-fastlanes v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/fastlanes) - Checking vortex-decimal-byte-parts v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/decimal-byte-parts) - Checking vortex-zigzag v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/zigzag) - Checking vortex-sparse v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/sparse) - Checking vortex-zstd v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/zstd) - Checking vortex-pco v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/pco) - Checking vortex-datetime-parts v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/datetime-parts) - Checking vortex-fsst v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/fsst) - Checking vortex-io v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-io) - Checking vortex-bytebool v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/bytebool) - Checking vortex-ipc v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-ipc) - Checking vortex-sequence v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/sequence) - Checking vortex-alp v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/encodings/alp) - Checking vortex-btrblocks v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-btrblocks) - Checking vortex-layout v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-layout) - Checking vortex-scan v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-scan) - Checking vortex-file v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-file) - Documenting vortex v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex) - Finished `dev` profile [unoptimized + debuginfo] target(s) in 7.33s pub mod vortex pub use vortex::compute From a914d78090aaa8a54d6ab99ceb4b87ab23064078 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Mon, 16 Feb 2026 10:11:12 +0000 Subject: [PATCH 4/8] u Signed-off-by: Joe Isaacs --- vortex-array/src/arrays/dict/compute/like.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vortex-array/src/arrays/dict/compute/like.rs b/vortex-array/src/arrays/dict/compute/like.rs index 9d3e046cb3a..0c3ed979551 100644 --- a/vortex-array/src/arrays/dict/compute/like.rs +++ b/vortex-array/src/arrays/dict/compute/like.rs @@ -9,9 +9,11 @@ use crate::Array; use crate::ArrayRef; use crate::IntoArray; use crate::arrays::ConstantArray; +use crate::arrays::ScalarFnArrayExt; +use crate::expr::Like; use crate::expr::LikeOptions; use crate::expr::LikeReduce; -use crate::expr::like::arrow_like; +use crate::optimizer::ArrayOptimizer; impl LikeReduce for DictVTable { fn like( @@ -25,7 +27,10 @@ impl LikeReduce for DictVTable { } if let Some(pattern) = pattern.as_constant() { let pattern = ConstantArray::new(pattern, array.values().len()).into_array(); - let values = arrow_like(array.values(), &pattern, options)?; + + let values = Like + .try_new_array(array.len(), options, [array.values().clone(), pattern])? + .optimize()?; // SAFETY: LIKE preserves the len of the values, so codes are still pointing at // valid positions. From 27a8cc2eb8f38d3a0fc7715da83952cc8897059c Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Mon, 16 Feb 2026 10:56:22 +0000 Subject: [PATCH 5/8] u Signed-off-by: Joe Isaacs --- vortex-array/src/arrays/dict/compute/like.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vortex-array/src/arrays/dict/compute/like.rs b/vortex-array/src/arrays/dict/compute/like.rs index 0c3ed979551..d777ad98cc4 100644 --- a/vortex-array/src/arrays/dict/compute/like.rs +++ b/vortex-array/src/arrays/dict/compute/like.rs @@ -29,7 +29,7 @@ impl LikeReduce for DictVTable { let pattern = ConstantArray::new(pattern, array.values().len()).into_array(); let values = Like - .try_new_array(array.len(), options, [array.values().clone(), pattern])? + .try_new_array(pattern.len(), options, [array.values().clone(), pattern])? .optimize()?; // SAFETY: LIKE preserves the len of the values, so codes are still pointing at From 00aef86072477b607fe5b5a7426847c1abd8fe24 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Mon, 16 Feb 2026 11:02:40 +0000 Subject: [PATCH 6/8] u Signed-off-by: Joe Isaacs --- vortex-array/src/arrays/dict/compute/like.rs | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/vortex-array/src/arrays/dict/compute/like.rs b/vortex-array/src/arrays/dict/compute/like.rs index d777ad98cc4..a32bca16332 100644 --- a/vortex-array/src/arrays/dict/compute/like.rs +++ b/vortex-array/src/arrays/dict/compute/like.rs @@ -47,3 +47,37 @@ impl LikeReduce for DictVTable { } } } + +#[cfg(test)] +mod tests { + use vortex_buffer::buffer; + use vortex_error::VortexResult; + + use crate::IntoArray; + use crate::arrays::BoolArray; + use crate::arrays::ConstantArray; + use crate::arrays::DictArray; + use crate::arrays::ScalarFnArrayExt; + use crate::arrays::VarBinArray; + use crate::assert_arrays_eq; + use crate::expr::Like; + use crate::expr::LikeOptions; + use crate::optimizer::ArrayOptimizer; + + #[test] + fn like_reduce_dict() -> VortexResult<()> { + let dict = DictArray::try_new( + buffer![0u8, 1, 0, 2].into_array(), + VarBinArray::from(vec!["hello", "world", "help"]).into_array(), + )? + .into_array(); + + let pattern = ConstantArray::new("hel%", 4).into_array(); + let result = Like + .try_new_array(4, LikeOptions::default(), [dict, pattern])? + .optimize()?; + + assert_arrays_eq!(result, BoolArray::from_iter([true, false, true, true])); + Ok(()) + } +} From 42144c716f7ec5080fa08a84cedb4e04c5af11ff Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Mon, 16 Feb 2026 11:15:07 +0000 Subject: [PATCH 7/8] u Signed-off-by: Joe Isaacs --- vortex-array/src/arrays/dict/compute/like.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vortex-array/src/arrays/dict/compute/like.rs b/vortex-array/src/arrays/dict/compute/like.rs index a32bca16332..3b97903e4c3 100644 --- a/vortex-array/src/arrays/dict/compute/like.rs +++ b/vortex-array/src/arrays/dict/compute/like.rs @@ -72,12 +72,12 @@ mod tests { )? .into_array(); - let pattern = ConstantArray::new("hel%", 4).into_array(); + let pattern = ConstantArray::new("hello%", 4).into_array(); let result = Like .try_new_array(4, LikeOptions::default(), [dict, pattern])? .optimize()?; - assert_arrays_eq!(result, BoolArray::from_iter([true, false, true, true])); + assert_arrays_eq!(result, BoolArray::from_iter([true, false, true, false])); Ok(()) } } From 0d47115585deebaa30b3eb24004a7ff29c97b72b Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Mon, 16 Feb 2026 11:34:21 +0000 Subject: [PATCH 8/8] u Signed-off-by: Joe Isaacs --- vortex-array/src/expr/exprs/like/mod.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/vortex-array/src/expr/exprs/like/mod.rs b/vortex-array/src/expr/exprs/like/mod.rs index 5454fa80dba..6a14d30bf3a 100644 --- a/vortex-array/src/expr/exprs/like/mod.rs +++ b/vortex-array/src/expr/exprs/like/mod.rs @@ -143,12 +143,6 @@ impl VTable for Like { .try_into() .map_err(|_| vortex_err!("Wrong argument count"))?; - if !child.is_canonical() || !pattern.is_canonical() { - let child = child.execute::(args.ctx)?; - let pattern = pattern.execute::(args.ctx)?; - return arrow_like(&child, &pattern, *options); - } - arrow_like(&child, &pattern, *options) }