in datafusion/core/src/physical_optimizer/pruning.rs [521:592]
fn rewrite_expr_to_prunable(
column_expr: &PhysicalExprRef,
op: Operator,
scalar_expr: &PhysicalExprRef,
schema: DFSchema,
) -> Result<(PhysicalExprRef, Operator, PhysicalExprRef)> {
if !is_compare_op(op) {
return plan_err!("rewrite_expr_to_prunable only support compare expression");
}
let column_expr_any = column_expr.as_any();
if column_expr_any
.downcast_ref::<phys_expr::Column>()
.is_some()
{
// `col op lit()`
Ok((column_expr.clone(), op, scalar_expr.clone()))
} else if let Some(cast) = column_expr_any.downcast_ref::<phys_expr::CastExpr>() {
// `cast(col) op lit()`
let arrow_schema: SchemaRef = schema.clone().into();
let from_type = cast.expr().data_type(&arrow_schema)?;
verify_support_type_for_prune(&from_type, cast.cast_type())?;
let (left, op, right) =
rewrite_expr_to_prunable(cast.expr(), op, scalar_expr, schema)?;
let left = Arc::new(phys_expr::CastExpr::new(
left,
cast.cast_type().clone(),
None,
));
Ok((left, op, right))
} else if let Some(try_cast) =
column_expr_any.downcast_ref::<phys_expr::TryCastExpr>()
{
// `try_cast(col) op lit()`
let arrow_schema: SchemaRef = schema.clone().into();
let from_type = try_cast.expr().data_type(&arrow_schema)?;
verify_support_type_for_prune(&from_type, try_cast.cast_type())?;
let (left, op, right) =
rewrite_expr_to_prunable(try_cast.expr(), op, scalar_expr, schema)?;
let left = Arc::new(phys_expr::TryCastExpr::new(
left,
try_cast.cast_type().clone(),
));
Ok((left, op, right))
} else if let Some(neg) = column_expr_any.downcast_ref::<phys_expr::NegativeExpr>() {
// `-col > lit()` --> `col < -lit()`
let (left, op, right) =
rewrite_expr_to_prunable(neg.arg(), op, scalar_expr, schema)?;
let right = Arc::new(phys_expr::NegativeExpr::new(right));
Ok((left, reverse_operator(op)?, right))
} else if let Some(not) = column_expr_any.downcast_ref::<phys_expr::NotExpr>() {
// `!col = true` --> `col = !true`
if op != Operator::Eq && op != Operator::NotEq {
return plan_err!("Not with operator other than Eq / NotEq is not supported");
}
if not
.arg()
.as_any()
.downcast_ref::<phys_expr::Column>()
.is_some()
{
let left = not.arg().clone();
let right = Arc::new(phys_expr::NotExpr::new(scalar_expr.clone()));
Ok((left, reverse_operator(op)?, right))
} else {
plan_err!("Not with complex expression {column_expr:?} is not supported")
}
} else {
plan_err!("column expression {column_expr:?} is not supported")
}
}