You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by al...@apache.org on 2021/11/02 20:22:24 UTC
[arrow-datafusion] branch master updated: Add algebraic
simplifications to constant_folding (#1208)
This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git
The following commit(s) were added to refs/heads/master by this push:
new bbd8e1b Add algebraic simplifications to constant_folding (#1208)
bbd8e1b is described below
commit bbd8e1b9a80f049c8998dd70aa3323089fa315c7
Author: Matthew Turner <ma...@outlook.com>
AuthorDate: Tue Nov 2 16:20:33 2021 -0400
Add algebraic simplifications to constant_folding (#1208)
* Add Or branch to constant folding
* Add test for Or
* Simplify or match
* Add And operator
* Updated Or and And logic
* Updated Or and And to handle nulls and added tests
---
datafusion/src/optimizer/constant_folding.rs | 207 +++++++++++++++++++++++++++
1 file changed, 207 insertions(+)
diff --git a/datafusion/src/optimizer/constant_folding.rs b/datafusion/src/optimizer/constant_folding.rs
index 8c29da4..dace622 100644
--- a/datafusion/src/optimizer/constant_folding.rs
+++ b/datafusion/src/optimizer/constant_folding.rs
@@ -210,6 +210,104 @@ impl<'a> ExprRewriter for Simplifier<'a> {
right,
},
},
+ Operator::Or => match (left.as_ref(), right.as_ref()) {
+ (Expr::Literal(ScalarValue::Boolean(b)), _)
+ if self.is_boolean_type(&right) =>
+ {
+ match b {
+ Some(true) => Expr::Literal(ScalarValue::Boolean(Some(true))),
+ Some(false) => match *right {
+ Expr::Literal(ScalarValue::Boolean(None)) => {
+ Expr::Literal(ScalarValue::Boolean(None))
+ }
+ _ => *right,
+ },
+ None => match *right {
+ Expr::Literal(ScalarValue::Boolean(Some(true))) => {
+ Expr::Literal(ScalarValue::Boolean(Some(true)))
+ }
+ Expr::Literal(ScalarValue::Boolean(Some(false))) => {
+ Expr::Literal(ScalarValue::Boolean(None))
+ }
+ _ => *right,
+ },
+ }
+ }
+ (_, Expr::Literal(ScalarValue::Boolean(b)))
+ if self.is_boolean_type(&left) =>
+ {
+ match b {
+ Some(true) => Expr::Literal(ScalarValue::Boolean(Some(true))),
+ Some(false) => match *left {
+ Expr::Literal(ScalarValue::Boolean(None)) => {
+ Expr::Literal(ScalarValue::Boolean(None))
+ }
+ _ => *left,
+ },
+ None => match *left {
+ Expr::Literal(ScalarValue::Boolean(Some(true))) => {
+ Expr::Literal(ScalarValue::Boolean(Some(true)))
+ }
+ Expr::Literal(ScalarValue::Boolean(Some(false))) => {
+ Expr::Literal(ScalarValue::Boolean(None))
+ }
+ _ => *left,
+ },
+ }
+ }
+ _ => Expr::BinaryExpr {
+ left,
+ op: Operator::Or,
+ right,
+ },
+ },
+ Operator::And => match (left.as_ref(), right.as_ref()) {
+ (Expr::Literal(ScalarValue::Boolean(b)), _)
+ if self.is_boolean_type(&right) =>
+ {
+ // match b {
+ // Some(false) => {
+ // Expr::Literal(ScalarValue::Boolean(Some(false)))
+ // }
+ // _ => *right,
+ // }
+ match b {
+ Some(true) => match *right {
+ Expr::Literal(ScalarValue::Boolean(None)) => {
+ Expr::Literal(ScalarValue::Boolean(None))
+ }
+ _ => *right,
+ },
+ Some(false) => {
+ Expr::Literal(ScalarValue::Boolean(Some(false)))
+ }
+ None => match *right {
+ Expr::Literal(ScalarValue::Boolean(Some(true))) => {
+ Expr::Literal(ScalarValue::Boolean(None))
+ }
+ Expr::Literal(ScalarValue::Boolean(Some(false))) => {
+ Expr::Literal(ScalarValue::Boolean(Some(false)))
+ }
+ _ => *right,
+ },
+ }
+ }
+ (_, Expr::Literal(ScalarValue::Boolean(b)))
+ if self.is_boolean_type(&left) =>
+ {
+ match b {
+ Some(false) => {
+ Expr::Literal(ScalarValue::Boolean(Some(false)))
+ }
+ _ => *left,
+ }
+ }
+ _ => Expr::BinaryExpr {
+ left,
+ op: Operator::And,
+ right,
+ },
+ },
_ => Expr::BinaryExpr { left, op, right },
},
// Not(Not(expr)) --> expr
@@ -811,4 +909,113 @@ mod tests {
assert_eq!(expected, actual);
}
+ #[test]
+ fn optimize_expr_bool_or() -> Result<()> {
+ let schema = expr_test_schema();
+ let mut rewriter = Simplifier {
+ schemas: vec![&schema],
+ };
+
+ // col || true is always true
+ assert_eq!(
+ (col("c2").or(Expr::Literal(ScalarValue::Boolean(Some(true)))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(Some(true))),
+ );
+
+ // col || false is always col
+ assert_eq!(
+ (col("c2").or(Expr::Literal(ScalarValue::Boolean(Some(false)))))
+ .rewrite(&mut rewriter)?,
+ col("c2"),
+ );
+
+ // true || null is always true
+ assert_eq!(
+ (Expr::Literal(ScalarValue::Boolean(Some(true)))
+ .or(Expr::Literal(ScalarValue::Boolean(None))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(Some(true))),
+ );
+
+ // null || true is always true
+ assert_eq!(
+ (Expr::Literal(ScalarValue::Boolean(None))
+ .or(Expr::Literal(ScalarValue::Boolean(Some(true)))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(Some(true))),
+ );
+
+ // false || null is always null
+ assert_eq!(
+ (Expr::Literal(ScalarValue::Boolean(Some(false)))
+ .or(Expr::Literal(ScalarValue::Boolean(None))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(None)),
+ );
+
+ // null || false is always null
+ assert_eq!(
+ (Expr::Literal(ScalarValue::Boolean(None))
+ .or(Expr::Literal(ScalarValue::Boolean(Some(false)))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(None)),
+ );
+
+ Ok(())
+ }
+ #[test]
+ fn optimize_expr_bool_and() -> Result<()> {
+ let schema = expr_test_schema();
+ let mut rewriter = Simplifier {
+ schemas: vec![&schema],
+ };
+
+ // col & true is always col
+ assert_eq!(
+ (col("c2").and(Expr::Literal(ScalarValue::Boolean(Some(true)))))
+ .rewrite(&mut rewriter)?,
+ col("c2"),
+ );
+ // col & false is always false
+ assert_eq!(
+ (col("c2").and(Expr::Literal(ScalarValue::Boolean(Some(false)))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(Some(false))),
+ );
+
+ // true && null is always null
+ assert_eq!(
+ (Expr::Literal(ScalarValue::Boolean(Some(true)))
+ .and(Expr::Literal(ScalarValue::Boolean(None))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(None)),
+ );
+
+ // null && true is always null
+ assert_eq!(
+ (Expr::Literal(ScalarValue::Boolean(None))
+ .and(Expr::Literal(ScalarValue::Boolean(Some(true)))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(None)),
+ );
+
+ // false && null is always false
+ assert_eq!(
+ (Expr::Literal(ScalarValue::Boolean(Some(false)))
+ .and(Expr::Literal(ScalarValue::Boolean(None))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(Some(false))),
+ );
+
+ // null && false is always false
+ assert_eq!(
+ (Expr::Literal(ScalarValue::Boolean(None))
+ .and(Expr::Literal(ScalarValue::Boolean(Some(false)))))
+ .rewrite(&mut rewriter)?,
+ lit(ScalarValue::Boolean(Some(false))),
+ );
+
+ Ok(())
+ }
}