IMPALA-9025: Handle AnalysisException caused by expr_rewrites
properly
When the optimizer rewrites conjunct exprs with constant values,
a new expr may cause AnalysisException. In this case,
the conjuncts should use the original expr, not the intermediate
expr produced by propagateConstants. Fixed optimizeConjuncts
to handle this scenario properly.
Tests:
Add unit test for alias.
Ran exhaustive tests.
Change-Id: Ic57bf3f4cdabfe9c5bb304d735bfbf1c0ca7a274
Reviewed-on: http://gerrit.cloudera.org:8080/14403
Reviewed-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
Tested-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
diff --git a/fe/src/main/java/org/apache/impala/analysis/Expr.java b/fe/src/main/java/org/apache/impala/analysis/Expr.java
index 84ee9b9..628e0c5 100644
--- a/fe/src/main/java/org/apache/impala/analysis/Expr.java
+++ b/fe/src/main/java/org/apache/impala/analysis/Expr.java
@@ -1182,15 +1182,20 @@
*/
public static boolean optimizeConjuncts(List<Expr> conjuncts, Analyzer analyzer) {
Preconditions.checkNotNull(conjuncts);
+ List<Expr> tmpConjuncts = new ArrayList<>();
try {
BitSet candidates = new BitSet(conjuncts.size());
candidates.set(0, Math.min(conjuncts.size(), CONST_PROPAGATION_EXPR_LIMIT));
int transfers = 0;
-
+ tmpConjuncts.addAll(conjuncts);
// Constant propagation may make other slots constant, so repeat the process
// until there are no more changes.
while (!candidates.isEmpty()) {
- BitSet changed = propagateConstants(conjuncts, candidates, analyzer);
+ // Use tmpConjuncts instead of conjuncts because propagateConstants can
+ // change the content of the first input param. We do not want to
+ // change the expr in conjucts before make sure the constant propagation
+ // does not cause analysis failures.
+ BitSet changed = propagateConstants(tmpConjuncts, candidates, analyzer);
candidates.clear();
int pruned = 0;
for (int i = changed.nextSetBit(0); i >= 0; i = changed.nextSetBit(i+1)) {
@@ -1200,12 +1205,13 @@
int index = i - pruned;
Preconditions.checkState(index >= 0);
ExprRewriter rewriter = analyzer.getExprRewriter();
- Expr rewritten = rewriter.rewrite(conjuncts.get(index), analyzer);
+ Expr rewritten = rewriter.rewrite(tmpConjuncts.get(index), analyzer);
// Re-analyze to add implicit casts and update cost
rewritten.reset();
rewritten.analyze(analyzer);
if (!rewritten.isConstant()) {
conjuncts.set(index, rewritten);
+ tmpConjuncts.set(index, rewritten);
if (++transfers < CONST_PROPAGATION_EXPR_LIMIT) candidates.set(index, true);
continue;
}
@@ -1221,6 +1227,7 @@
if (IS_TRUE_LITERAL.apply(rewritten)) {
pruned++;
conjuncts.remove(index);
+ tmpConjuncts.remove(index);
}
}
}
diff --git a/testdata/workloads/functional-query/queries/QueryTest/alias.test b/testdata/workloads/functional-query/queries/QueryTest/alias.test
index e14488f..8560048 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/alias.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/alias.test
@@ -85,3 +85,12 @@
---- TYPES
bigint
====
+---- QUERY
+# literal alias
+# IMPALA-9025: When constant propagation optimization fails, the query fails
+# with "ERROR: IllegalStateException: null"
+select * from (select t.* from alltypestiny t
+inner join (select 10 bigint_col) d where
+t.int_col < d.bigint_col ) q
+where int_col <> bigint_col and int_col = 10
+====