IMPALA-10096: Use the original ordinal if the group by ordinal reference is a constant int

The SelectStmt's groupingExprs_ uses the analyzed version and the
ordinal reference will be substituted.
It will throw an exception if the ordinal reference is still a numeric
literal, because we will re-analyze after the expression has been
rewritten. For example, here "count(1)" is rewritten to "count(*)" so
we need to re-analyze the new query.
select 13, id, count(1) from dimtbl group by 1, 2;
The rewritten sql should be
select 13, id, count(*) from dimtbl group by 1, id;
If the original query uses "count(*)", it won't hit the bug since
no rewriting happens.

Testing:
 - Added new unit tests with ordinal in GROUP BY whereas SELECT has
   the INT literal.
 - Ran 'mvn test' for the FE

Change-Id: I34f659d15073d69aa0a4685f56ad94557df86560
Reviewed-on: http://gerrit.cloudera.org:8080/16353
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/SelectStmt.java b/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java
index 3d520f3..4ad4652 100644
--- a/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java
@@ -756,7 +756,17 @@
         }
       }
       // initialize groupingExprs_ with the analyzed version
-      groupingExprs_ = groupingExprsCopy_;
+      // use the original ordinal if the analyzed expr is a INT literal
+      List<Expr> groupingExprs = new ArrayList<>();
+      for (int i = 0; i < groupingExprsCopy_.size(); ++i) {
+        Expr expr = groupingExprsCopy_.get(i);
+        if (expr instanceof NumericLiteral && Expr.IS_INT_LITERAL.apply(expr)) {
+          groupingExprs.add(groupingExprs_.get(i).clone());
+        } else {
+          groupingExprs.add(expr);
+        }
+      }
+      groupingExprs_ = groupingExprs;
 
       if (groupByClause_ != null && groupByClause_.hasGroupingSets()) {
         groupByClause_.analyzeGroupingSets(groupingExprsCopy_);
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/aggregation.test b/testdata/workloads/functional-planner/queries/PlannerTest/aggregation.test
index d36a2af..2ac3f53 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/aggregation.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/aggregation.test
@@ -1612,3 +1612,63 @@
    partitions=24/24 files=24 size=478.45KB
    row-size=4B cardinality=7.30K
 ====
+# IMPALA-10096: use the original ordinal if the group by ordinal reference is a
+# constant int
+select 13, id, count(1) from functional.dimtbl group by 1, 2
+---- PLAN
+PLAN-ROOT SINK
+|
+01:AGGREGATE [FINALIZE]
+|  output: count(*)
+|  group by: 13, id
+|  row-size=17B cardinality=10
+|
+00:SCAN HDFS [functional.dimtbl]
+   HDFS partitions=1/1 files=1 size=171B
+   row-size=8B cardinality=10
+====
+# IMPALA-10096: use the original ordinal if the group by ordinal reference is a
+# constant int
+select -1, id, count(1) from functional.dimtbl group by 1, 2
+---- PLAN
+PLAN-ROOT SINK
+|
+01:AGGREGATE [FINALIZE]
+|  output: count(*)
+|  group by: -1, id
+|  row-size=17B cardinality=10
+|
+00:SCAN HDFS [functional.dimtbl]
+   HDFS partitions=1/1 files=1 size=171B
+   row-size=8B cardinality=10
+====
+# IMPALA-10096: use the original ordinal if the group by ordinal reference is a
+# constant int
+select 2, id, count(1) from functional.dimtbl group by 1, 2
+---- PLAN
+PLAN-ROOT SINK
+|
+01:AGGREGATE [FINALIZE]
+|  output: count(*)
+|  group by: 2, id
+|  row-size=17B cardinality=10
+|
+00:SCAN HDFS [functional.dimtbl]
+   HDFS partitions=1/1 files=1 size=171B
+   row-size=8B cardinality=10
+====
+# IMPALA-10096: use the original ordinal if the group by ordinal reference is a
+# constant int
+select 2 + 1, id, count(1) from functional.dimtbl group by 1, 2
+---- PLAN
+PLAN-ROOT SINK
+|
+01:AGGREGATE [FINALIZE]
+|  output: count(*)
+|  group by: 2 + 1, id
+|  row-size=18B cardinality=10
+|
+00:SCAN HDFS [functional.dimtbl]
+   HDFS partitions=1/1 files=1 size=171B
+   row-size=8B cardinality=10
+====