diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java index 0d934ef..c1af924 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java @@ -46,6 +46,8 @@ import org.antlr.runtime.ClassicToken; import org.antlr.runtime.Token; import org.antlr.runtime.tree.Tree; +import org.antlr.runtime.tree.TreeVisitor; +import org.antlr.runtime.tree.TreeVisitorAction; import org.antlr.runtime.tree.TreeWizard; import org.antlr.runtime.tree.TreeWizard.ContextVisitor; import org.apache.commons.lang.StringUtils; @@ -2423,7 +2425,7 @@ private Operator genHavingPlan(String dest, QB qb, Operator input, output = putOpInsertMap(output, inputRR); return output; } - + private Operator genPlanForSubQueryPredicate( QB qbSQ, ISubQueryJoinInfo subQueryPredicate) throws SemanticException { @@ -13959,13 +13961,80 @@ private RelNode genGBHavingLogicalPlan(QB qb, RelNode srcRel, Map exprToAlias = qbPI.getAllExprToColumnAlias(); + /* + * a mouthful, but safe: + * - a QB is guaranteed to have atleast 1 destination + * - we don't support multi insert, so picking the first dest. + */ + Set aggExprs = qbPI.getDestToAggregationExprs().values() + .iterator().next().keySet(); + + for (Map.Entry selExpr : exprToAlias.entrySet()) { + ASTNode selAST = selExpr.getKey(); + if (!aggExprs.contains(selAST.toStringTree().toLowerCase())) { + continue; + } + final String aliasToCheck = selExpr.getValue(); + final Set aliasReferences = new HashSet(); + TreeVisitorAction action = new TreeVisitorAction() { + + @Override + public Object pre(Object t) { + if (ParseDriver.adaptor.getType(t) == HiveParser.TOK_TABLE_OR_COL) { + Object c = ParseDriver.adaptor.getChild(t, 0); + if (c != null + && ParseDriver.adaptor.getType(c) == HiveParser.Identifier + && ParseDriver.adaptor.getText(c).equals(aliasToCheck)) { + aliasReferences.add(t); + } + } + return t; + } + + @Override + public Object post(Object t) { + return t; + } + }; + new TreeVisitor(ParseDriver.adaptor).visit(havingExpr, action); + + if (aliasReferences.size() > 0) { + String havingClause = SemanticAnalyzer.this.ctx + .getTokenRewriteStream().toString( + havingExpr.getTokenStartIndex(), + havingExpr.getTokenStopIndex()); + String msg = String.format( + "Encountered Select alias '%s' in having clause '%s'" + + " This non standard behavior is not supported with cbo on." + + " Turn off cbo for these queries.", aliasToCheck, + havingClause); + LOG.debug(msg); + throw new OptiqSemanticException(msg); + } + } + + } + private ImmutableMap buildHiveToOptiqColumnMap(RowResolver rr, RelNode rNode) { ImmutableMap.Builder b = new ImmutableMap.Builder(); int i = 0;