Skip to content

Commit

Permalink
Simplify IsNotNull and IsNull expression (#6345)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonahgao authored May 15, 2023
1 parent eb918ab commit 7563cdb
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 4 deletions.
34 changes: 34 additions & 0 deletions datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,12 @@ impl<'a, S: SimplifyInfo> TreeNodeRewriter for Simplifier<'a, S> {
lit(!negated)
}

// a IS NOT NULL --> true, if a is not nullable
Expr::IsNotNull(expr) if !info.nullable(&expr)? => lit(true),

// a IS NULL --> false, if a is not nullable
Expr::IsNull(expr) if !info.nullable(&expr)? => lit(false),

// no additional rewrites possible
expr => expr,
};
Expand Down Expand Up @@ -2596,6 +2602,34 @@ mod tests {
);
}

#[test]
fn simplify_expr_is_not_null() {
assert_eq!(
simplify(Expr::IsNotNull(Box::new(col("c1")))),
Expr::IsNotNull(Box::new(col("c1")))
);

// 'c1_non_null IS NOT NULL' is always true
assert_eq!(
simplify(Expr::IsNotNull(Box::new(col("c1_non_null")))),
lit(true)
);
}

#[test]
fn simplify_expr_is_null() {
assert_eq!(
simplify(Expr::IsNull(Box::new(col("c1")))),
Expr::IsNull(Box::new(col("c1")))
);

// 'c1_non_null IS NULL' is always false
assert_eq!(
simplify(Expr::IsNull(Box::new(col("c1_non_null")))),
lit(false)
);
}

#[test]
fn simplify_expr_eq() {
let schema = expr_test_schema();
Expand Down
35 changes: 31 additions & 4 deletions datafusion/optimizer/src/simplify_expressions/simplify_exprs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ mod tests {
Field::new("b", DataType::Boolean, false),
Field::new("c", DataType::Boolean, false),
Field::new("d", DataType::UInt32, false),
Field::new("e", DataType::UInt32, true),
]);
table_scan(Some("test"), &schema, None)
.expect("creating scan")
Expand Down Expand Up @@ -623,9 +624,9 @@ mod tests {
let table_scan = test_table_scan();

let plan = LogicalPlanBuilder::from(table_scan)
.filter(col("d").is_null().not())?
.filter(col("e").is_null().not())?
.build()?;
let expected = "Filter: test.d IS NOT NULL\
let expected = "Filter: test.e IS NOT NULL\
\n TableScan: test";

assert_optimized_plan_eq(&plan, expected)
Expand All @@ -636,9 +637,9 @@ mod tests {
let table_scan = test_table_scan();

let plan = LogicalPlanBuilder::from(table_scan)
.filter(col("d").is_not_null().not())?
.filter(col("e").is_not_null().not())?
.build()?;
let expected = "Filter: test.d IS NULL\
let expected = "Filter: test.e IS NULL\
\n TableScan: test";

assert_optimized_plan_eq(&plan, expected)
Expand Down Expand Up @@ -848,4 +849,30 @@ mod tests {
"TableScan: test, unsupported_filters=[g = f AS g = power(f,Float64(1))]";
assert_optimized_plan_eq(&plan, expected)
}

#[test]
fn simplify_is_not_null() -> Result<()> {
let table_scan = test_table_scan();

let plan = LogicalPlanBuilder::from(table_scan)
.filter(col("d").is_not_null())?
.build()?;
let expected = "Filter: Boolean(true)\
\n TableScan: test";

assert_optimized_plan_eq(&plan, expected)
}

#[test]
fn simplify_is_null() -> Result<()> {
let table_scan = test_table_scan();

let plan = LogicalPlanBuilder::from(table_scan)
.filter(col("d").is_null())?
.build()?;
let expected = "Filter: Boolean(false)\
\n TableScan: test";

assert_optimized_plan_eq(&plan, expected)
}
}

0 comments on commit 7563cdb

Please sign in to comment.