use std::sync::Arc;
use arrow::datatypes::Schema;
use datafusion_common::{Result, ScalarValue, tree_node::Transformed};
use datafusion_expr::Operator;
use crate::PhysicalExpr;
use crate::expressions::{BinaryExpr, InListExpr, Literal, NotExpr, in_list, lit};
#[deprecated(
since = "53.0.0",
note = "This function will be made private in a future release, please file an issue if you have a reason for keeping it public."
)]
pub fn simplify_not_expr(
expr: Arc<dyn PhysicalExpr>,
schema: &Schema,
) -> Result<Transformed<Arc<dyn PhysicalExpr>>> {
let not_expr = match expr.as_any().downcast_ref::<NotExpr>() {
Some(not_expr) => not_expr,
None => return Ok(Transformed::no(expr)),
};
let inner_expr = not_expr.arg();
if let Some(inner_not) = inner_expr.as_any().downcast_ref::<NotExpr>() {
return Ok(Transformed::yes(Arc::clone(inner_not.arg())));
}
if let Some(literal) = inner_expr.as_any().downcast_ref::<Literal>() {
if let ScalarValue::Boolean(Some(val)) = literal.value() {
return Ok(Transformed::yes(lit(ScalarValue::Boolean(Some(!val)))));
}
if let ScalarValue::Boolean(None) = literal.value() {
return Ok(Transformed::yes(lit(ScalarValue::Boolean(None))));
}
}
if let Some(in_list_expr) = inner_expr.as_any().downcast_ref::<InListExpr>() {
let negated = !in_list_expr.negated();
let new_in_list = in_list(
Arc::clone(in_list_expr.expr()),
in_list_expr.list().to_vec(),
&negated,
schema,
)?;
return Ok(Transformed::yes(new_in_list));
}
if let Some(binary_expr) = inner_expr.as_any().downcast_ref::<BinaryExpr>() {
if let Some(negated_op) = binary_expr.op().negate() {
let new_binary = Arc::new(BinaryExpr::new(
Arc::clone(binary_expr.left()),
negated_op,
Arc::clone(binary_expr.right()),
));
return Ok(Transformed::yes(new_binary));
}
match binary_expr.op() {
Operator::And => {
let not_left: Arc<dyn PhysicalExpr> =
Arc::new(NotExpr::new(Arc::clone(binary_expr.left())));
let not_right: Arc<dyn PhysicalExpr> =
Arc::new(NotExpr::new(Arc::clone(binary_expr.right())));
let new_binary =
Arc::new(BinaryExpr::new(not_left, Operator::Or, not_right));
return Ok(Transformed::yes(new_binary));
}
Operator::Or => {
let not_left: Arc<dyn PhysicalExpr> =
Arc::new(NotExpr::new(Arc::clone(binary_expr.left())));
let not_right: Arc<dyn PhysicalExpr> =
Arc::new(NotExpr::new(Arc::clone(binary_expr.right())));
let new_binary =
Arc::new(BinaryExpr::new(not_left, Operator::And, not_right));
return Ok(Transformed::yes(new_binary));
}
_ => {}
}
}
Ok(Transformed::no(expr))
}