From 64a2a60ee2694d3f0942877fbd4ffd2384fe963b Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Fri, 13 Feb 2026 16:58:32 +0000 Subject: [PATCH 1/2] break[array]: move like compute to lazy compute Signed-off-by: Joe Isaacs --- vortex-array/public-api.lock | 96 ++++---- 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 ++ 11 files changed, 245 insertions(+), 336 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/public-api.lock b/vortex-array/public-api.lock index 945d7ffdc7f..7ad0d1ed4f6 100644 --- a/vortex-array/public-api.lock +++ b/vortex-array/public-api.lock @@ -1,3 +1,5 @@ + Documenting vortex-array v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-array) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.16s pub mod vortex_array pub mod vortex_array::accessor pub trait vortex_array::accessor::ArrayAccessor @@ -57,8 +59,6 @@ pub fn vortex_array::arrays::DictVTable::is_constant(&self, array: &vortex_array impl vortex_array::compute::IsSortedKernel for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::is_sorted(&self, array: &vortex_array::arrays::DictArray) -> vortex_error::VortexResult> 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> impl vortex_array::expr::FillNullKernel for vortex_array::arrays::DictVTable @@ -565,8 +565,6 @@ pub fn vortex_array::arrays::DictVTable::is_constant(&self, array: &vortex_array impl vortex_array::compute::IsSortedKernel for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::is_sorted(&self, array: &vortex_array::arrays::DictArray) -> vortex_error::VortexResult> 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> impl vortex_array::expr::FillNullKernel for vortex_array::arrays::DictVTable @@ -2907,35 +2905,6 @@ impl vo pub fn vortex_array::compute::IsSortedKernelAdapter::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>) -> vortex_error::VortexResult> 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 pub fn vortex_array::compute::ListContains::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>, kernels: &[arcref::ArcRef]) -> vortex_error::VortexResult @@ -3160,8 +3129,6 @@ impl pub fn vortex_array::compute::IsConstantKernelAdapter::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>) -> vortex_error::VortexResult> impl vortex_array::compute::Kernel for vortex_array::compute::IsSortedKernelAdapter 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> impl vortex_array::compute::Kernel for vortex_array::compute::MaskKernelAdapter @@ -3172,10 +3139,6 @@ impl vo pub fn vortex_array::compute::NaNCountKernelAdapter::invoke(&self, args: &vortex_array::compute::InvocationArgs<'_>) -> vortex_error::VortexResult> impl vortex_array::compute::Kernel for vortex_array::compute::SumKernelAdapter 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> pub trait vortex_array::compute::MaskKernel: vortex_array::vtable::VTable @@ -3252,8 +3215,6 @@ impl vortex_array::compute::Options for vortex_array::compute::BooleanOperator pub fn vortex_array::compute::BooleanOperator::as_any(&self) -> &dyn core::any::Any 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 impl vortex_array::compute::Options for vortex_scalar::typed_view::primitive::numeric_operator::NumericOperator @@ -3292,7 +3253,6 @@ pub fn vortex_array::compute::is_constant_opts(array: &dyn vortex_array::Array, pub fn vortex_array::compute::is_sorted(array: &dyn vortex_array::Array) -> vortex_error::VortexResult> pub fn vortex_array::compute::is_sorted_opts(array: &dyn vortex_array::Array, strict: bool) -> vortex_error::VortexResult> 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 pub fn vortex_array::compute::min_max(array: &dyn vortex_array::Array) -> vortex_error::VortexResult> @@ -4167,7 +4127,7 @@ pub fn vortex_array::expr::IsNull::serialize(&self, _instance: &Self::Options) - pub fn vortex_array::expr::IsNull::stat_falsification(&self, _options: &Self::Options, expr: &vortex_array::expr::Expression, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option 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 pub fn vortex_array::expr::Like::child_name(&self, _instance: &Self::Options, child_idx: usize) -> vortex_array::expr::ChildName pub fn vortex_array::expr::Like::deserialize(&self, _metadata: &[u8], _session: &vortex_session::VortexSession) -> vortex_error::VortexResult @@ -4177,8 +4137,42 @@ pub fn vortex_array::expr::Like::id(&self) -> vortex_array::expr::ExprId pub fn vortex_array::expr::Like::is_null_sensitive(&self, _instance: &Self::Options) -> bool pub fn vortex_array::expr::Like::return_dtype(&self, _options: &Self::Options, arg_dtypes: &[vortex_dtype::dtype::DType]) -> vortex_error::VortexResult 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 pub type vortex_array::expr::ListContains::Options = vortex_array::expr::EmptyOptions @@ -4471,6 +4465,10 @@ impl vortex_array::expr::FillNullReduce for vortex_array::arrays::ChunkedVTable pub fn vortex_array::arrays::ChunkedVTable::fill_null(array: &vortex_array::arrays::ChunkedArray, fill_value: &vortex_scalar::scalar::Scalar) -> vortex_error::VortexResult> 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> 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> pub trait vortex_array::expr::NotReduce: vortex_array::vtable::VTable @@ -4614,7 +4612,7 @@ pub fn vortex_array::expr::IsNull::return_dtype(&self, _options: &Self::Options, pub fn vortex_array::expr::IsNull::serialize(&self, _instance: &Self::Options) -> vortex_error::VortexResult>> pub fn vortex_array::expr::IsNull::stat_falsification(&self, _options: &Self::Options, expr: &vortex_array::expr::Expression, catalog: &dyn vortex_array::expr::pruning::StatsCatalog) -> core::option::Option 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 pub fn vortex_array::expr::Like::child_name(&self, _instance: &Self::Options, child_idx: usize) -> vortex_array::expr::ChildName pub fn vortex_array::expr::Like::deserialize(&self, _metadata: &[u8], _session: &vortex_session::VortexSession) -> vortex_error::VortexResult @@ -4624,7 +4622,7 @@ pub fn vortex_array::expr::Like::id(&self) -> vortex_array::expr::ExprId pub fn vortex_array::expr::Like::is_null_sensitive(&self, _instance: &Self::Options) -> bool pub fn vortex_array::expr::Like::return_dtype(&self, _options: &Self::Options, arg_dtypes: &[vortex_dtype::dtype::DType]) -> vortex_error::VortexResult 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> impl vortex_array::expr::VTable for vortex_array::expr::ListContains pub type vortex_array::expr::ListContains::Options = vortex_array::expr::EmptyOptions @@ -4869,6 +4867,9 @@ pub fn vortex_array::compute::CastExecuteAdaptor::execute_parent(&self, array impl vortex_array::kernel::ExecuteParentKernel for vortex_array::expr::FillNullExecuteAdaptor where V: vortex_array::expr::FillNullKernel pub type vortex_array::expr::FillNullExecuteAdaptor::Parent = vortex_array::arrays::ExactScalarFn 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 pub fn vortex_array::expr::NotExecuteAdaptor::execute_parent(&self, array: &::Array, _parent: vortex_array::arrays::ScalarFnArrayView<'_, vortex_array::expr::Not>, _child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult> @@ -4960,6 +4961,9 @@ pub fn vortex_array::compute::CastReduceAdaptor::reduce_parent(&self, array: impl vortex_array::optimizer::rules::ArrayParentReduceRule for vortex_array::expr::FillNullReduceAdaptor where V: vortex_array::expr::FillNullReduce pub type vortex_array::expr::FillNullReduceAdaptor::Parent = vortex_array::arrays::ExactScalarFn 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 pub fn vortex_array::expr::NotReduceAdaptor::reduce_parent(&self, array: &::Array, _parent: vortex_array::arrays::ScalarFnArrayView<'_, vortex_array::expr::Not>, _child_idx: usize) -> vortex_error::VortexResult> 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 121c16c617f..2a588e5be93 100644 --- a/vortex-array/src/compute/mod.rs +++ b/vortex-array/src/compute/mod.rs @@ -26,7 +26,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::*; @@ -60,7 +59,6 @@ mod filter; mod invert; mod is_constant; mod is_sorted; -mod like; mod list_contains; mod mask; mod min_max; @@ -86,7 +84,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 9b88d47b833..4cde97938cb 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 pub use vortex::expr From e4d44ffeffaf0132385fe39b0acfc49dfc4e6c02 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Fri, 13 Feb 2026 18:02:40 +0000 Subject: [PATCH 2/2] u Signed-off-by: Joe Isaacs --- vortex-array/public-api.lock | 8 +++- 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 + 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 vortex-array/src/arrays/dict/compute/like.rs diff --git a/vortex-array/public-api.lock b/vortex-array/public-api.lock index d6bf00757b5..15b2e68c5b9 100644 --- a/vortex-array/public-api.lock +++ b/vortex-array/public-api.lock @@ -1,5 +1,5 @@ Documenting vortex-array v0.1.0 (/Users/joeisaacs/git/spiraldb/vortex/vortex-array) - Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.75s + Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.03s pub mod vortex_array pub mod vortex_array::accessor pub trait vortex_array::accessor::ArrayAccessor @@ -63,6 +63,8 @@ impl vortex_array::expr::CastReduce for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::cast(array: &vortex_array::arrays::DictArray, dtype: &vortex_dtype::dtype::DType) -> vortex_error::VortexResult> 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 pub fn vortex_array::arrays::DictVTable::array_hash(array: &vortex_array::arrays::DictArray, state: &mut H, precision: vortex_array::Precision) @@ -569,6 +571,8 @@ impl vortex_array::expr::CastReduce for vortex_array::arrays::DictVTable pub fn vortex_array::arrays::DictVTable::cast(array: &vortex_array::arrays::DictArray, dtype: &vortex_dtype::dtype::DType) -> vortex_error::VortexResult> 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 pub fn vortex_array::arrays::DictVTable::array_hash(array: &vortex_array::arrays::DictArray, state: &mut H, precision: vortex_array::Precision) @@ -4571,6 +4575,8 @@ 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> pub trait vortex_array::expr::NotReduce: vortex_array::vtable::VTable 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)),