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
+====