mirror of
https://github.com/apache/impala.git
synced 2025-12-25 02:03:09 -05:00
IMPALA-13203: Rewrite 'id = 0 OR false' as expected
Currently, ExprRewriter cannot rewrite 'id = 0 OR false' to 'id = 0' as expected. More precisely, it fails to rewrite any cases where a boolean literal follows 'AND/OR' as expected. The issue is that the CompoundPredicate generated by NormalizeExprsRule is not analyzed, causing SimplifyConditionalsRule to skip the rewrite. This patch fixes the issue by adding analysis of the rewritten CompoundPredicate in NormalizeExprsRule. Testing: - Modified and passed FE test case ExprRewriteRulesTest#testCompoundPredicate - Modified and passed related test case Change-Id: I9d9fffdd1cc644cc2b48f08c2509f22a72362d22 Reviewed-on: http://gerrit.cloudera.org:8080/21568 Reviewed-by: Csaba Ringhofer <csringhofer@cloudera.com> Tested-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
This commit is contained in:
@@ -38,17 +38,20 @@ public class NormalizeExprsRule implements ExprRewriteRule {
|
||||
|
||||
// TODO: add normalization for other expr types.
|
||||
if (expr instanceof CompoundPredicate) {
|
||||
return normalizeCompoundPredicate((CompoundPredicate) expr);
|
||||
return normalizeCompoundPredicate((CompoundPredicate) expr, analyzer);
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
private Expr normalizeCompoundPredicate(CompoundPredicate expr) {
|
||||
private Expr normalizeCompoundPredicate(CompoundPredicate expr, Analyzer analyzer) {
|
||||
if (expr.getOp() == CompoundPredicate.Operator.NOT) return expr;
|
||||
|
||||
if (!(expr.getChild(0) instanceof BoolLiteral)
|
||||
&& expr.getChild(1) instanceof BoolLiteral) {
|
||||
return new CompoundPredicate(expr.getOp(), expr.getChild(1), expr.getChild(0));
|
||||
CompoundPredicate newExpr = new CompoundPredicate(expr.getOp(), expr.getChild(1),
|
||||
expr.getChild(0));
|
||||
newExpr.analyzeNoThrow(analyzer);
|
||||
return newExpr;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -527,7 +527,8 @@ public class ExprCardinalityTest {
|
||||
// Chain of OR rewritten to IN
|
||||
verifySelectExpr("alltypes", "int_col = 10 or int_col = 20", 3, 2.0/10);
|
||||
// Or with literals
|
||||
verifySelectExpr("alltypes", "int_col = 10 or true", 3, 1.0);
|
||||
// 'int_col = 10 or true' rewritten to 'true', expected NDV = 1
|
||||
verifySelectExpr("alltypes", "int_col = 10 or true", 1, 1.0);
|
||||
verifySelectExpr("alltypes", "int_col = 10 or false", 3, 0.1);
|
||||
verifySelectExpr("alltypes", "int_col = 10 or null", 3, 0.1);
|
||||
}
|
||||
|
||||
@@ -440,12 +440,15 @@ public class ExprRewriteRulesTest extends FrontendTestBase {
|
||||
|
||||
@Test
|
||||
public void testCompoundPredicate() throws ImpalaException {
|
||||
ExprRewriteRule rule = SimplifyConditionalsRule.INSTANCE;
|
||||
List<ExprRewriteRule> rules = Lists.newArrayList(NormalizeExprsRule.INSTANCE,
|
||||
SimplifyConditionalsRule.INSTANCE);
|
||||
|
||||
RewritesOk("false OR id = 0", rule, "id = 0");
|
||||
RewritesOk("true OR id = 0", rule, "TRUE");
|
||||
RewritesOk("false && id = 0", rule, "FALSE");
|
||||
RewritesOk("true && id = 0", rule, "id = 0");
|
||||
RewritesOk("id = 0 OR false", rules, "id = 0");
|
||||
RewritesOk("id = 0 OR true", rules, "TRUE");
|
||||
RewritesOk("id = 0 && false", rules, "FALSE");
|
||||
RewritesOk("id = 0 && true", rules, "id = 0");
|
||||
RewritesOk("false OR id = 0 AND true", rules, "id = 0");
|
||||
RewritesOk("true AND id = 0 OR false", rules, "id = 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -273,7 +273,7 @@ PLAN-ROOT SINK
|
||||
|
|
||||
00:SCAN HDFS [functional.alltypes]
|
||||
HDFS partitions=24/24 files=24 size=478.45KB
|
||||
predicates: int_col = 10, TRUE OR 10 + random() * functional.alltypes.tinyint_col = 100
|
||||
predicates: int_col = 10
|
||||
row-size=5B cardinality=231
|
||||
====
|
||||
# Collection predicates within HDFS scan nodes get optimized
|
||||
|
||||
@@ -157,9 +157,8 @@ on (a.id = b.id and 1 + 1 > 10)
|
||||
---- PLAN
|
||||
PLAN-ROOT SINK
|
||||
|
|
||||
02:HASH JOIN [LEFT OUTER JOIN]
|
||||
| hash predicates: a.id = b.id
|
||||
| other join predicates: FALSE
|
||||
02:NESTED LOOP JOIN [LEFT OUTER JOIN]
|
||||
| join predicates: FALSE
|
||||
| row-size=178B cardinality=100
|
||||
|
|
||||
|--01:SCAN HDFS [functional.alltypestiny b]
|
||||
@@ -179,11 +178,9 @@ on (a.id = b.id and !true)
|
||||
---- PLAN
|
||||
PLAN-ROOT SINK
|
||||
|
|
||||
02:HASH JOIN [RIGHT OUTER JOIN]
|
||||
| hash predicates: a.id = b.id
|
||||
| other join predicates: FALSE
|
||||
| runtime filters: RF000 <- b.id
|
||||
| row-size=178B cardinality=9
|
||||
02:NESTED LOOP JOIN [RIGHT OUTER JOIN]
|
||||
| join predicates: FALSE
|
||||
| row-size=178B cardinality=100
|
||||
|
|
||||
|--01:SCAN HDFS [functional.alltypestiny b]
|
||||
| HDFS partitions=4/4 files=4 size=460B
|
||||
@@ -191,7 +188,6 @@ PLAN-ROOT SINK
|
||||
|
|
||||
00:SCAN HDFS [functional.alltypessmall a]
|
||||
HDFS partitions=4/4 files=4 size=6.32KB
|
||||
runtime filters: RF000 -> a.id
|
||||
row-size=89B cardinality=100
|
||||
====
|
||||
# Constant conjunct in the ON-clause of an outer join is
|
||||
|
||||
@@ -1276,6 +1276,6 @@ PLAN-ROOT SINK
|
||||
|
|
||||
00:SCAN HDFS [functional.alltypes]
|
||||
partitions=24/24 files=24 size=478.45KB
|
||||
predicates: functional.alltypes.int_col = 1, FALSE OR 1 + random() * 1 = 100
|
||||
predicates: functional.alltypes.int_col = 1, 1 + random() * 1 = 100
|
||||
row-size=4B cardinality=231
|
||||
====
|
||||
|
||||
Reference in New Issue
Block a user