-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Add algebraic simplifications to constant_folding #1208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c75922f
ff060ea
e04a8dd
fc715de
c240e83
056508d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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))), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so cool!
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this can match because |
||
| 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))), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could also add the rules that |
||
| 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()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The rules for null and AND are |
||
| (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(()) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alamb to help me understand, can you provide color on whats an example of an
Exprthat isnt aBooleanbut that has a boolean type?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nvm, i get it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One example is if someone writes
col_a OR trueandcol_ahas type ofint64or something -- I don't know how far such an expression will get (it will likely error out when trying to to actually run thePhysicalExpr)