use vortex_dtype::DType;
use vortex_dtype::FieldName;
use vortex_error::VortexResult;
use vortex_session::VortexSession;
use crate::Array;
use crate::ArrayRef;
use crate::ExecutionCtx;
use crate::IntoArray;
use crate::arrays::ConstantArray;
use crate::arrays::ScalarFnArrayExt;
use crate::expr::Between;
use crate::expr::BetweenOptions;
use crate::expr::Cast;
use crate::expr::EmptyOptions;
use crate::expr::Expression;
use crate::expr::FillNull;
use crate::expr::GetItem;
use crate::expr::IsNull;
use crate::expr::Mask;
use crate::expr::Not;
use crate::expr::VTableExt;
use crate::expr::Zip;
use crate::optimizer::ArrayOptimizer;
use crate::scalar::Scalar;
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 zip(&self, if_false: Expression, mask: Expression) -> 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 zip(&self, if_false: Expression, mask: Expression) -> VortexResult<Expression> {
Zip.try_new_expr(EmptyOptions, [self.clone(), if_false, mask])
}
}
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_false: ArrayRef, mask: ArrayRef) -> 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> {
FillNull
.try_new_array(
self.len(),
EmptyOptions,
[
self.clone(),
ConstantArray::new(fill_value.into(), 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_false: ArrayRef, mask: ArrayRef) -> VortexResult<ArrayRef> {
let scalar_fn =
Zip.try_new_array(self.len(), EmptyOptions, [self.clone(), if_false, mask])?;
let mut ctx = ExecutionCtx::new(VortexSession::empty());
scalar_fn.execute::<ArrayRef>(&mut ctx)
}
fn between(
self,
lower: ArrayRef,
upper: ArrayRef,
options: BetweenOptions,
) -> VortexResult<ArrayRef> {
Between
.try_new_array(self.len(), options, [self, lower, upper])?
.optimize()
}
}