Skip to content

Commit b03c1dd

Browse files
committed
Expressions
Signed-off-by: Nicholas Gates <[email protected]>
1 parent cedbb4b commit b03c1dd

File tree

15 files changed

+267
-480
lines changed

15 files changed

+267
-480
lines changed

vortex-array/src/compute/like.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

44
use std::any::Any;
5+
use std::fmt::Display;
6+
use std::fmt::Formatter;
57
use std::sync::LazyLock;
68

79
use arcref::ArcRef;
@@ -150,6 +152,19 @@ pub struct LikeOptions {
150152
pub case_insensitive: bool,
151153
}
152154

155+
impl Display for LikeOptions {
156+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
157+
if self.negated {
158+
write!(f, "NOT ")?;
159+
}
160+
if self.case_insensitive {
161+
write!(f, "ILIKE")
162+
} else {
163+
write!(f, "LIKE")
164+
}
165+
}
166+
}
167+
153168
impl Options for LikeOptions {
154169
fn as_any(&self) -> &dyn Any {
155170
self

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,13 @@ use crate::expr::ChildName;
2525
use crate::expr::ExecutionArgs;
2626
use crate::expr::ExprId;
2727
use crate::expr::Expression;
28-
use crate::expr::ScalarFnExprExt;
2928
use crate::expr::StatsCatalog;
3029
use crate::expr::VTable;
3130
use crate::expr::VTableExt;
3231
use crate::expr::exprs::binary::eq;
3332
use crate::expr::exprs::literal::lit;
3433
use crate::expr::functions::EmptyOptions;
3534
use crate::expr::stats::Stat;
36-
use crate::scalar_fns::is_null;
3735

3836
/// Expression that checks for null values.
3937
pub struct IsNull;

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

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ use vortex_dtype::DType;
88
use vortex_error::VortexResult;
99
use vortex_error::vortex_bail;
1010
use vortex_proto::expr as pb;
11+
use vortex_vector::Datum;
1112

1213
use crate::ArrayRef;
1314
use crate::compute::LikeOptions;
1415
use crate::compute::like as like_compute;
16+
use crate::expr::Arity;
1517
use crate::expr::ChildName;
18+
use crate::expr::ExecutionArgs;
1619
use crate::expr::ExprId;
1720
use crate::expr::Expression;
18-
use crate::expr::ExpressionView;
1921
use crate::expr::VTable;
2022
use crate::expr::VTableExt;
2123

@@ -39,22 +41,16 @@ impl VTable for Like {
3941
))
4042
}
4143

42-
fn deserialize(&self, metadata: &[u8]) -> VortexResult<Option<Self::Options>> {
44+
fn deserialize(&self, metadata: &[u8]) -> VortexResult<Self::Options> {
4345
let opts = pb::LikeOpts::decode(metadata)?;
44-
Ok(Some(LikeOptions {
46+
Ok(LikeOptions {
4547
negated: opts.negated,
4648
case_insensitive: opts.case_insensitive,
47-
}))
49+
})
4850
}
4951

50-
fn validate(&self, expr: &ExpressionView<Self>) -> VortexResult<()> {
51-
if expr.children().len() != 2 {
52-
vortex_bail!(
53-
"Like expression requires exactly 2 children, got {}",
54-
expr.children().len()
55-
);
56-
}
57-
Ok(())
52+
fn arity(&self, _options: &Self::Options) -> Arity {
53+
Arity::Exact(2)
5854
}
5955

6056
fn child_name(&self, _instance: &Self::Options, child_idx: usize) -> ChildName {
@@ -65,22 +61,27 @@ impl VTable for Like {
6561
}
6662
}
6763

68-
fn fmt_sql(&self, expr: &ExpressionView<Self>, f: &mut Formatter<'_>) -> std::fmt::Result {
64+
fn fmt_sql(
65+
&self,
66+
options: &Self::Options,
67+
expr: &Expression,
68+
f: &mut Formatter<'_>,
69+
) -> std::fmt::Result {
6970
expr.child(0).fmt_sql(f)?;
70-
if expr.data().negated {
71+
if options.negated {
7172
write!(f, " not")?;
7273
}
73-
if expr.data().case_insensitive {
74+
if options.case_insensitive {
7475
write!(f, " ilike ")?;
7576
} else {
7677
write!(f, " like ")?;
7778
}
7879
expr.child(1).fmt_sql(f)
7980
}
8081

81-
fn return_dtype(&self, expr: &ExpressionView<Self>, scope: &DType) -> VortexResult<DType> {
82-
let input = expr.children()[0].return_dtype(scope)?;
83-
let pattern = expr.children()[1].return_dtype(scope)?;
82+
fn return_dtype(&self, _options: &Self::Options, arg_dtypes: &[DType]) -> VortexResult<DType> {
83+
let input = &arg_dtypes[0];
84+
let pattern = &arg_dtypes[1];
8485

8586
if !input.is_utf8() {
8687
vortex_bail!("LIKE expression requires UTF8 input dtype, got {}", input);
@@ -97,10 +98,19 @@ impl VTable for Like {
9798
))
9899
}
99100

100-
fn evaluate(&self, expr: &ExpressionView<Self>, scope: &ArrayRef) -> VortexResult<ArrayRef> {
101+
fn evaluate(
102+
&self,
103+
options: &Self::Options,
104+
expr: &Expression,
105+
scope: &ArrayRef,
106+
) -> VortexResult<ArrayRef> {
101107
let child = expr.child(0).evaluate(scope)?;
102108
let pattern = expr.child(1).evaluate(scope)?;
103-
like_compute(&child, &pattern, *expr.data())
109+
like_compute(&child, &pattern, *options)
110+
}
111+
112+
fn execute(&self, data: &Self::Options, args: ExecutionArgs) -> VortexResult<Datum> {
113+
todo!()
104114
}
105115

106116
fn is_null_sensitive(&self, _instance: &Self::Options) -> bool {

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

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

44
use std::fmt::Formatter;
5+
use std::ops::BitOr;
56

67
use vortex_dtype::DType;
78
use vortex_error::VortexResult;
89
use vortex_error::vortex_bail;
10+
use vortex_vector::Datum;
911

1012
use crate::ArrayRef;
1113
use crate::compute::list_contains as compute_list_contains;
14+
use crate::expr::Arity;
1215
use crate::expr::ChildName;
16+
use crate::expr::ExecutionArgs;
1317
use crate::expr::ExprId;
1418
use crate::expr::Expression;
15-
use crate::expr::ExpressionView;
1619
use crate::expr::StatsCatalog;
1720
use crate::expr::VTable;
1821
use crate::expr::VTableExt;
@@ -22,11 +25,12 @@ use crate::expr::exprs::binary::lt;
2225
use crate::expr::exprs::binary::or;
2326
use crate::expr::exprs::literal::Literal;
2427
use crate::expr::exprs::literal::lit;
28+
use crate::expr::functions::EmptyOptions;
2529

2630
pub struct ListContains;
2731

2832
impl VTable for ListContains {
29-
type Options = ();
33+
type Options = EmptyOptions;
3034

3135
fn id(&self) -> ExprId {
3236
ExprId::from("vortex.list.contains")
@@ -36,18 +40,12 @@ impl VTable for ListContains {
3640
Ok(Some(vec![]))
3741
}
3842

39-
fn deserialize(&self, _metadata: &[u8]) -> VortexResult<Option<Self::Options>> {
40-
Ok(Some(()))
43+
fn deserialize(&self, _metadata: &[u8]) -> VortexResult<Self::Options> {
44+
Ok(EmptyOptions)
4145
}
4246

43-
fn validate(&self, expr: &ExpressionView<Self>) -> VortexResult<()> {
44-
if expr.children().len() != 2 {
45-
vortex_bail!(
46-
"ListContains expression requires exactly 2 children, got {}",
47-
expr.children().len()
48-
);
49-
}
50-
Ok(())
47+
fn arity(&self, _options: &Self::Options) -> Arity {
48+
Arity::Exact(2)
5149
}
5250

5351
fn child_name(&self, _instance: &Self::Options, child_idx: usize) -> ChildName {
@@ -60,18 +58,22 @@ impl VTable for ListContains {
6058
),
6159
}
6260
}
63-
64-
fn fmt_sql(&self, expr: &ExpressionView<Self>, f: &mut Formatter<'_>) -> std::fmt::Result {
61+
fn fmt_sql(
62+
&self,
63+
_options: &Self::Options,
64+
expr: &Expression,
65+
f: &mut Formatter<'_>,
66+
) -> std::fmt::Result {
6567
write!(f, "contains(")?;
6668
expr.child(0).fmt_sql(f)?;
6769
write!(f, ", ")?;
6870
expr.child(1).fmt_sql(f)?;
6971
write!(f, ")")
7072
}
7173

72-
fn return_dtype(&self, expr: &ExpressionView<Self>, scope: &DType) -> VortexResult<DType> {
73-
let list_dtype = expr.child(0).return_dtype(scope)?;
74-
let value_dtype = expr.child(1).return_dtype(scope)?;
74+
fn return_dtype(&self, _options: &Self::Options, arg_dtypes: &[DType]) -> VortexResult<DType> {
75+
let list_dtype = &arg_dtypes[0];
76+
let needle_dtype = &arg_dtypes[0];
7577

7678
let nullability = match list_dtype {
7779
DType::List(_, list_nullability) => list_nullability,
@@ -81,38 +83,52 @@ impl VTable for ListContains {
8183
list_dtype
8284
);
8385
}
84-
} | value_dtype.nullability();
86+
}
87+
.bitor(needle_dtype.nullability());
8588

8689
Ok(DType::Bool(nullability))
8790
}
8891

89-
fn evaluate(&self, expr: &ExpressionView<Self>, scope: &ArrayRef) -> VortexResult<ArrayRef> {
92+
fn evaluate(
93+
&self,
94+
_options: &Self::Options,
95+
expr: &Expression,
96+
scope: &ArrayRef,
97+
) -> VortexResult<ArrayRef> {
9098
let list_array = expr.child(0).evaluate(scope)?;
9199
let value_array = expr.child(1).evaluate(scope)?;
92100
compute_list_contains(list_array.as_ref(), value_array.as_ref())
93101
}
94102

103+
fn execute(&self, _data: &Self::Options, _args: ExecutionArgs) -> VortexResult<Datum> {
104+
todo!()
105+
}
106+
95107
fn stat_falsification(
96108
&self,
97-
expr: &ExpressionView<Self>,
109+
_options: &Self::Options,
110+
expr: &Expression,
98111
catalog: &dyn StatsCatalog,
99112
) -> Option<Expression> {
113+
let list = expr.child(0);
114+
let needle = expr.child(1);
115+
100116
// falsification(contains([1,2,5], x)) =>
101117
// falsification(x != 1) and falsification(x != 2) and falsification(x != 5)
102-
let min = expr.list().stat_min(catalog)?;
103-
let max = expr.list().stat_max(catalog)?;
118+
let min = list.stat_min(catalog)?;
119+
let max = list.stat_max(catalog)?;
104120
// If the list is constant when we can compare each element to the value
105121
if min == max {
106122
let list_ = min
107123
.as_opt::<Literal>()
108-
.and_then(|l| l.data().as_list_opt())
124+
.and_then(|l| l.as_list_opt())
109125
.and_then(|l| l.elements())?;
110126
if list_.is_empty() {
111127
// contains([], x) is always false.
112128
return Some(lit(true));
113129
}
114-
let value_max = expr.needle().stat_max(catalog)?;
115-
let value_min = expr.needle().stat_min(catalog)?;
130+
let value_max = needle.stat_max(catalog)?;
131+
let value_min = needle.stat_min(catalog)?;
116132

117133
return list_
118134
.iter()
@@ -143,17 +159,7 @@ impl VTable for ListContains {
143159
/// let expr = list_contains(root(), lit(42));
144160
/// ```
145161
pub fn list_contains(list: Expression, value: Expression) -> Expression {
146-
ListContains.new_expr((), [list, value])
147-
}
148-
149-
impl ExpressionView<'_, ListContains> {
150-
pub fn list(&self) -> &Expression {
151-
&self.children()[0]
152-
}
153-
154-
pub fn needle(&self) -> &Expression {
155-
&self.children()[1]
156-
}
162+
ListContains.new_expr(EmptyOptions, [list, value])
157163
}
158164

159165
#[cfg(test)]

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ impl VTable for Literal {
6565
fn fmt_sql(
6666
&self,
6767
scalar: &Scalar,
68-
expr: &Expression,
68+
_expr: &Expression,
6969
f: &mut Formatter<'_>,
7070
) -> std::fmt::Result {
71-
write!(f, "{}", expr.data())
71+
write!(f, "{}", scalar)
7272
}
7373

7474
fn return_dtype(&self, options: &Self::Options, _arg_dtypes: &[DType]) -> VortexResult<DType> {

0 commit comments

Comments
 (0)