Skip to content

Commit c1fe3dd

Browse files
authored
feat: remove filters with null constants (#8700)
1 parent 96cede2 commit c1fe3dd

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

datafusion/optimizer/src/eliminate_filter.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
//! Optimizer rule to replace `where false` on a plan with an empty relation.
18+
//! Optimizer rule to replace `where false or null` on a plan with an empty relation.
1919
//! This saves time in planning and executing the query.
2020
//! Note that this rule should be applied after simplify expressions optimizer rule.
2121
use crate::optimizer::ApplyOrder;
@@ -27,7 +27,7 @@ use datafusion_expr::{
2727

2828
use crate::{OptimizerConfig, OptimizerRule};
2929

30-
/// Optimization rule that eliminate the scalar value (true/false) filter with an [LogicalPlan::EmptyRelation]
30+
/// Optimization rule that eliminate the scalar value (true/false/null) filter with an [LogicalPlan::EmptyRelation]
3131
#[derive(Default)]
3232
pub struct EliminateFilter;
3333

@@ -46,20 +46,22 @@ impl OptimizerRule for EliminateFilter {
4646
) -> Result<Option<LogicalPlan>> {
4747
match plan {
4848
LogicalPlan::Filter(Filter {
49-
predicate: Expr::Literal(ScalarValue::Boolean(Some(v))),
49+
predicate: Expr::Literal(ScalarValue::Boolean(v)),
5050
input,
5151
..
5252
}) => {
5353
match *v {
5454
// input also can be filter, apply again
55-
true => Ok(Some(
55+
Some(true) => Ok(Some(
5656
self.try_optimize(input, _config)?
5757
.unwrap_or_else(|| input.as_ref().clone()),
5858
)),
59-
false => Ok(Some(LogicalPlan::EmptyRelation(EmptyRelation {
60-
produce_one_row: false,
61-
schema: input.schema().clone(),
62-
}))),
59+
Some(false) | None => {
60+
Ok(Some(LogicalPlan::EmptyRelation(EmptyRelation {
61+
produce_one_row: false,
62+
schema: input.schema().clone(),
63+
})))
64+
}
6365
}
6466
}
6567
_ => Ok(None),
@@ -105,6 +107,21 @@ mod tests {
105107
assert_optimized_plan_equal(&plan, expected)
106108
}
107109

110+
#[test]
111+
fn filter_null() -> Result<()> {
112+
let filter_expr = Expr::Literal(ScalarValue::Boolean(None));
113+
114+
let table_scan = test_table_scan().unwrap();
115+
let plan = LogicalPlanBuilder::from(table_scan)
116+
.aggregate(vec![col("a")], vec![sum(col("b"))])?
117+
.filter(filter_expr)?
118+
.build()?;
119+
120+
// No aggregate / scan / limit
121+
let expected = "EmptyRelation";
122+
assert_optimized_plan_equal(&plan, expected)
123+
}
124+
108125
#[test]
109126
fn filter_false_nested() -> Result<()> {
110127
let filter_expr = Expr::Literal(ScalarValue::Boolean(Some(false)));

0 commit comments

Comments
 (0)