use arrow::array::{ArrayRef, Datum};
use arrow::error::ArrowError;
use arrow_array::BooleanArray;
use datafusion_common::{Result, ScalarValue};
use datafusion_expr::ColumnarValue;
use std::sync::Arc;
pub(crate) fn apply(
lhs: &ColumnarValue,
rhs: &ColumnarValue,
f: impl Fn(&dyn Datum, &dyn Datum) -> Result<ArrayRef, ArrowError>,
) -> Result<ColumnarValue> {
match (&lhs, &rhs) {
(ColumnarValue::Array(left), ColumnarValue::Array(right)) => {
Ok(ColumnarValue::Array(f(&left.as_ref(), &right.as_ref())?))
}
(ColumnarValue::Scalar(left), ColumnarValue::Array(right)) => Ok(
ColumnarValue::Array(f(&left.to_scalar()?, &right.as_ref())?),
),
(ColumnarValue::Array(left), ColumnarValue::Scalar(right)) => Ok(
ColumnarValue::Array(f(&left.as_ref(), &right.to_scalar()?)?),
),
(ColumnarValue::Scalar(left), ColumnarValue::Scalar(right)) => {
let array = f(&left.to_scalar()?, &right.to_scalar()?)?;
let scalar = ScalarValue::try_from_array(array.as_ref(), 0)?;
Ok(ColumnarValue::Scalar(scalar))
}
}
}
pub(crate) fn apply_cmp(
lhs: &ColumnarValue,
rhs: &ColumnarValue,
f: impl Fn(&dyn Datum, &dyn Datum) -> Result<BooleanArray, ArrowError>,
) -> Result<ColumnarValue> {
apply(lhs, rhs, |l, r| Ok(Arc::new(f(l, r)?)))
}