Skip to content

Commit e08c98f

Browse files
committed
feat[array]: owned matchers
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent 5e93e8e commit e08c98f

7 files changed

Lines changed: 204 additions & 5 deletions

File tree

vortex-array/public-api.lock

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3618,6 +3618,12 @@ pub fn vortex_array::arrays::scalar_fn::AnyScalarFn::matches(array: &dyn vortex_
36183618

36193619
pub fn vortex_array::arrays::scalar_fn::AnyScalarFn::try_match(array: &dyn vortex_array::DynArray) -> core::option::Option<Self::Match>
36203620

3621+
impl vortex_array::matcher::OwnedMatcher for vortex_array::arrays::scalar_fn::AnyScalarFn
3622+
3623+
pub type vortex_array::arrays::scalar_fn::AnyScalarFn::OwnedMatch = vortex_array::arrays::scalar_fn::ScalarFnArray
3624+
3625+
pub fn vortex_array::arrays::scalar_fn::AnyScalarFn::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
3626+
36213627
pub struct vortex_array::arrays::scalar_fn::ExactScalarFn<F: vortex_array::scalar_fn::ScalarFnVTable>(_)
36223628

36233629
impl<F: core::default::Default + vortex_array::scalar_fn::ScalarFnVTable> core::default::Default for vortex_array::arrays::scalar_fn::ExactScalarFn<F>
@@ -15068,6 +15074,12 @@ pub fn vortex_array::matcher::AnyArray::matches(_array: &dyn vortex_array::DynAr
1506815074

1506915075
pub fn vortex_array::matcher::AnyArray::try_match(array: &dyn vortex_array::DynArray) -> core::option::Option<Self::Match>
1507015076

15077+
impl vortex_array::matcher::OwnedMatcher for vortex_array::matcher::AnyArray
15078+
15079+
pub type vortex_array::matcher::AnyArray::OwnedMatch = alloc::sync::Arc<dyn vortex_array::DynArray>
15080+
15081+
pub fn vortex_array::matcher::AnyArray::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
15082+
1507115083
pub trait vortex_array::matcher::Matcher
1507215084

1507315085
pub type vortex_array::matcher::Matcher::Match<'a>
@@ -15124,6 +15136,42 @@ pub fn V::matches(array: &dyn vortex_array::DynArray) -> bool
1512415136

1512515137
pub fn V::try_match<'a>(array: &'a dyn vortex_array::DynArray) -> core::option::Option<Self::Match>
1512615138

15139+
pub trait vortex_array::matcher::OwnedMatcher: vortex_array::matcher::Matcher
15140+
15141+
pub type vortex_array::matcher::OwnedMatcher::OwnedMatch
15142+
15143+
pub fn vortex_array::matcher::OwnedMatcher::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
15144+
15145+
impl vortex_array::matcher::OwnedMatcher for vortex_array::AnyCanonical
15146+
15147+
pub type vortex_array::AnyCanonical::OwnedMatch = vortex_array::Canonical
15148+
15149+
pub fn vortex_array::AnyCanonical::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
15150+
15151+
impl vortex_array::matcher::OwnedMatcher for vortex_array::AnyColumnar
15152+
15153+
pub type vortex_array::AnyColumnar::OwnedMatch = vortex_array::Columnar
15154+
15155+
pub fn vortex_array::AnyColumnar::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
15156+
15157+
impl vortex_array::matcher::OwnedMatcher for vortex_array::arrays::scalar_fn::AnyScalarFn
15158+
15159+
pub type vortex_array::arrays::scalar_fn::AnyScalarFn::OwnedMatch = vortex_array::arrays::scalar_fn::ScalarFnArray
15160+
15161+
pub fn vortex_array::arrays::scalar_fn::AnyScalarFn::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
15162+
15163+
impl vortex_array::matcher::OwnedMatcher for vortex_array::matcher::AnyArray
15164+
15165+
pub type vortex_array::matcher::AnyArray::OwnedMatch = alloc::sync::Arc<dyn vortex_array::DynArray>
15166+
15167+
pub fn vortex_array::matcher::AnyArray::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
15168+
15169+
impl<V: vortex_array::vtable::VTable> vortex_array::matcher::OwnedMatcher for V
15170+
15171+
pub type V::OwnedMatch = <V as vortex_array::vtable::VTable>::Array
15172+
15173+
pub fn V::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
15174+
1512715175
pub mod vortex_array::normalize
1512815176

1512915177
pub enum vortex_array::normalize::Operation
@@ -24098,6 +24146,12 @@ pub fn vortex_array::AnyCanonical::matches(array: &dyn vortex_array::DynArray) -
2409824146

2409924147
pub fn vortex_array::AnyCanonical::try_match<'a>(array: &'a dyn vortex_array::DynArray) -> core::option::Option<Self::Match>
2410024148

24149+
impl vortex_array::matcher::OwnedMatcher for vortex_array::AnyCanonical
24150+
24151+
pub type vortex_array::AnyCanonical::OwnedMatch = vortex_array::Canonical
24152+
24153+
pub fn vortex_array::AnyCanonical::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
24154+
2410124155
pub struct vortex_array::AnyColumnar
2410224156

2410324157
impl vortex_array::matcher::Matcher for vortex_array::AnyColumnar
@@ -24108,6 +24162,12 @@ pub fn vortex_array::AnyColumnar::matches(array: &dyn vortex_array::DynArray) ->
2410824162

2410924163
pub fn vortex_array::AnyColumnar::try_match<'a>(array: &'a dyn vortex_array::DynArray) -> core::option::Option<Self::Match>
2411024164

24165+
impl vortex_array::matcher::OwnedMatcher for vortex_array::AnyColumnar
24166+
24167+
pub type vortex_array::AnyColumnar::OwnedMatch = vortex_array::Columnar
24168+
24169+
pub fn vortex_array::AnyColumnar::maybe_match(array: vortex_array::ArrayRef) -> core::option::Option<Self::OwnedMatch>
24170+
2411124171
#[repr(transparent)] pub struct vortex_array::ArrayAdapter<V: vortex_array::vtable::VTable>(_)
2411224172

2411324173
impl<V: vortex_array::vtable::VTable> vortex_array::ArrayAdapter<V>

vortex-array/src/array/mod.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use crate::expr::stats::Stat;
5151
use crate::expr::stats::StatsProviderExt;
5252
use crate::hash;
5353
use crate::matcher::Matcher;
54+
use crate::matcher::OwnedMatcher;
5455
use crate::optimizer::ArrayOptimizer;
5556
use crate::scalar::Scalar;
5657
use crate::scalar_fn::ReduceNode;
@@ -316,6 +317,18 @@ impl dyn DynArray + '_ {
316317
})
317318
}
318319

320+
/// Returns the array matched by the given owned matcher, consuming the `ArrayRef`.
321+
pub fn into_<M: OwnedMatcher>(self: Arc<Self>) -> M::OwnedMatch {
322+
self.try_into_matched::<M>()
323+
.vortex_expect("Failed to downcast")
324+
}
325+
326+
/// Try to match the given array using an owned matcher, returning the owned matched type
327+
/// if successful.
328+
pub fn try_into_matched<M: OwnedMatcher>(self: Arc<Self>) -> Option<M::OwnedMatch> {
329+
M::maybe_match(self)
330+
}
331+
319332
pub fn as_constant(&self) -> Option<Scalar> {
320333
self.as_opt::<Constant>().map(|a| a.scalar().clone())
321334
}
@@ -1144,3 +1157,37 @@ impl<V: VTable> Matcher for V {
11441157
.map(|adapter| adapter.as_inner())
11451158
}
11461159
}
1160+
1161+
/// Implement an owned matcher for a specific VTable type.
1162+
///
1163+
/// During the migration, this tries both `Array<V>` (new path) and `ArrayAdapter<V>`
1164+
/// (legacy path). Returns `V::Array`.
1165+
impl<V: VTable> OwnedMatcher for V {
1166+
type OwnedMatch = V::Array;
1167+
1168+
fn maybe_match(array: ArrayRef) -> Option<Self::OwnedMatch> {
1169+
if !<V as Matcher>::matches(&*array) {
1170+
return None;
1171+
}
1172+
let any_arc = array.as_any_arc();
1173+
// Try new Array<V> first.
1174+
match any_arc.downcast::<Array<V>>() {
1175+
Ok(typed) => Some(match Arc::try_unwrap(typed) {
1176+
Ok(array) => array.into_inner(),
1177+
Err(arc) => arc.deref().inner().clone(),
1178+
}),
1179+
Err(any_arc) => {
1180+
// Fall back to legacy ArrayAdapter<V>.
1181+
match any_arc.downcast::<ArrayAdapter<V>>() {
1182+
Ok(adapter) => Some(match Arc::try_unwrap(adapter) {
1183+
Ok(adapter) => adapter.into_inner(),
1184+
Err(arc) => arc.as_inner().clone(),
1185+
}),
1186+
Err(_) => {
1187+
vortex_panic!("matches returned true but downcast failed")
1188+
}
1189+
}
1190+
}
1191+
}
1192+
}
1193+
}

vortex-array/src/arrays/dict/vtable/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,9 @@ impl VTable for Dict {
221221
.try_into::<Primitive>()
222222
.ok()
223223
.vortex_expect("must be primitive");
224-
debug_assert!(values.is_canonical());
225-
// TODO: add canonical owned cast.
226-
let values = values.to_canonical()?;
224+
let values = values
225+
.try_into_matched::<AnyCanonical>()
226+
.vortex_expect("must be canonical");
227227

228228
Ok(ExecutionResult::done(
229229
take_canonical(values, &codes, ctx)?.into_array(),

vortex-array/src/arrays/scalar_fn/vtable/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use crate::executor::ExecutionCtx;
3333
use crate::executor::ExecutionResult;
3434
use crate::expr::Expression;
3535
use crate::matcher::Matcher;
36+
use crate::matcher::OwnedMatcher;
3637
use crate::scalar_fn;
3738
use crate::scalar_fn::Arity;
3839
use crate::scalar_fn::ChildName;
@@ -259,6 +260,14 @@ impl Matcher for AnyScalarFn {
259260
}
260261
}
261262

263+
impl OwnedMatcher for AnyScalarFn {
264+
type OwnedMatch = ScalarFnArray;
265+
266+
fn maybe_match(array: ArrayRef) -> Option<Self::OwnedMatch> {
267+
array.try_into::<ScalarFnVTable>().ok()
268+
}
269+
}
270+
262271
/// A matcher that matches a specific scalar function expression.
263272
#[derive(Debug, Default)]
264273
pub struct ExactScalarFn<F: scalar_fn::ScalarFnVTable>(PhantomData<F>);

vortex-array/src/canonical.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use crate::dtype::PType;
5151
use crate::match_each_decimal_value_type;
5252
use crate::match_each_native_ptype;
5353
use crate::matcher::Matcher;
54+
use crate::matcher::OwnedMatcher;
5455
use crate::validity::Validity;
5556

5657
/// An enum capturing the default uncompressed encodings for each [Vortex type](DType).
@@ -1030,6 +1031,56 @@ impl Matcher for AnyCanonical {
10301031
}
10311032
}
10321033

1034+
impl OwnedMatcher for AnyCanonical {
1035+
type OwnedMatch = Canonical;
1036+
1037+
fn maybe_match(array: ArrayRef) -> Option<Self::OwnedMatch> {
1038+
if !<AnyCanonical as Matcher>::matches(&*array) {
1039+
return None;
1040+
}
1041+
let array = match array.try_into::<Null>() {
1042+
Ok(a) => return Some(Canonical::Null(a)),
1043+
Err(array) => array,
1044+
};
1045+
let array = match array.try_into::<Bool>() {
1046+
Ok(a) => return Some(Canonical::Bool(a)),
1047+
Err(array) => array,
1048+
};
1049+
let array = match array.try_into::<Primitive>() {
1050+
Ok(a) => return Some(Canonical::Primitive(a)),
1051+
Err(array) => array,
1052+
};
1053+
let array = match array.try_into::<Decimal>() {
1054+
Ok(a) => return Some(Canonical::Decimal(a)),
1055+
Err(array) => array,
1056+
};
1057+
let array = match array.try_into::<Struct>() {
1058+
Ok(a) => return Some(Canonical::Struct(a)),
1059+
Err(array) => array,
1060+
};
1061+
let array = match array.try_into::<ListView>() {
1062+
Ok(a) => return Some(Canonical::List(a)),
1063+
Err(array) => array,
1064+
};
1065+
let array = match array.try_into::<FixedSizeList>() {
1066+
Ok(a) => return Some(Canonical::FixedSizeList(a)),
1067+
Err(array) => array,
1068+
};
1069+
let array = match array.try_into::<VarBinView>() {
1070+
Ok(a) => return Some(Canonical::VarBinView(a)),
1071+
Err(array) => array,
1072+
};
1073+
let array = match array.try_into::<Variant>() {
1074+
Ok(a) => return Some(Canonical::Variant(a)),
1075+
Err(array) => array,
1076+
};
1077+
match array.try_into::<Extension>() {
1078+
Ok(a) => Some(Canonical::Extension(a)),
1079+
Err(_) => None,
1080+
}
1081+
}
1082+
}
1083+
10331084
#[cfg(test)]
10341085
mod test {
10351086
use std::sync::Arc;

vortex-array/src/columnar.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::arrays::Constant;
1616
use crate::arrays::ConstantArray;
1717
use crate::dtype::DType;
1818
use crate::matcher::Matcher;
19+
use crate::matcher::OwnedMatcher;
1920
use crate::scalar::Scalar;
2021

2122
/// Represents a columnnar array of data, either in canonical form or as a constant array.
@@ -110,3 +111,16 @@ impl Matcher for AnyColumnar {
110111
}
111112
}
112113
}
114+
115+
impl OwnedMatcher for AnyColumnar {
116+
type OwnedMatch = Columnar;
117+
118+
fn maybe_match(array: ArrayRef) -> Option<Self::OwnedMatch> {
119+
match array.try_into::<Constant>() {
120+
Ok(constant) => Some(Columnar::Constant(constant)),
121+
Err(array) => {
122+
<AnyCanonical as OwnedMatcher>::maybe_match(array).map(Columnar::Canonical)
123+
}
124+
}
125+
}
126+
}

vortex-array/src/matcher.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
use crate::ArrayRef;
45
use crate::DynArray;
56

6-
/// Trait for matching array types.
7+
/// Trait for matching array types by reference.
78
pub trait Matcher {
89
type Match<'a>;
910

10-
/// Check if the given array matches this matcher type
11+
/// Check if the given array matches this matcher type.
1112
fn matches(array: &dyn DynArray) -> bool {
1213
Self::try_match(array).is_some()
1314
}
@@ -16,6 +17,14 @@ pub trait Matcher {
1617
fn try_match<'a>(array: &'a dyn DynArray) -> Option<Self::Match<'a>>;
1718
}
1819

20+
/// Trait for matching array types by owned value.
21+
pub trait OwnedMatcher: Matcher {
22+
type OwnedMatch;
23+
24+
/// Try to match the given array, returning the owned matched type if successful.
25+
fn maybe_match(array: ArrayRef) -> Option<Self::OwnedMatch>;
26+
}
27+
1928
/// Matches any array type (wildcard matcher)
2029
#[derive(Debug)]
2130
pub struct AnyArray;
@@ -33,3 +42,12 @@ impl Matcher for AnyArray {
3342
Some(array)
3443
}
3544
}
45+
46+
impl OwnedMatcher for AnyArray {
47+
type OwnedMatch = ArrayRef;
48+
49+
#[inline(always)]
50+
fn maybe_match(array: ArrayRef) -> Option<Self::OwnedMatch> {
51+
Some(array)
52+
}
53+
}

0 commit comments

Comments
 (0)