use vortex_error::VortexResult;
use crate::ArrayRef;
use crate::IntoArray;
use crate::arrays::ConstantArray;
use crate::arrays::scalar_fn::ScalarFnFactoryExt;
use crate::dtype::DType;
use crate::dtype::FieldName;
use crate::expr::Expression;
use crate::optimizer::ArrayOptimizer;
use crate::scalar::Scalar;
use crate::scalar_fn::EmptyOptions;
use crate::scalar_fn::ScalarFnVTableExt;
use crate::scalar_fn::fns::between::Between;
use crate::scalar_fn::fns::between::BetweenOptions;
use crate::scalar_fn::fns::binary::Binary;
use crate::scalar_fn::fns::cast::Cast;
use crate::scalar_fn::fns::fill_null::FillNull;
use crate::scalar_fn::fns::get_item::GetItem;
use crate::scalar_fn::fns::is_null::IsNull;
use crate::scalar_fn::fns::list_contains::ListContains;
use crate::scalar_fn::fns::mask::Mask;
use crate::scalar_fn::fns::not::Not;
use crate::scalar_fn::fns::operators::Operator;
use crate::scalar_fn::fns::zip::Zip;
pub trait ExprBuiltins: Sized {
fn cast(&self, dtype: DType) -> VortexResult<Expression>;
fn fill_null(&self, fill_value: Expression) -> VortexResult<Expression>;
fn get_item(&self, field_name: impl Into<FieldName>) -> VortexResult<Expression>;
fn is_null(&self) -> VortexResult<Expression>;
fn mask(&self, mask: Expression) -> VortexResult<Expression>;
fn not(&self) -> VortexResult<Expression>;
fn list_contains(&self, value: Expression) -> VortexResult<Expression>;
fn zip(&self, if_true: Expression, if_false: Expression) -> VortexResult<Expression>;
fn binary(&self, rhs: Expression, op: Operator) -> VortexResult<Expression>;
}
impl ExprBuiltins for Expression {
fn cast(&self, dtype: DType) -> VortexResult<Expression> {
Cast.try_new_expr(dtype, [self.clone()])
}
fn fill_null(&self, fill_value: Expression) -> VortexResult<Expression> {
FillNull.try_new_expr(EmptyOptions, [self.clone(), fill_value])
}
fn get_item(&self, field_name: impl Into<FieldName>) -> VortexResult<Expression> {
GetItem.try_new_expr(field_name.into(), [self.clone()])
}
fn is_null(&self) -> VortexResult<Expression> {
IsNull.try_new_expr(EmptyOptions, [self.clone()])
}
fn mask(&self, mask: Expression) -> VortexResult<Expression> {
Mask.try_new_expr(EmptyOptions, [self.clone(), mask])
}
fn not(&self) -> VortexResult<Expression> {
Not.try_new_expr(EmptyOptions, [self.clone()])
}
fn list_contains(&self, value: Expression) -> VortexResult<Expression> {
ListContains.try_new_expr(EmptyOptions, [self.clone(), value])
}
fn zip(&self, if_true: Expression, if_false: Expression) -> VortexResult<Expression> {
Zip.try_new_expr(EmptyOptions, [if_true, if_false, self.clone()])
}
fn binary(&self, rhs: Expression, op: Operator) -> VortexResult<Expression> {
Binary.try_new_expr(op, [self.clone(), rhs])
}
}
pub trait ArrayBuiltins: Sized {
fn cast(&self, dtype: DType) -> VortexResult<ArrayRef>;
fn fill_null(&self, fill_value: impl Into<Scalar>) -> VortexResult<ArrayRef>;
fn get_item(&self, field_name: impl Into<FieldName>) -> VortexResult<ArrayRef>;
fn is_null(&self) -> VortexResult<ArrayRef>;
fn mask(self, mask: ArrayRef) -> VortexResult<ArrayRef>;
fn not(&self) -> VortexResult<ArrayRef>;
fn zip(&self, if_true: ArrayRef, if_false: ArrayRef) -> VortexResult<ArrayRef>;
fn list_contains(&self, value: ArrayRef) -> VortexResult<ArrayRef>;
fn binary(&self, rhs: ArrayRef, op: Operator) -> VortexResult<ArrayRef>;
fn between(
self,
lower: ArrayRef,
upper: ArrayRef,
options: BetweenOptions,
) -> VortexResult<ArrayRef>;
}
impl ArrayBuiltins for ArrayRef {
fn cast(&self, dtype: DType) -> VortexResult<ArrayRef> {
if self.dtype() == &dtype {
return Ok(self.clone());
}
Cast.try_new_array(self.len(), dtype, [self.clone()])?
.optimize()
}
fn fill_null(&self, fill_value: impl Into<Scalar>) -> VortexResult<ArrayRef> {
let fill_value = fill_value.into();
if !self.dtype().is_nullable() {
return self.cast(fill_value.dtype().clone());
}
FillNull
.try_new_array(
self.len(),
EmptyOptions,
[
self.clone(),
ConstantArray::new(fill_value, self.len()).into_array(),
],
)?
.optimize()
}
fn get_item(&self, field_name: impl Into<FieldName>) -> VortexResult<ArrayRef> {
GetItem
.try_new_array(self.len(), field_name.into(), [self.clone()])?
.optimize()
}
fn is_null(&self) -> VortexResult<ArrayRef> {
IsNull
.try_new_array(self.len(), EmptyOptions, [self.clone()])?
.optimize()
}
fn mask(self, mask: ArrayRef) -> VortexResult<ArrayRef> {
Mask.try_new_array(self.len(), EmptyOptions, [self, mask])?
.optimize()
}
fn not(&self) -> VortexResult<ArrayRef> {
Not.try_new_array(self.len(), EmptyOptions, [self.clone()])?
.optimize()
}
fn zip(&self, if_true: ArrayRef, if_false: ArrayRef) -> VortexResult<ArrayRef> {
Zip.try_new_array(self.len(), EmptyOptions, [if_true, if_false, self.clone()])
}
fn list_contains(&self, value: ArrayRef) -> VortexResult<ArrayRef> {
ListContains
.try_new_array(self.len(), EmptyOptions, [self.clone(), value])?
.optimize()
}
fn binary(&self, rhs: ArrayRef, op: Operator) -> VortexResult<ArrayRef> {
Binary
.try_new_array(self.len(), op, [self.clone(), rhs])?
.optimize()
}
fn between(
self,
lower: ArrayRef,
upper: ArrayRef,
options: BetweenOptions,
) -> VortexResult<ArrayRef> {
Between
.try_new_array(self.len(), options, [self, lower, upper])?
.optimize()
}
}