optd_datafusion_repr/rules/
filter.rsuse std::collections::HashSet;
use optd_core::nodes::PlanNodeOrGroup;
use optd_core::optimizer::Optimizer;
use optd_core::rules::{Rule, RuleMatcher};
use super::macros::define_rule;
use crate::plan_nodes::{
ArcDfPredNode, ConstantPred, ConstantType, DfNodeType, DfPredType, DfReprPlanNode,
DfReprPredNode, JoinType, LogOpPred, LogOpType, LogicalEmptyRelation, LogicalFilter,
LogicalJoin,
};
use crate::{ArcDfPlanNode, OptimizerExt};
pub(crate) fn simplify_log_expr(log_expr: ArcDfPredNode, changed: &mut bool) -> ArcDfPredNode {
let log_expr = LogOpPred::from_pred_node(log_expr).unwrap();
let op = log_expr.op_type();
let mut new_children_set = HashSet::new();
let mut new_children = Vec::new();
let log_expr_children = log_expr.children();
let children_size = log_expr_children.len();
for child in log_expr_children {
let mut new_child = child;
if let DfPredType::LogOp(_) = new_child.typ {
new_child = simplify_log_expr(new_child, changed);
}
if let DfPredType::Constant(ConstantType::Bool) = new_child.typ {
let data = ConstantPred::from_pred_node(new_child).unwrap().value();
*changed = true;
if data.as_bool() {
if op == LogOpType::And {
continue;
}
if op == LogOpType::Or {
return ConstantPred::bool(true).into_pred_node();
}
unreachable!("no other type in logOp");
}
if op == LogOpType::And {
return ConstantPred::bool(false).into_pred_node();
}
if op == LogOpType::Or {
continue;
}
unreachable!("no other type in logOp");
} else if !new_children_set.contains(&new_child) {
new_children_set.insert(new_child.clone());
new_children.push(new_child);
}
}
if new_children.is_empty() {
if op == LogOpType::And {
return ConstantPred::bool(true).into_pred_node();
}
if op == LogOpType::Or {
return ConstantPred::bool(false).into_pred_node();
}
unreachable!("no other type in logOp");
}
if new_children.len() == 1 {
*changed = true;
return new_children.first().cloned().unwrap().into_pred_node();
}
if children_size != new_children.len() {
*changed = true;
}
LogOpPred::new(op, new_children).into_pred_node()
}
define_rule!(SimplifyFilterRule, apply_simplify_filter, (Filter, child));
fn apply_simplify_filter(
_optimizer: &impl Optimizer<DfNodeType>,
binding: ArcDfPlanNode,
) -> Vec<PlanNodeOrGroup<DfNodeType>> {
let filter = LogicalFilter::from_plan_node(binding).unwrap();
let cond = filter.cond();
match cond.typ {
DfPredType::LogOp(_) => {
let mut changed = false;
let new_log_expr = simplify_log_expr(cond, &mut changed);
if changed {
let filter_node = LogicalFilter::new_unchecked(filter.child(), new_log_expr);
return vec![filter_node.into_plan_node().into()];
}
vec![]
}
_ => {
vec![]
}
}
}
define_rule!(
SimplifyJoinCondRule,
apply_simplify_join_cond,
(Join(JoinType::Inner), left, right)
);
fn apply_simplify_join_cond(
_optimizer: &impl Optimizer<DfNodeType>,
binding: ArcDfPlanNode,
) -> Vec<PlanNodeOrGroup<DfNodeType>> {
let join = LogicalJoin::from_plan_node(binding).unwrap();
let cond = join.cond();
let left = join.left();
let right = join.right();
match cond.typ {
DfPredType::LogOp(_) => {
let mut changed = false;
let new_log_expr = simplify_log_expr(cond, &mut changed);
if changed {
let join_node =
LogicalJoin::new_unchecked(left, right, new_log_expr, JoinType::Inner);
return vec![join_node.into_plan_node().into()];
}
vec![]
}
_ => {
vec![]
}
}
}
define_rule!(EliminateFilterRule, apply_eliminate_filter, (Filter, child));
fn apply_eliminate_filter(
optimizer: &impl Optimizer<DfNodeType>,
binding: ArcDfPlanNode,
) -> Vec<PlanNodeOrGroup<DfNodeType>> {
let filter = LogicalFilter::from_plan_node(binding).unwrap();
let cond = filter.cond();
if let DfPredType::Constant(ConstantType::Bool) = cond.typ {
if let Some(ref data) = cond.data {
if data.as_bool() {
return vec![filter.child()];
} else {
let schema = optimizer.get_schema_of(filter.child());
let node = LogicalEmptyRelation::new(false, schema);
return vec![node.into_plan_node().into()];
}
}
}
vec![]
}