Skip to content

Commit

Permalink
Implement rewrite for EliminateOneUnion and EliminateJoin (#10184)
Browse files Browse the repository at this point in the history
* implement rewrite for EliminateJoin

* implement rewrite for eliminate_on_union
  • Loading branch information
Lordworms authored Apr 23, 2024
1 parent c96182b commit 08030f3
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 29 deletions.
2 changes: 1 addition & 1 deletion datafusion/expr/src/logical_plan/tree_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ impl TreeNode for LogicalPlan {

/// Converts a `Arc<LogicalPlan>` without copying, if possible. Copies the plan
/// if there is a shared reference
fn unwrap_arc(plan: Arc<LogicalPlan>) -> LogicalPlan {
pub fn unwrap_arc(plan: Arc<LogicalPlan>) -> LogicalPlan {
Arc::try_unwrap(plan)
// if None is returned, there is another reference to this
// LogicalPlan, so we can not own it, and must clone instead
Expand Down
51 changes: 32 additions & 19 deletions datafusion/optimizer/src/eliminate_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
//! [`EliminateJoin`] rewrites `INNER JOIN` with `true`/`null`
use crate::optimizer::ApplyOrder;
use crate::{OptimizerConfig, OptimizerRule};
use datafusion_common::{Result, ScalarValue};
use datafusion_common::tree_node::Transformed;
use datafusion_common::{internal_err, Result, ScalarValue};
use datafusion_expr::JoinType::Inner;
use datafusion_expr::{
logical_plan::{EmptyRelation, LogicalPlan},
Expand All @@ -39,38 +40,50 @@ impl EliminateJoin {
impl OptimizerRule for EliminateJoin {
fn try_optimize(
&self,
plan: &LogicalPlan,
_plan: &LogicalPlan,
_config: &dyn OptimizerConfig,
) -> Result<Option<LogicalPlan>> {
internal_err!("Should have called EliminateJoin::rewrite")
}

fn name(&self) -> &str {
"eliminate_join"
}

fn apply_order(&self) -> Option<ApplyOrder> {
Some(ApplyOrder::TopDown)
}

fn rewrite(
&self,
plan: LogicalPlan,
_config: &dyn OptimizerConfig,
) -> Result<Transformed<LogicalPlan>> {
match plan {
LogicalPlan::Join(join) if join.join_type == Inner && join.on.is_empty() => {
match join.filter {
Some(Expr::Literal(ScalarValue::Boolean(Some(true)))) => {
Ok(Some(LogicalPlan::CrossJoin(CrossJoin {
left: join.left.clone(),
right: join.right.clone(),
schema: join.schema.clone(),
Ok(Transformed::yes(LogicalPlan::CrossJoin(CrossJoin {
left: join.left,
right: join.right,
schema: join.schema,
})))
}
Some(Expr::Literal(ScalarValue::Boolean(Some(false)))) => {
Ok(Some(LogicalPlan::EmptyRelation(EmptyRelation {
Some(Expr::Literal(ScalarValue::Boolean(Some(false)))) => Ok(
Transformed::yes(LogicalPlan::EmptyRelation(EmptyRelation {
produce_one_row: false,
schema: join.schema.clone(),
})))
}
_ => Ok(None),
schema: join.schema,
})),
),
_ => Ok(Transformed::no(LogicalPlan::Join(join))),
}
}
_ => Ok(None),
_ => Ok(Transformed::no(plan)),
}
}

fn name(&self) -> &str {
"eliminate_join"
}

fn apply_order(&self) -> Option<ApplyOrder> {
Some(ApplyOrder::TopDown)
fn supports_rewrite(&self) -> bool {
true
}
}

Expand Down
30 changes: 21 additions & 9 deletions datafusion/optimizer/src/eliminate_one_union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

//! [`EliminateOneUnion`] eliminates single element `Union`
use crate::{OptimizerConfig, OptimizerRule};
use datafusion_common::Result;
use datafusion_expr::logical_plan::{LogicalPlan, Union};
use datafusion_common::{internal_err, tree_node::Transformed, Result};
use datafusion_expr::logical_plan::{tree_node::unwrap_arc, LogicalPlan, Union};

use crate::optimizer::ApplyOrder;

Expand All @@ -36,21 +36,33 @@ impl EliminateOneUnion {
impl OptimizerRule for EliminateOneUnion {
fn try_optimize(
&self,
plan: &LogicalPlan,
_plan: &LogicalPlan,
_config: &dyn OptimizerConfig,
) -> Result<Option<LogicalPlan>> {
match plan {
LogicalPlan::Union(Union { inputs, .. }) if inputs.len() == 1 => {
Ok(inputs.first().map(|input| input.as_ref().clone()))
}
_ => Ok(None),
}
internal_err!("Should have called EliminateOneUnion::rewrite")
}

fn name(&self) -> &str {
"eliminate_one_union"
}

fn supports_rewrite(&self) -> bool {
true
}

fn rewrite(
&self,
plan: LogicalPlan,
_config: &dyn OptimizerConfig,
) -> Result<Transformed<LogicalPlan>> {
match plan {
LogicalPlan::Union(Union { mut inputs, .. }) if inputs.len() == 1 => {
Ok(Transformed::yes(unwrap_arc(inputs.pop().unwrap())))
}
_ => Ok(Transformed::no(plan)),
}
}

fn apply_order(&self) -> Option<ApplyOrder> {
Some(ApplyOrder::TopDown)
}
Expand Down

0 comments on commit 08030f3

Please sign in to comment.