Skip to content

Commit 80e01eb

Browse files
feat[scalar_fn]: is_null (#5601)
Signed-off-by: Joe Isaacs <[email protected]>
1 parent 168982b commit 80e01eb

File tree

8 files changed

+154
-1
lines changed

8 files changed

+154
-1
lines changed

vortex-array/src/expr/exprs/binary.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ pub fn eq(lhs: Expression, rhs: Expression) -> Expression {
319319
/// ## Example usage
320320
///
321321
/// ```
322-
/// # use vortex_array::arrays::{BoolArray, PrimitiveArray };
322+
/// # use vortex_array::arrays::{BoolArray, PrimitiveArray};
323323
/// # use vortex_array::{IntoArray, ToCanonical};
324324
/// # use vortex_array::validity::Validity;
325325
/// # use vortex_buffer::buffer;

vortex-array/src/expr/exprs/is_null.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use std::fmt::Formatter;
55
use std::ops::Not;
66

7+
use is_null::IsNullFn;
78
use vortex_dtype::DType;
89
use vortex_dtype::Nullability;
910
use vortex_error::VortexExpect;
@@ -24,12 +25,15 @@ use crate::expr::ExecutionArgs;
2425
use crate::expr::ExprId;
2526
use crate::expr::Expression;
2627
use crate::expr::ExpressionView;
28+
use crate::expr::ScalarFnExprExt;
2729
use crate::expr::StatsCatalog;
2830
use crate::expr::VTable;
2931
use crate::expr::VTableExt;
3032
use crate::expr::exprs::binary::eq;
3133
use crate::expr::exprs::literal::lit;
34+
use crate::expr::functions::EmptyOptions;
3235
use crate::expr::stats::Stat;
36+
use crate::scalar_fns::is_null;
3337

3438
/// Expression that checks for null values.
3539
pub struct IsNull;
@@ -110,6 +114,10 @@ impl VTable for IsNull {
110114
fn is_fallible(&self, _instance: &Self::Instance) -> bool {
111115
false
112116
}
117+
118+
fn expr_v2(&self, view: &ExpressionView<Self>) -> VortexResult<Expression> {
119+
ScalarFnExprExt::try_new_expr(&IsNullFn, EmptyOptions, view.children().clone())
120+
}
113121
}
114122

115123
/// Creates an expression that checks for null values.

vortex-array/src/expr/exprs/not.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ use crate::expr::ExecutionArgs;
1717
use crate::expr::ExprId;
1818
use crate::expr::Expression;
1919
use crate::expr::ExpressionView;
20+
use crate::expr::ScalarFnExprExt;
2021
use crate::expr::VTable;
2122
use crate::expr::VTableExt;
23+
use crate::expr::functions::EmptyOptions;
24+
use crate::scalar_fns::not;
2225

2326
/// Expression that logically inverts boolean values.
2427
pub struct Not;
@@ -89,6 +92,10 @@ impl VTable for Not {
8992
fn is_fallible(&self, _instance: &Self::Instance) -> bool {
9093
false
9194
}
95+
96+
fn expr_v2(&self, view: &ExpressionView<Self>) -> VortexResult<Expression> {
97+
ScalarFnExprExt::try_new_expr(&not::NotFn, EmptyOptions, view.children().clone())
98+
}
9299
}
93100

94101
/// Creates an expression that logically inverts boolean values.

vortex-array/src/expr/vtable.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::fmt::Display;
88
use std::fmt::Formatter;
99
use std::hash::Hash;
1010
use std::hash::Hasher;
11+
use std::ops::Deref;
1112
use std::sync::Arc;
1213

1314
use arcref::ArcRef;
@@ -152,6 +153,13 @@ pub trait VTable: 'static + Sized + Send + Sync {
152153
_ = instance;
153154
true
154155
}
156+
157+
/// **For internal usage**. This will return an Expression that is part of the
158+
/// expression -> new_expression migration.
159+
#[doc(hidden)]
160+
fn expr_v2(&self, expr: &ExpressionView<Self>) -> VortexResult<Expression> {
161+
Ok(expr.deref().clone())
162+
}
155163
}
156164

157165
/// Arguments for expression execution.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use std::ops::Not;
5+
6+
use vortex_dtype::DType;
7+
use vortex_dtype::Nullability::NonNullable;
8+
use vortex_error::VortexResult;
9+
use vortex_mask::Mask;
10+
use vortex_vector::Datum;
11+
use vortex_vector::ScalarOps;
12+
use vortex_vector::Vector;
13+
use vortex_vector::VectorOps;
14+
use vortex_vector::bool::BoolVector;
15+
16+
use crate::expr::ChildName;
17+
use crate::expr::ExprId;
18+
use crate::expr::functions::ArgName;
19+
use crate::expr::functions::Arity;
20+
use crate::expr::functions::EmptyOptions;
21+
use crate::expr::functions::ExecutionArgs;
22+
use crate::expr::functions::VTable;
23+
24+
pub struct IsNullFn;
25+
impl VTable for IsNullFn {
26+
type Options = EmptyOptions;
27+
28+
fn id(&self) -> ExprId {
29+
ExprId::new_ref("is_null")
30+
}
31+
32+
fn arity(&self, _: &Self::Options) -> Arity {
33+
Arity::Fixed(1)
34+
}
35+
36+
fn arg_name(&self, _: &Self::Options, arg_idx: usize) -> ArgName {
37+
match arg_idx {
38+
0 => ChildName::from("input"),
39+
_ => unreachable!("Invalid child index {} for IsNull expression", arg_idx),
40+
}
41+
}
42+
43+
fn return_dtype(&self, _options: &Self::Options, _arg_types: &[DType]) -> VortexResult<DType> {
44+
Ok(DType::Bool(NonNullable))
45+
}
46+
47+
fn execute(&self, _: &Self::Options, args: &ExecutionArgs) -> VortexResult<Datum> {
48+
Ok(match args.input_datums(0) {
49+
Datum::Scalar(sc) => Datum::Scalar(sc.is_invalid().into()),
50+
Datum::Vector(vec) => Vector::Bool(BoolVector::new(
51+
vec.validity().to_bit_buffer().not(),
52+
Mask::AllTrue(vec.len()),
53+
))
54+
.into(),
55+
})
56+
}
57+
}

vortex-array/src/scalar_fns/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use crate::expr::Expression;
1919
use crate::expr::ScalarFnExprExt;
2020

2121
pub mod cast;
22+
pub mod is_null;
23+
pub mod not;
2224

2325
/// A collection of built-in scalar functions that can be applied to expressions or arrays.
2426
pub trait BuiltinScalarFns: Sized {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use vortex_compute::logical::LogicalNot;
5+
use vortex_dtype::DType;
6+
use vortex_error::VortexResult;
7+
use vortex_error::vortex_bail;
8+
use vortex_vector::Datum;
9+
use vortex_vector::Scalar;
10+
use vortex_vector::Vector;
11+
use vortex_vector::bool::BoolScalar;
12+
13+
use crate::expr::ChildName;
14+
use crate::expr::functions::ArgName;
15+
use crate::expr::functions::Arity;
16+
use crate::expr::functions::EmptyOptions;
17+
use crate::expr::functions::ExecutionArgs;
18+
use crate::expr::functions::FunctionId;
19+
use crate::expr::functions::NullHandling;
20+
use crate::expr::functions::VTable;
21+
22+
pub struct NotFn;
23+
impl VTable for NotFn {
24+
type Options = EmptyOptions;
25+
26+
fn id(&self) -> FunctionId {
27+
FunctionId::from("vortex.not")
28+
}
29+
30+
fn arity(&self, _: &Self::Options) -> Arity {
31+
Arity::Fixed(1)
32+
}
33+
34+
fn null_handling(&self, _options: &Self::Options) -> NullHandling {
35+
NullHandling::Propagate
36+
}
37+
38+
fn arg_name(&self, _: &Self::Options, arg_idx: usize) -> ArgName {
39+
match arg_idx {
40+
0 => ChildName::from("input"),
41+
_ => unreachable!("Invalid child index {} for Not expression", arg_idx),
42+
}
43+
}
44+
45+
fn return_dtype(&self, _options: &Self::Options, arg_types: &[DType]) -> VortexResult<DType> {
46+
let child_dtype = &arg_types[0];
47+
if !matches!(child_dtype, DType::Bool(_)) {
48+
vortex_bail!(
49+
"Not expression expects a boolean child, got: {}",
50+
child_dtype
51+
);
52+
}
53+
Ok(child_dtype.clone())
54+
}
55+
56+
fn execute(&self, _: &Self::Options, args: &ExecutionArgs) -> VortexResult<Datum> {
57+
Ok(match args.input_datums(0) {
58+
Datum::Scalar(Scalar::Bool(sc)) => {
59+
Datum::Scalar(BoolScalar::new(sc.value().map(|v| !v)).into())
60+
}
61+
Datum::Vector(Vector::Bool(vec)) => Datum::Vector(vec.clone().not().into()),
62+
_ => unreachable!("Not expects a boolean"),
63+
})
64+
}
65+
}

vortex-vector/src/bool/scalar.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,9 @@ impl From<BoolScalar> for Scalar {
4343
Scalar::Bool(val)
4444
}
4545
}
46+
47+
impl From<bool> for Scalar {
48+
fn from(value: bool) -> Self {
49+
BoolScalar::new(Some(value)).into()
50+
}
51+
}

0 commit comments

Comments
 (0)