Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @byteink. would you mind adding more description? Why the simplification needed and what exactly problem it solves? is it a bug or something?

Copy link
Member

@jackwener jackwener May 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create table test(a int not null);

select a is null

we can convert it into

select false

because a is not null

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@comphead It is not a bug. I've added some descriptions.


// 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)
}
}