diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java index 3c7b707..fbb6968 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java @@ -513,7 +513,10 @@ void validateAndRewriteAST(RowResolver outerQueryRR, String outerQueryAlias, Set outerQryAliases) throws SemanticException { - ASTNode selectClause = (ASTNode) subQueryAST.getChild(1).getChild(1); + ASTNode fromClause = getChildFromSubqueryAST("From", HiveParser.TOK_FROM); + ASTNode insertClause = getChildFromSubqueryAST("Insert", HiveParser.TOK_INSERT); + + ASTNode selectClause = (ASTNode) insertClause.getChild(1); int selectExprStart = 0; if ( selectClause.getChild(0).getType() == HiveParser.TOK_HINTLIST ) { @@ -537,7 +540,7 @@ void validateAndRewriteAST(RowResolver outerQueryRR, * Restriction 17.s :: SubQuery cannot use the same table alias as one used in * the Outer Query. */ - List sqAliases = SubQueryUtils.getTableAliasesInSubQuery(this); + List sqAliases = SubQueryUtils.getTableAliasesInSubQuery(fromClause); String sharedAlias = null; for(String s : sqAliases ) { if ( outerQryAliases.contains(s) ) { @@ -545,7 +548,7 @@ void validateAndRewriteAST(RowResolver outerQueryRR, } } if ( sharedAlias != null) { - ASTNode whereClause = SubQueryUtils.subQueryWhere(subQueryAST); + ASTNode whereClause = SubQueryUtils.subQueryWhere(insertClause); if ( whereClause != null ) { ASTNode u = SubQueryUtils.hasUnQualifiedColumnReferences(whereClause); @@ -581,7 +584,7 @@ void validateAndRewriteAST(RowResolver outerQueryRR, containsAggregationExprs = containsAggregationExprs | ( r == 1 ); } - rewrite(outerQueryRR, forHavingClause, outerQueryAlias); + rewrite(outerQueryRR, forHavingClause, outerQueryAlias, insertClause, selectClause); SubQueryUtils.setOriginDeep(subQueryAST, originalSQASTOrigin); @@ -631,6 +634,16 @@ void validateAndRewriteAST(RowResolver outerQueryRR, } + private ASTNode getChildFromSubqueryAST(String errorMsg, int type) throws SemanticException { + ASTNode childAST = (ASTNode) subQueryAST.getFirstChildWithType(type); + if (childAST == null && errorMsg != null) { + subQueryAST.setOrigin(originalSQASTOrigin); + throw new SemanticException(ErrorMsg.INVALID_SUBQUERY_EXPRESSION.getMsg( + subQueryAST, errorMsg + " clause is missing in SubQuery.")); + } + return childAST; + } + private void setJoinType() { if ( operator.getType() == SubQueryType.NOT_IN || operator.getType() == SubQueryType.NOT_EXISTS ) { @@ -744,7 +757,7 @@ String getNextCorrExprAlias() { * R2.x = min(R1.y) * Where R1 is an outer table reference, and R2 is a SubQuery table reference. * b. When hoisting the correlation predicate to a join predicate, we need to - * rewrite it to be in the form the Join code allows: so the predicte needs + * rewrite it to be in the form the Join code allows: so the predict needs * to contain a qualified column references. * We handle this by generating a new name for the aggregation expression, * like R1._gby_sq_col_1 and adding this mapping to the Outer Query's @@ -753,9 +766,8 @@ String getNextCorrExprAlias() { */ private void rewrite(RowResolver parentQueryRR, boolean forHavingClause, - String outerQueryAlias) throws SemanticException { - ASTNode selectClause = (ASTNode) subQueryAST.getChild(1).getChild(1); - ASTNode whereClause = SubQueryUtils.subQueryWhere(subQueryAST); + String outerQueryAlias, ASTNode insertClause, ASTNode selectClause) throws SemanticException { + ASTNode whereClause = SubQueryUtils.subQueryWhere(insertClause); if ( whereClause == null ) { return; diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java index 089ad78..ab30d31 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java @@ -271,10 +271,9 @@ static int checkAggOrWindowing(ASTNode expressionTree) throws SemanticException return r; } - static List getTableAliasesInSubQuery(QBSubQuery sq) { + static List getTableAliasesInSubQuery(ASTNode fromClause) { List aliases = new ArrayList(); - ASTNode joinAST = (ASTNode) sq.getSubQueryAST().getChild(0); - getTableAliasesInSubQuery((ASTNode) joinAST.getChild(0), aliases); + getTableAliasesInSubQuery((ASTNode) fromClause.getChild(0), aliases); return aliases; } @@ -318,10 +317,10 @@ else if ( type == HiveParser.TOK_TABLE_OR_COL ) { return null; } - static ASTNode subQueryWhere(ASTNode subQueryAST) { - if ( subQueryAST.getChild(1).getChildCount() > 2 && - subQueryAST.getChild(1).getChild(2).getType() == HiveParser.TOK_WHERE ) { - return (ASTNode) subQueryAST.getChild(1).getChild(2); + static ASTNode subQueryWhere(ASTNode insertClause) { + if (insertClause.getChildCount() > 2 && + insertClause.getChild(2).getType() == HiveParser.TOK_WHERE ) { + return (ASTNode) insertClause.getChild(2); } return null; } diff --git ql/src/test/queries/clientnegative/subquery_missing_from.q ql/src/test/queries/clientnegative/subquery_missing_from.q new file mode 100644 index 0000000..3b49ac6 --- /dev/null +++ ql/src/test/queries/clientnegative/subquery_missing_from.q @@ -0,0 +1 @@ +select * from src where src.key in (select key); \ No newline at end of file diff --git ql/src/test/results/clientnegative/subquery_missing_from.q.out ql/src/test/results/clientnegative/subquery_missing_from.q.out new file mode 100644 index 0000000..eaf7735 --- /dev/null +++ ql/src/test/results/clientnegative/subquery_missing_from.q.out @@ -0,0 +1,3 @@ +FAILED: SemanticException Line 0:-1 Invalid SubQuery expression 'key' in definition of SubQuery sq_1 [ +src.key in (select key) +] used as sq_1 at Line 1:32: From clause is missing in SubQuery.