1use vortex_error::VortexResult;
13
14use crate::ArrayRef;
15use crate::IntoArray;
16use crate::arrays::ConstantArray;
17use crate::arrays::InterleaveArray;
18use crate::dtype::DType;
19use crate::dtype::FieldName;
20use crate::expr::Expression;
21use crate::optimizer::ArrayOptimizer;
22use crate::scalar::Scalar;
23use crate::scalar_fn::EmptyOptions;
24use crate::scalar_fn::ScalarFnVTableExt;
25use crate::scalar_fn::fns::between::Between;
26use crate::scalar_fn::fns::between::BetweenOptions;
27use crate::scalar_fn::fns::binary::Binary;
28use crate::scalar_fn::fns::cast::Cast;
29use crate::scalar_fn::fns::fill_null::FillNull;
30use crate::scalar_fn::fns::get_item::GetItem;
31use crate::scalar_fn::fns::is_not_null::IsNotNull;
32use crate::scalar_fn::fns::is_null::IsNull;
33use crate::scalar_fn::fns::list_contains::ListContains;
34use crate::scalar_fn::fns::mask::Mask;
35use crate::scalar_fn::fns::not::Not;
36use crate::scalar_fn::fns::operators::Operator;
37use crate::scalar_fn::fns::zip::Zip;
38
39pub trait ExprBuiltins: Sized {
41 fn cast(&self, dtype: DType) -> VortexResult<Expression>;
43
44 fn fill_null(&self, fill_value: Expression) -> VortexResult<Expression>;
46
47 fn get_item(&self, field_name: impl Into<FieldName>) -> VortexResult<Expression>;
49
50 fn is_null(&self) -> VortexResult<Expression>;
52
53 fn is_not_null(&self) -> VortexResult<Expression>;
55
56 fn mask(&self, mask: Expression) -> VortexResult<Expression>;
60
61 fn not(&self) -> VortexResult<Expression>;
63
64 fn list_contains(&self, value: Expression) -> VortexResult<Expression>;
66
67 fn zip(&self, if_true: Expression, if_false: Expression) -> VortexResult<Expression>;
69
70 fn binary(&self, rhs: Expression, op: Operator) -> VortexResult<Expression>;
74}
75
76impl ExprBuiltins for Expression {
77 fn cast(&self, dtype: DType) -> VortexResult<Expression> {
78 Cast.try_new_expr(dtype, [self.clone()])
79 }
80
81 fn fill_null(&self, fill_value: Expression) -> VortexResult<Expression> {
82 FillNull.try_new_expr(EmptyOptions, [self.clone(), fill_value])
83 }
84
85 fn get_item(&self, field_name: impl Into<FieldName>) -> VortexResult<Expression> {
86 GetItem.try_new_expr(field_name.into(), [self.clone()])
87 }
88
89 fn is_null(&self) -> VortexResult<Expression> {
90 IsNull.try_new_expr(EmptyOptions, [self.clone()])
91 }
92
93 fn is_not_null(&self) -> VortexResult<Expression> {
94 IsNotNull.try_new_expr(EmptyOptions, [self.clone()])
95 }
96
97 fn mask(&self, mask: Expression) -> VortexResult<Expression> {
98 Mask.try_new_expr(EmptyOptions, [self.clone(), mask])
99 }
100
101 fn not(&self) -> VortexResult<Expression> {
102 Not.try_new_expr(EmptyOptions, [self.clone()])
103 }
104
105 fn list_contains(&self, value: Expression) -> VortexResult<Expression> {
106 ListContains.try_new_expr(EmptyOptions, [self.clone(), value])
107 }
108
109 fn zip(&self, if_true: Expression, if_false: Expression) -> VortexResult<Expression> {
110 Zip.try_new_expr(EmptyOptions, [if_true, if_false, self.clone()])
111 }
112
113 fn binary(&self, rhs: Expression, op: Operator) -> VortexResult<Expression> {
114 Binary.try_new_expr(op, [self.clone(), rhs])
115 }
116}
117
118pub trait ArrayBuiltins: Sized {
119 fn cast(&self, dtype: DType) -> VortexResult<ArrayRef>;
121
122 fn fill_null(&self, fill_value: impl Into<Scalar>) -> VortexResult<ArrayRef>;
124
125 fn get_item(&self, field_name: impl Into<FieldName>) -> VortexResult<ArrayRef>;
127
128 fn is_null(&self) -> VortexResult<ArrayRef>;
130
131 fn is_not_null(&self) -> VortexResult<ArrayRef>;
133
134 fn mask(self, mask: ArrayRef) -> VortexResult<ArrayRef>;
138
139 fn not(&self) -> VortexResult<ArrayRef>;
141
142 fn zip(&self, if_true: ArrayRef, if_false: ArrayRef) -> VortexResult<ArrayRef>;
144
145 fn interleave(
150 &self,
151 values: impl IntoIterator<Item = ArrayRef>,
152 row_indices: ArrayRef,
153 ) -> VortexResult<ArrayRef>;
154
155 fn list_contains(&self, value: ArrayRef) -> VortexResult<ArrayRef>;
157
158 fn binary(&self, rhs: ArrayRef, op: Operator) -> VortexResult<ArrayRef>;
160
161 fn between(
163 self,
164 lower: ArrayRef,
165 upper: ArrayRef,
166 options: BetweenOptions,
167 ) -> VortexResult<ArrayRef>;
168}
169
170impl ArrayBuiltins for ArrayRef {
171 fn cast(&self, dtype: DType) -> VortexResult<ArrayRef> {
172 if self.dtype() == &dtype {
173 return Ok(self.clone());
174 }
175 Cast::new(self.clone(), dtype).into_array().optimize()
176 }
177
178 fn fill_null(&self, fill_value: impl Into<Scalar>) -> VortexResult<ArrayRef> {
179 let fill_value = fill_value.into();
180 if !self.dtype().is_nullable() {
181 return self.cast(fill_value.dtype().clone());
182 }
183 FillNull::try_new(
184 self.clone(),
185 ConstantArray::new(fill_value, self.len()).into_array(),
186 )?
187 .into_array()
188 .optimize()
189 }
190
191 fn get_item(&self, field_name: impl Into<FieldName>) -> VortexResult<ArrayRef> {
192 GetItem::try_new(self.clone(), field_name)?
193 .into_array()
194 .optimize()
195 }
196
197 fn is_null(&self) -> VortexResult<ArrayRef> {
198 IsNull::new(self.clone()).into_array().optimize()
199 }
200
201 fn is_not_null(&self) -> VortexResult<ArrayRef> {
202 IsNotNull::new(self.clone()).into_array().optimize()
203 }
204
205 fn mask(self, mask: ArrayRef) -> VortexResult<ArrayRef> {
206 Mask::try_new(self, mask)?.into_array().optimize()
207 }
208
209 fn not(&self) -> VortexResult<ArrayRef> {
210 Not::try_new(self.clone())?.into_array().optimize()
211 }
212
213 fn zip(&self, if_true: ArrayRef, if_false: ArrayRef) -> VortexResult<ArrayRef> {
214 Ok(Zip::try_new(if_true, if_false, self.clone())?.into_array())
215 }
216
217 fn interleave(
218 &self,
219 values: impl IntoIterator<Item = ArrayRef>,
220 row_indices: ArrayRef,
221 ) -> VortexResult<ArrayRef> {
222 Ok(
223 InterleaveArray::try_new(values.into_iter().collect(), self.clone(), row_indices)?
224 .into_array(),
225 )
226 }
227
228 fn list_contains(&self, value: ArrayRef) -> VortexResult<ArrayRef> {
229 ListContains::try_new(self.clone(), value)?
230 .into_array()
231 .optimize()
232 }
233
234 fn binary(&self, rhs: ArrayRef, op: Operator) -> VortexResult<ArrayRef> {
235 Binary::try_new(self.clone(), rhs, op)?
236 .into_array()
237 .optimize()
238 }
239
240 fn between(
241 self,
242 lower: ArrayRef,
243 upper: ArrayRef,
244 options: BetweenOptions,
245 ) -> VortexResult<ArrayRef> {
246 Between::try_new(self, lower, upper, options)?
247 .into_array()
248 .optimize()
249 }
250}