diff --git a/fe/src/main/java/org/apache/impala/analysis/QueryStmt.java b/fe/src/main/java/org/apache/impala/analysis/QueryStmt.java index 6f21a331e..178e80c62 100644 --- a/fe/src/main/java/org/apache/impala/analysis/QueryStmt.java +++ b/fe/src/main/java/org/apache/impala/analysis/QueryStmt.java @@ -197,7 +197,7 @@ public abstract class QueryStmt extends StatementBase { isAscOrder.add(Boolean.valueOf(orderByElement.isAsc())); nullsFirstParams.add(orderByElement.getNullsFirstParam()); } - substituteOrdinalsAliases(orderingExprs, "ORDER BY", analyzer); + substituteOrdinalsAndAliases(orderingExprs, "ORDER BY", analyzer); if (!analyzer.isRootAnalyzer() && hasOffset() && !hasLimit()) { throw new AnalysisException("Order-by with offset without limit not supported" + @@ -268,41 +268,42 @@ public abstract class QueryStmt extends StatementBase { } /** - * Return the first expr in exprs that is a non-unique alias. Return null if none of - * exprs is an ambiguous alias. + * Substitutes an ordinal or an alias. An ordinal is an integer NumericLiteral + * that refers to a select-list expression by ordinal. An alias is a SlotRef + * that matches the alias of a select-list expression (tracked by 'aliasMap_'). + * We should substitute by ordinal or alias but not both to avoid an incorrect + * double substitution. + * Returns clone() of 'expr' if it is not an ordinal, nor an alias. + * The returned expr is analyzed regardless of whether substitution was performed. */ - protected Expr getFirstAmbiguousAlias(List exprs) { - for (Expr exp: exprs) { - if (ambiguousAliasList_.contains(exp)) return exp; + protected Expr substituteOrdinalOrAlias(Expr expr, String errorPrefix, + Analyzer analyzer) throws AnalysisException { + Expr substituteExpr = trySubstituteOrdinal(expr, errorPrefix, analyzer); + if (substituteExpr != null) return substituteExpr; + if (ambiguousAliasList_.contains(expr)) { + throw new AnalysisException("Column '" + expr.toSql() + + "' in " + errorPrefix + " clause is ambiguous"); } - return null; + if (expr instanceof SlotRef) { + substituteExpr = expr.trySubstitute(aliasSmap_, analyzer, false); + } else { + expr.analyze(analyzer); + substituteExpr = expr; + } + return substituteExpr; } /** - * Substitute exprs of the form "" with the corresponding - * expressions and any alias references in aliasSmap_. - * Modifies exprs list in-place. + * Substitutes top-level ordinals and aliases. Does not substitute ordinals and + * aliases in subexpressions. + * Modifies the 'exprs' list in-place. + * The 'exprs' are all analyzed after this function regardless of whether + * substitution was performed. */ - protected void substituteOrdinalsAliases(List exprs, String errorPrefix, + protected void substituteOrdinalsAndAliases(List exprs, String errorPrefix, Analyzer analyzer) throws AnalysisException { - Expr ambiguousAlias = getFirstAmbiguousAlias(exprs); - if (ambiguousAlias != null) { - throw new AnalysisException("Column '" + ambiguousAlias.toSql() + - "' in " + errorPrefix + " clause is ambiguous"); - } - - ListIterator i = exprs.listIterator(); - while (i.hasNext()) { - Expr expr = i.next(); - // We can substitute either by ordinal or by alias. - // If we substitute by ordinal, we should not replace any aliases, since - // the new expression was copied from the select clause context, where - // alias substitution is not performed in the same way. - Expr substituteExpr = trySubstituteOrdinal(expr, errorPrefix, analyzer); - if (substituteExpr == null) { - substituteExpr = expr.trySubstitute(aliasSmap_, analyzer, false); - } - i.set(substituteExpr); + for (int i = 0; i < exprs.size(); ++i) { + exprs.set(i, substituteOrdinalOrAlias(exprs.get(i), errorPrefix, analyzer)); } } 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 2ba5105f2..f9d08b73b 100644 --- a/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java +++ b/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java @@ -541,13 +541,12 @@ public class SelectStmt extends QueryStmt { // Analyze the HAVING clause first so we can check if it contains aggregates. // We need to analyze/register it even if we are not computing aggregates. if (havingClause_ != null) { - if (havingClause_.contains(Predicates.instanceOf(Subquery.class))) { + havingPred_ = substituteOrdinalOrAlias(havingClause_, "HAVING", analyzer); + // can't contain subqueries + if (havingPred_.contains(Predicates.instanceOf(Subquery.class))) { throw new AnalysisException( "Subqueries are not supported in the HAVING clause."); } - // substitute aliases in place (ordinals not allowed in having clause) - havingPred_ = havingClause_.substitute(aliasSmap_, analyzer, false); - havingPred_.checkReturnsBool("HAVING clause", true); // can't contain analytic exprs Expr analyticExpr = havingPred_.findFirstOf(AnalyticExpr.class); if (analyticExpr != null) { @@ -555,6 +554,7 @@ public class SelectStmt extends QueryStmt { "HAVING clause must not contain analytic expressions: " + analyticExpr.toSql()); } + havingPred_.checkReturnsBool("HAVING clause", true); } if (groupingExprs_ == null && !selectList_.isDistinct() @@ -615,7 +615,7 @@ public class SelectStmt extends QueryStmt { // exprs during analysis (in case we need to print them later) groupingExprsCopy = Expr.cloneList(groupingExprs_); - substituteOrdinalsAliases(groupingExprsCopy, "GROUP BY", analyzer); + substituteOrdinalsAndAliases(groupingExprsCopy, "GROUP BY", analyzer); for (int i = 0; i < groupingExprsCopy.size(); ++i) { groupingExprsCopy.get(i).analyze(analyzer); @@ -887,6 +887,23 @@ public class SelectStmt extends QueryStmt { } } + /** + * If given expr is rewritten into an integer literal, then return the original expr, + * otherwise return the rewritten expr. + * Used for GROUP BY, ORDER BY, and HAVING where we don't want to create an ordinal + * from a constant arithmetic expr, e.g. 1 * 2 =/=> 2 + */ + private Expr rewriteCheckOrdinalResult(ExprRewriter rewriter, Expr expr) + throws AnalysisException { + Expr rewrittenExpr = rewriter.rewrite(expr, analyzer_); + if (rewrittenExpr.isLiteral() && rewrittenExpr.getType().isIntegerType()) { + return expr; + } + else { + return rewrittenExpr; + } + } + @Override public void rewriteExprs(ExprRewriter rewriter) throws AnalysisException { Preconditions.checkState(isAnalyzed()); @@ -900,12 +917,17 @@ public class SelectStmt extends QueryStmt { for (Subquery s: subqueryExprs) s.getStatement().rewriteExprs(rewriter); } if (havingClause_ != null) { - havingClause_ = rewriter.rewrite(havingClause_, analyzer_); + havingClause_ = rewriteCheckOrdinalResult(rewriter, havingClause_); + } + if (groupingExprs_ != null) { + for (int i = 0; i < groupingExprs_.size(); ++i) { + groupingExprs_.set(i, rewriteCheckOrdinalResult( + rewriter, groupingExprs_.get(i))); + } } - if (groupingExprs_ != null) rewriter.rewriteList(groupingExprs_, analyzer_); if (orderByElements_ != null) { for (OrderByElement orderByElem: orderByElements_) { - orderByElem.setExpr(rewriter.rewrite(orderByElem.getExpr(), analyzer_)); + orderByElem.setExpr(rewriteCheckOrdinalResult(rewriter, orderByElem.getExpr())); } } } diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java index 93a4090de..91d1c00fd 100644 --- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java +++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeExprsTest.java @@ -951,11 +951,6 @@ public class AnalyzeExprsTest extends AnalyzerTest { "select id, tinyint_col, sum(distinct tinyint_col) over(order by id) " + "from functional.alltypes", "DISTINCT not allowed in analytic function"); - // select list alias needs to be ignored - AnalysisError( - "select min(id) over (order by tinyint_col) as X from functional.alltypes " - + "group by id, tinyint_col order by rank() over (order by X)", - "Nesting of analytic expressions is not allowed"); // IGNORE NULLS may only be used with first_value/last_value AnalysisError( "select sum(id ignore nulls) over (order by id) from functional.alltypes", @@ -1005,7 +1000,6 @@ public class AnalyzeExprsTest extends AnalyzerTest { + "order by rank() over (order by tinyint_col), int_col) " + "from functional.alltypes", "Nesting of analytic expressions is not allowed"); - // lead/lag variants AnalyzesOk( "select lag(int_col, 10, 5 + 1) over (partition by id, bool_col " diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java index f9d5cf536..1d8d1be1a 100644 --- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java +++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java @@ -974,7 +974,7 @@ public class AnalyzeStmtsTest extends AnalyzerTest { } @Test - public void TestOrdinals() throws AnalysisException { + public void TestAliasesAndOrdinals() throws AnalysisException { AnalysisError("select * from functional.alltypes group by 1", "cannot combine '*' in select list with grouping or aggregation"); AnalysisError("select * from functional.alltypes order by 14", @@ -985,6 +985,89 @@ public class AnalyzeStmtsTest extends AnalyzerTest { AnalyzesOk("select * from (select max(id) from functional.testtbl) t1 order by 1"); AnalysisError("select * from (select max(id) from functional.testtbl) t1 order by 2", "ORDER BY: ordinal exceeds number of items in select list: 2"); + + // IMPALA-5191: In GROUP BY, HAVING, ORDER BY, aliases and ordinals must only be + // substituted at the top level + // Ambiguous alias in HAVING + AnalysisError("select not bool_col m, min(smallint_col) m, max(bigint_col) m " + + "from functional.alltypes group by bool_col having m", + "Column 'm' in HAVING clause is ambiguous"); + // GROUP BY, ORDER BY, HAVING contains top-level SlotRef or ordinal + AnalyzesOk("select int_col / 2 as x from functional.alltypes group by x"); + AnalyzesOk("select int_col / 2 as x from functional.alltypes order by x"); + AnalyzesOk("select not bool_col as nb from functional.alltypes having nb"); + AnalyzesOk("select int_col / 2 as x from functional.alltypes group by 1"); + AnalyzesOk("select int_col / 2 as x from functional.alltypes order by 1"); + AnalyzesOk("select not bool_col as nb from functional.alltypes having 1"); + // GROUP BY, ORDER BY, HAVING contains alias in subexpression + AnalysisError( + "select int_col / 2 as x from functional.alltypes group by x / 2", + "Could not resolve column/field reference: 'x'"); + AnalysisError( + "select int_col / 2 as x from functional.alltypes order by -x", + "Could not resolve column/field reference: 'x'"); + AnalysisError( + "select int_col / 2 as x from functional.alltypes having x > 0", + "Could not resolve column/field reference: 'x'"); + // Alias or ordinal referring to aggregation output in GROUP BY, ORDER BY, HAVING + AnalysisError("select count(*) a from functional.alltypes group by a", + "GROUP BY expression must not contain aggregate functions: a"); + AnalyzesOk("select count(*) a from functional.alltypes order by a"); + AnalysisError("select count(*) a from functional.alltypes having a", + "HAVING clause 'count(*)' requires return type 'BOOLEAN'. " + + "Actual type is 'BIGINT'."); + AnalysisError("select count(*) from functional.alltypes group by 1", + "GROUP BY expression must not contain aggregate functions: 1"); + AnalyzesOk("select count(*) from functional.alltypes order by 1"); + AnalysisError("select count(*) from functional.alltypes having 1", + "HAVING clause 'count(*)' requires return type 'BOOLEAN'. " + + "Actual type is 'BIGINT'."); + // Alias or ordinal referring to predicate in GROUP BY, ORDER BY, HAVING + AnalysisError("select count(*) > 10 a from functional.alltypes group by a", + "GROUP BY expression must not contain aggregate functions: a"); + AnalyzesOk("select count(*) > 10 a from functional.alltypes order by a"); + AnalyzesOk("select count(*) > 10 a from functional.alltypes having a"); + AnalysisError("select count(*) > 10 from functional.alltypes group by 1", + "GROUP BY expression must not contain aggregate functions: 1"); + AnalyzesOk("select count(*) > 10 from functional.alltypes order by 1"); + AnalyzesOk("select count(*) > 10 from functional.alltypes having 1"); + // Alias or ordinal referring to analytic output in GROUP BY, ORDER BY, HAVING + AnalysisError("select sum(id) over(order by id) a " + + "from functional.alltypes group by a", + "GROUP BY expression must not contain analytic expressions: " + + "sum(id) OVER (ORDER BY id ASC)"); + AnalyzesOk("select sum(id) over(order by id) a from functional.alltypes order by a"); + AnalysisError("select sum(id) over(order by id) a from functional.alltypes having a", + "HAVING clause must not contain analytic expressions: " + + "sum(id) OVER (ORDER BY id ASC)"); + AnalysisError("select sum(id) over(order by id) " + + "from functional.alltypes group by 1", + "GROUP BY expression must not contain analytic expressions: " + + "sum(id) OVER (ORDER BY id ASC)"); + AnalyzesOk("select sum(id) over(order by id) from functional.alltypes order by 1"); + AnalysisError("select sum(id) over(order by id) from functional.alltypes having 1", + "HAVING clause must not contain analytic expressions: " + + "sum(id) OVER (ORDER BY id ASC)"); + AnalyzesOk("with w_test as (select '1' as one, 2 as two, '3' as three) " + + "select one as one, substring(cast(two as string), 1, 1) as two, " + + "three as three, count(1) as cnt " + + "from w_test " + + "group by one, substring(cast(two as string), 1, 1), three"); + // Constant exprs should not be interpreted as ordinals + AnalyzesOk("select int_col, count(*) from functional.alltypes group by 1, 1 * 2"); + AnalyzesOk("select int_col, bigint_col from functional.alltypes order by 1 + 4"); + AnalysisError("select int_col, bool_col, count(*) from functional.alltypes " + + "group by 1, 2 having 1 + 1", + "HAVING clause '1 + 1' requires return type 'BOOLEAN'. " + + "Actual type is 'SMALLINT'."); + AnalyzesOk("select int_col, count(*) from functional.alltypes group by 1, " + + "if(true, 2, int_col)"); + AnalyzesOk("select int_col, bigint_col from functional.alltypes order by " + + "if(true, 7, int_col)"); + AnalysisError("select int_col, bool_col, count(*) from functional.alltypes " + + "group by 1, 2 having if(TRUE, 2, int_col)", + "HAVING clause 'if(TRUE, 2, int_col)' requires return type 'BOOLEAN'. " + + "Actual type is 'INT'."); } @Test @@ -1999,7 +2082,8 @@ public class AnalyzeStmtsTest extends AnalyzerTest { // Test select stmt avg smap. AnalyzesOk("select cast(avg(c1) as decimal(10,4)) as c from " + - "functional.decimal_tiny group by c3 having c = 5.1106 order by 1"); + "functional.decimal_tiny group by c3 having cast(avg(c1) as " + + "decimal(10,4)) = 5.1106 order by 1"); // check CHAR and VARCHAR aggregates checkExprType("select min(cast('foo' as char(5))) from functional.chars_tiny", diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/constant-folding.test b/testdata/workloads/functional-planner/queries/PlannerTest/constant-folding.test index 2b2d5ef8b..37b31631a 100644 --- a/testdata/workloads/functional-planner/queries/PlannerTest/constant-folding.test +++ b/testdata/workloads/functional-planner/queries/PlannerTest/constant-folding.test @@ -98,12 +98,12 @@ predicates: float_col != 0 tuple-ids=0 row-size=116B cardinality=500 ==== # Test aggregation. -select sum(1 + 1 + id) sm +select sum(1 + 1 + id) from functional.alltypes group by timestamp_col = cast('2015-11-15' as timestamp) + interval 1 year having 1024 * 1024 * count(*) % 2 = 0 - and (sm > 1 or sm > 1) - and (sm between 5 and 10) + and (sum(1 + 1 + id) > 1 or sum(1 + 1 + id) > 1) + and (sum(1 + 1 + id) between 5 and 10) ---- PLAN F00:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1 | Per-Host Resources: mem-estimate=138.00MB mem-reservation=1.94MB diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/predicate-propagation.test b/testdata/workloads/functional-planner/queries/PlannerTest/predicate-propagation.test index cc29c8c19..09a2993da 100644 --- a/testdata/workloads/functional-planner/queries/PlannerTest/predicate-propagation.test +++ b/testdata/workloads/functional-planner/queries/PlannerTest/predicate-propagation.test @@ -1070,7 +1070,7 @@ inner join (select bigint_col, count(tinyint_col) x, max(smallint_col) y, min(in from functional.alltypessmall group by bigint_col # assigned in agg node and scan of t1 - having x + y > 10) t2 + having count(tinyint_col) + max(smallint_col) > 10) t2 on (t1.id = t2.x and t1.tinyint_col = t2.y) inner join (select count(tinyint_col) x, max(smallint_col) y, min(int_col) z from functional.alltypestiny) t3 diff --git a/testdata/workloads/functional-query/queries/QueryTest/alias.test b/testdata/workloads/functional-query/queries/QueryTest/alias.test new file mode 100644 index 000000000..e14488f5d --- /dev/null +++ b/testdata/workloads/functional-query/queries/QueryTest/alias.test @@ -0,0 +1,87 @@ +==== +---- QUERY +# GROUP BY alias +select int_col / 2 as x from alltypes group by x +---- RESULTS +1.5 +3.5 +4.5 +3 +1 +0.5 +4 +0 +2 +2.5 +---- TYPES +double +==== +---- QUERY +# GROUP BY alias ORDER BY alias +select int_col / 2 as x from alltypes group by x order by x +---- RESULTS +0 +0.5 +1 +1.5 +2 +2.5 +3 +3.5 +4 +4.5 +---- TYPES +double +==== +---- QUERY +# HAVING with bool typed alias +select int_col / 2 as x, not bool_col as nb +from alltypes group by x, nb having nb +---- RESULTS +0.5,true +3.5,true +1.5,true +4.5,true +2.5,true +---- TYPES +double,boolean +==== +---- QUERY +# count(*) alias ORDER BY +select count(*) a from alltypes order by a +---- RESULTS +7300 +---- TYPES +bigint +==== +---- QUERY +# count(*) > 10 alias ORDER BY +select count(*) > 10 a from alltypes order by a +---- RESULTS +true +---- TYPES +boolean +==== +---- QUERY +# count(*) > 10 alias HAVING +select count(*) > 10 a from alltypes having a +---- RESULTS +true +---- TYPES +boolean +==== +---- QUERY +# sum(id) over(order by id) alias ORDER BY +select sum(id) over(order by id) a from alltypestiny order by a +---- RESULTS +0 +1 +3 +6 +10 +15 +21 +28 +---- TYPES +bigint +==== diff --git a/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test b/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test index be75c23ba..dafe9ad38 100644 --- a/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test +++ b/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test @@ -295,7 +295,7 @@ DECIMAL,DECIMAL,DECIMAL # Test AVG() with DECIMAL_V1 set decimal_v2=false; select avg(l_extendedprice) as a from tpch_parquet.lineitem -group by l_tax having a > 38247.190 order by 1; +group by l_tax having avg(l_extendedprice) > 38247.190 order by 1; ---- RESULTS 38250.48 38251.62 @@ -309,7 +309,7 @@ DECIMAL # Test AVG() with DECIMAL_V2 set decimal_v2=true; select avg(l_extendedprice) as a from tpch_parquet.lineitem -group by l_tax having a > 38247.190 order by 1; +group by l_tax having avg(l_extendedprice) > 38247.190 order by 1; ---- RESULTS 38247.196745 38250.487309 diff --git a/testdata/workloads/functional-query/queries/QueryTest/exprs.test b/testdata/workloads/functional-query/queries/QueryTest/exprs.test index a15f3b5d8..50ee288d9 100644 --- a/testdata/workloads/functional-query/queries/QueryTest/exprs.test +++ b/testdata/workloads/functional-query/queries/QueryTest/exprs.test @@ -2622,7 +2622,8 @@ select count(now()) c, avg(cast('2016-11-22 16:40:00.00' as timestamp)) a, from functional_parquet.alltypes where timestamp_col < cast('2013-02-18 20:46:00.01' as timestamp) group by g -having a = cast('2016-11-22 16:40:00.00' as timestamp) +having avg(cast('2016-11-22 16:40:00.00' as timestamp)) = + cast('2016-11-22 16:40:00.00' as timestamp) order by c, cast('2016-11-22 16:40:00.00' as timestamp) ---- RESULTS 7300,2016-11-22 16:40:00,2016-11-22 16:40:00 @@ -2651,8 +2652,8 @@ BIGINT select tinyint_col, count(*) cnt from functional_parquet.alltypesagg group by 1 -having cnt > 1000 or cnt > 1000 - and cnt between 1500 and 2500 +having count(*) > 1000 or count(*) > 1000 + and count(*) between 1500 and 2500 ---- TYPES TINYINT, BIGINT ---- RESULTS diff --git a/testdata/workloads/functional-query/queries/QueryTest/nested-types-tpch.test b/testdata/workloads/functional-query/queries/QueryTest/nested-types-tpch.test index c8a80b227..8ec37535a 100644 --- a/testdata/workloads/functional-query/queries/QueryTest/nested-types-tpch.test +++ b/testdata/workloads/functional-query/queries/QueryTest/nested-types-tpch.test @@ -135,7 +135,7 @@ t1.c_orders t3, t3.item.o_lineitems t4 WHERE t1.c_custkey < 100 AND t2.p_partkey < 100 GROUP BY 1 -HAVING int_col <= 5 +HAVING COALESCE(t2.p_size, t4.pos, o_orderkey) <= 5 ORDER BY 1 ---- RESULTS 1,177 diff --git a/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_highndv.test b/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_highndv.test index 2830837af..3a87d9939 100644 --- a/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_highndv.test +++ b/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_highndv.test @@ -6,7 +6,7 @@ SELECT l_orderkey, count(*) AS cnt FROM lineitem GROUP BY l_orderkey -HAVING cnt > 9999999999999; +HAVING count(*) > 9999999999999; ---- RESULTS ---- TYPES BIGINT,BIGINT diff --git a/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_lowndv.test b/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_lowndv.test index b28d7d6b2..1856804d9 100644 --- a/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_lowndv.test +++ b/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_lowndv.test @@ -6,7 +6,7 @@ SELECT l_linenumber, count(*) AS cnt FROM lineitem GROUP BY l_linenumber -HAVING cnt > 9999999999999; +HAVING count(*) > 9999999999999; ---- RESULTS ---- TYPES ==== diff --git a/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_pk.test b/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_pk.test index f5db9d94d..f45caaa10 100644 --- a/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_pk.test +++ b/testdata/workloads/targeted-perf/queries/primitive_groupby_bigint_pk.test @@ -6,7 +6,7 @@ SELECT l_orderkey, l_partkey, count(*) AS cnt FROM lineitem GROUP BY l_orderkey,l_partkey -HAVING cnt > 9999999999999; +HAVING count(*) > 9999999999999; ---- RESULTS ---- TYPES ==== diff --git a/testdata/workloads/targeted-perf/queries/primitive_groupby_decimal_highndv.test b/testdata/workloads/targeted-perf/queries/primitive_groupby_decimal_highndv.test index cfb976a26..35c584503 100644 --- a/testdata/workloads/targeted-perf/queries/primitive_groupby_decimal_highndv.test +++ b/testdata/workloads/targeted-perf/queries/primitive_groupby_decimal_highndv.test @@ -7,7 +7,7 @@ SELECT l_extendedprice, count(*) AS cnt FROM lineitem GROUP BY l_extendedprice -HAVING cnt > 9999999999999; +HAVING count(*) > 9999999999999; ---- RESULTS ---- TYPES DECIMAL,BIGINT diff --git a/testdata/workloads/targeted-perf/queries/primitive_groupby_decimal_lowndv.test b/testdata/workloads/targeted-perf/queries/primitive_groupby_decimal_lowndv.test index 6398059da..7f18b3ccf 100644 --- a/testdata/workloads/targeted-perf/queries/primitive_groupby_decimal_lowndv.test +++ b/testdata/workloads/targeted-perf/queries/primitive_groupby_decimal_lowndv.test @@ -7,7 +7,7 @@ SELECT l_discount, count(*) AS cnt FROM lineitem GROUP BY l_discount -HAVING cnt > 9999999999999; +HAVING count(*) > 9999999999999; ---- RESULTS ---- TYPES ==== diff --git a/tests/query_test/test_queries.py b/tests/query_test/test_queries.py index 997b59a1d..4667d96e8 100644 --- a/tests/query_test/test_queries.py +++ b/tests/query_test/test_queries.py @@ -110,6 +110,9 @@ class TestQueries(ImpalaTestSuite): def test_subquery(self, vector): self.run_test_case('QueryTest/subquery', vector) + def test_alias(self, vector): + self.run_test_case('QueryTest/alias', vector) + def test_subquery_in_constant_lhs(self, vector): self.run_test_case('QueryTest/subquery-in-constant-lhs', vector)