You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by ha...@apache.org on 2013/10/23 16:54:18 UTC

svn commit: r1535040 [1/3] - in /hive/trunk/ql/src: java/org/apache/hadoop/hive/ql/ java/org/apache/hadoop/hive/ql/parse/ test/queries/clientnegative/ test/queries/clientpositive/ test/results/clientnegative/ test/results/clientpositive/

Author: hashutosh
Date: Wed Oct 23 14:54:17 2013
New Revision: 1535040

URL: http://svn.apache.org/r1535040
Log:
HIVE-784 : Support uncorrelated subqueries in the WHERE clause (Harish Butani via Ashutosh Chauhan)

Added:
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java
    hive/trunk/ql/src/test/queries/clientnegative/subquery_exists_implicit_gby.q
    hive/trunk/ql/src/test/queries/clientnegative/subquery_in_groupby.q
    hive/trunk/ql/src/test/queries/clientnegative/subquery_in_select.q
    hive/trunk/ql/src/test/queries/clientnegative/subquery_multiple_cols_in_select.q
    hive/trunk/ql/src/test/queries/clientnegative/subquery_notexists_implicit_gby.q
    hive/trunk/ql/src/test/queries/clientnegative/subquery_subquery_chain.q
    hive/trunk/ql/src/test/queries/clientnegative/subquery_windowing_corr.q
    hive/trunk/ql/src/test/queries/clientnegative/subquery_with_or_cond.q
    hive/trunk/ql/src/test/queries/clientpositive/subquery_exists.q
    hive/trunk/ql/src/test/queries/clientpositive/subquery_in.q
    hive/trunk/ql/src/test/queries/clientpositive/subquery_multiinsert.q
    hive/trunk/ql/src/test/queries/clientpositive/subquery_notexists.q
    hive/trunk/ql/src/test/queries/clientpositive/subquery_notin.q
    hive/trunk/ql/src/test/results/clientnegative/subquery_exists_implicit_gby.q.out
    hive/trunk/ql/src/test/results/clientnegative/subquery_in_groupby.q.out
    hive/trunk/ql/src/test/results/clientnegative/subquery_in_select.q.out
    hive/trunk/ql/src/test/results/clientnegative/subquery_multiple_cols_in_select.q.out
    hive/trunk/ql/src/test/results/clientnegative/subquery_notexists_implicit_gby.q.out
    hive/trunk/ql/src/test/results/clientnegative/subquery_subquery_chain.q.out
    hive/trunk/ql/src/test/results/clientnegative/subquery_windowing_corr.q.out
    hive/trunk/ql/src/test/results/clientnegative/subquery_with_or_cond.q.out
    hive/trunk/ql/src/test/results/clientpositive/subquery_exists.q.out
    hive/trunk/ql/src/test/results/clientpositive/subquery_in.q.out
    hive/trunk/ql/src/test/results/clientpositive/subquery_multiinsert.q.out
    hive/trunk/ql/src/test/results/clientpositive/subquery_notexists.q.out
    hive/trunk/ql/src/test/results/clientpositive/subquery_notin.q.out
Modified:
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java?rev=1535040&r1=1535039&r2=1535040&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java Wed Oct 23 14:54:17 2013
@@ -363,6 +363,8 @@ public enum ErrorMsg {
   INVALID_BIGTABLE_MAPJOIN(10246, "{0} table chosen for streaming is not valid", true),
   MISSING_OVER_CLAUSE(10247, "Missing over clause for function : "),
   PARTITION_SPEC_TYPE_MISMATCH(10248, "Cannot add partition column {0} of type {1} as it cannot be converted to type {2}", true),
+  UNSUPPORTED_SUBQUERY_EXPRESSION(10249, "Unsupported SubQuery Expression"),
+  INVALID_SUBQUERY_EXPRESSION(10250, "Invalid SubQuery expression"),
 
   SCRIPT_INIT_ERROR(20000, "Unable to initialize custom script."),
   SCRIPT_IO_ERROR(20001, "An error occurred while reading or writing to your custom script. "

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g?rev=1535040&r1=1535039&r2=1535040&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g Wed Oct 23 14:54:17 2013
@@ -301,6 +301,10 @@ TOK_WINDOWVALUES;
 TOK_WINDOWRANGE;
 TOK_IGNOREPROTECTION;
 TOK_EXCHANGEPARTITION;
+TOK_SUBQUERY_EXPR;
+TOK_SUBQUERY_OP;
+TOK_SUBQUERY_OP_NOTIN;
+TOK_SUBQUERY_OP_NOTEXISTS;
 }
 
 

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g?rev=1535040&r1=1535039&r2=1535040&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g Wed Oct 23 14:54:17 2013
@@ -371,6 +371,11 @@ precedenceEqualOperator
     precedenceEqualNegatableOperator | EQUAL | EQUAL_NS | NOTEQUAL | LESSTHANOREQUALTO | LESSTHAN | GREATERTHANOREQUALTO | GREATERTHAN
     ;
 
+subQueryExpression 
+    : 
+    LPAREN! selectStatement RPAREN!     
+ ;
+ 
 precedenceEqualExpression
     :
     (left=precedenceBitwiseOrExpression -> $left)
@@ -379,8 +384,12 @@ precedenceEqualExpression
        -> ^(KW_NOT ^(precedenceEqualNegatableOperator $precedenceEqualExpression $notExpr))
     | (precedenceEqualOperator equalExpr=precedenceBitwiseOrExpression)
        -> ^(precedenceEqualOperator $precedenceEqualExpression $equalExpr)
+    | (KW_NOT KW_IN LPAREN KW_SELECT)=>  (KW_NOT KW_IN subQueryExpression) 
+       -> ^(KW_NOT ^(TOK_SUBQUERY_EXPR ^(TOK_SUBQUERY_OP KW_IN) subQueryExpression $precedenceEqualExpression))
     | (KW_NOT KW_IN expressions)
        -> ^(KW_NOT ^(TOK_FUNCTION KW_IN $precedenceEqualExpression expressions))
+    | (KW_IN LPAREN KW_SELECT)=>  (KW_IN subQueryExpression) 
+       -> ^(TOK_SUBQUERY_EXPR ^(TOK_SUBQUERY_OP KW_IN) subQueryExpression $precedenceEqualExpression)
     | (KW_IN expressions)
        -> ^(TOK_FUNCTION KW_IN $precedenceEqualExpression expressions)
     | ( KW_NOT KW_BETWEEN (min=precedenceBitwiseOrExpression) KW_AND (max=precedenceBitwiseOrExpression) )
@@ -388,6 +397,7 @@ precedenceEqualExpression
     | ( KW_BETWEEN (min=precedenceBitwiseOrExpression) KW_AND (max=precedenceBitwiseOrExpression) )
        -> ^(TOK_FUNCTION Identifier["between"] KW_FALSE $left $min $max)
     )*
+    | (KW_EXISTS LPAREN KW_SELECT)=> (KW_EXISTS subQueryExpression) -> ^(TOK_SUBQUERY_EXPR ^(TOK_SUBQUERY_OP KW_EXISTS) subQueryExpression)
     ;
 
 expressions

Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java Wed Oct 23 14:54:17 2013
@@ -0,0 +1,645 @@
+package org.apache.hadoop.hive.ql.parse;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import org.apache.hadoop.hive.ql.Context;
+import org.apache.hadoop.hive.ql.ErrorMsg;
+import org.apache.hadoop.hive.ql.lib.Node;
+import org.apache.hadoop.hive.ql.lib.NodeProcessor;
+import org.apache.hadoop.hive.ql.parse.TypeCheckProcFactory.DefaultExprProcessor;
+import org.apache.hadoop.hive.ql.plan.ExprNodeConstantDesc;
+import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
+
+public class QBSubQuery {
+
+  public static enum SubQueryType {
+    EXISTS,
+    NOT_EXISTS,
+    IN,
+    NOT_IN;
+
+    public static SubQueryType get(ASTNode opNode) throws SemanticException {
+      switch(opNode.getType()) {
+      case HiveParser.KW_EXISTS:
+        return EXISTS;
+      case HiveParser.TOK_SUBQUERY_OP_NOTEXISTS:
+        return NOT_EXISTS;
+      case HiveParser.KW_IN:
+        return IN;
+      case HiveParser.TOK_SUBQUERY_OP_NOTIN:
+        return NOT_IN;
+      default:
+        throw new SemanticException(SemanticAnalyzer.generateErrorMessage(opNode,
+            "Operator not supported in SubQuery use."));
+      }
+    }
+  }
+
+  public static class SubQueryTypeDef {
+    private final ASTNode ast;
+    private final SubQueryType type;
+
+    public SubQueryTypeDef(ASTNode ast, SubQueryType type) {
+      super();
+      this.ast = ast;
+      this.type = type;
+    }
+
+    public ASTNode getAst() {
+      return ast;
+    }
+
+    public SubQueryType getType() {
+      return type;
+    }
+
+  }
+
+  /*
+   * An expression is either the left/right side of an Equality predicate in the SubQuery where
+   * clause; or it is the entire conjunct. For e.g. if the Where Clause for a SubQuery is:
+   * where R1.X = R2.Y and R2.Z > 7
+   * Then the expressions analyzed are R1.X, R2.X ( the left and right sides of the Equality
+   * predicate); and R2.Z > 7.
+   *
+   * The ExprType tracks whether the expr:
+   * - has a reference to a SubQuery table source
+   * - has a reference to Outer(parent) Query table source
+   */
+  static enum ExprType {
+    REFERS_NONE(false, false) {
+      @Override
+      public ExprType combine(ExprType other) {
+        return other;
+      }
+    },
+    REFERS_PARENT(true, false) {
+      @Override
+      public ExprType combine(ExprType other) {
+        switch(other) {
+        case REFERS_SUBQUERY:
+        case REFERS_BOTH:
+          return REFERS_BOTH;
+        default:
+          return this;
+        }
+      }
+    },
+    REFERS_SUBQUERY(false, true) {
+      @Override
+      public ExprType combine(ExprType other) {
+        switch(other) {
+        case REFERS_PARENT:
+        case REFERS_BOTH:
+          return REFERS_BOTH;
+        default:
+          return this;
+        }
+      }
+    },
+    REFERS_BOTH(true,true) {
+      @Override
+      public ExprType combine(ExprType other) {
+        return this;
+      }
+    };
+
+    final boolean refersParent;
+    final boolean refersSubQuery;
+
+    ExprType(boolean refersParent, boolean refersSubQuery) {
+      this.refersParent = refersParent;
+      this.refersSubQuery = refersSubQuery;
+    }
+
+    public boolean refersParent() {
+      return refersParent;
+    }
+    public boolean refersSubQuery() {
+      return refersSubQuery;
+    }
+    public abstract ExprType combine(ExprType other);
+  }
+
+  static class Conjunct {
+    private final ASTNode leftExpr;
+    private final ASTNode rightExpr;
+    private final ExprType leftExprType;
+    private final ExprType rightExprType;
+
+    public Conjunct(ASTNode leftExpr, ASTNode rightExpr, ExprType leftExprType,
+        ExprType rightExprType) {
+      super();
+      this.leftExpr = leftExpr;
+      this.rightExpr = rightExpr;
+      this.leftExprType = leftExprType;
+      this.rightExprType = rightExprType;
+    }
+    public ASTNode getLeftExpr() {
+      return leftExpr;
+    }
+    public ASTNode getRightExpr() {
+      return rightExpr;
+    }
+    public ExprType getLeftExprType() {
+      return leftExprType;
+    }
+    public ExprType getRightExprType() {
+      return rightExprType;
+    }
+
+    boolean eitherSideRefersBoth() {
+      if ( leftExprType == ExprType.REFERS_BOTH ) {
+        return true;
+      } else if ( rightExpr != null ) {
+        return rightExprType == ExprType.REFERS_BOTH;
+      }
+      return false;
+    }
+
+    boolean isCorrelated() {
+      if ( rightExpr != null ) {
+        return leftExprType.combine(rightExprType) == ExprType.REFERS_BOTH;
+      }
+      return false;
+    }
+
+    boolean refersOuterOnly() {
+      if ( rightExpr == null ) {
+        return leftExprType == ExprType.REFERS_PARENT;
+      }
+      return leftExprType.combine(rightExprType) == ExprType.REFERS_PARENT;
+    }
+  }
+
+  class ConjunctAnalyzer {
+    RowResolver parentQueryRR;
+    NodeProcessor defaultExprProcessor;
+    Stack<Node> stack;
+
+    ConjunctAnalyzer(RowResolver parentQueryRR) {
+      this.parentQueryRR = parentQueryRR;
+      defaultExprProcessor = new DefaultExprProcessor();
+      stack = new Stack<Node>();
+    }
+
+    /*
+     * 1. On encountering a DOT, we attempt to resolve the leftmost name
+     *    to the Parent Query.
+     * 2. An unqualified name is assumed to be a SubQuery reference.
+     *    We don't attempt to resolve this to the Parent; because
+     *    we require all Parent column references to be qualified.
+     * 3. All other expressions have a Type based on their children.
+     *    An Expr w/o children is assumed to refer to neither.
+     */
+    private ExprType analyzeExpr(ASTNode expr) {
+      ExprNodeDesc exprNode;
+      if ( expr.getType() == HiveParser.DOT) {
+        ASTNode dot = firstDot(expr);
+        exprNode = resolveDot(dot);
+        if ( exprNode != null ) {
+          return ExprType.REFERS_PARENT;
+        }
+        return ExprType.REFERS_SUBQUERY;
+      } else if ( expr.getType() == HiveParser.TOK_TABLE_OR_COL ) {
+        return ExprType.REFERS_SUBQUERY;
+      } else {
+        ExprType exprType = ExprType.REFERS_NONE;
+        int cnt = expr.getChildCount();
+        for(int i=0; i < cnt; i++) {
+          ASTNode child = (ASTNode) expr.getChild(i);
+          exprType = exprType.combine(analyzeExpr(child));
+        }
+        return exprType;
+      }
+    }
+
+    /*
+     * 1. The only correlation operator we check for is EQUAL; because that is
+     *    the one for which we can do a Algebraic transformation.
+     * 2. For expressions that are not an EQUAL predicate, we treat them as conjuncts
+     *    having only 1 side. These should only contain references to the SubQuery
+     *    table sources.
+     * 3. For expressions that are an EQUAL predicate; we analyze each side and let the
+     *    left and right exprs in the Conjunct object.
+     *
+     * @return Conjunct  contains details on the left and right side of the conjunct expression.
+     */
+    Conjunct analyzeConjunct(ASTNode conjunct) throws SemanticException {
+      int type = conjunct.getType();
+
+      if ( type == HiveParser.EQUAL ) {
+        ASTNode left = (ASTNode) conjunct.getChild(0);
+        ASTNode right = (ASTNode) conjunct.getChild(1);
+        ExprType leftType = analyzeExpr(left);
+        ExprType rightType = analyzeExpr(right);
+
+        return new Conjunct(left, right, leftType, rightType);
+      } else {
+        ExprType sqExprType = analyzeExpr(conjunct);
+        return new Conjunct(conjunct, null, sqExprType, null);
+      }
+    }
+
+    /*
+     * Try to resolve a qualified name as a column reference on the Parent Query's RowResolver.
+     * Apply this logic on the leftmost(first) dot in an AST tree.
+     */
+    protected ExprNodeDesc resolveDot(ASTNode node) {
+      try {
+        TypeCheckCtx tcCtx = new TypeCheckCtx(parentQueryRR);
+        String str = BaseSemanticAnalyzer.unescapeIdentifier(node.getChild(1).getText());
+        ExprNodeDesc idDesc = new ExprNodeConstantDesc(TypeInfoFactory.stringTypeInfo, str);
+        return (ExprNodeDesc)
+            defaultExprProcessor.process(node, stack, tcCtx, (Object) null, idDesc);
+      } catch(SemanticException se) {
+        return null;
+      }
+    }
+
+    /*
+     * We want to resolve the leftmost name to the Parent Query's RR.
+     * Hence we do a left walk down the AST, until we reach the bottom most DOT.
+     */
+    protected ASTNode firstDot(ASTNode dot) {
+      ASTNode firstChild = (ASTNode) dot.getChild(0);
+      if ( firstChild != null && firstChild.getType() == HiveParser.DOT) {
+        return firstDot(firstChild);
+      }
+      return dot;
+    }
+
+  }
+
+  private final String outerQueryId;
+  private final int sqIdx;
+  private final String alias;
+  private final ASTNode subQueryAST;
+  private final ASTNode parentQueryExpression;
+  private final SubQueryTypeDef operator;
+  private boolean containsAggregationExprs;
+  private boolean hasCorrelation;
+  private ASTNode joinConditionAST;
+  private JoinType joinType;
+  private ASTNode postJoinConditionAST;
+  private int numCorrExprsinSQ;
+  private List<ASTNode> subQueryJoinAliasExprs;
+  private transient final ASTNodeOrigin originalSQASTOrigin;
+
+  /*
+   * tracks number of exprs from correlated predicates added to SQ select list.
+   */
+  private int numOfCorrelationExprsAddedToSQSelect;
+
+  private boolean groupbyAddedToSQ;
+
+  public QBSubQuery(String outerQueryId,
+      int sqIdx,
+      ASTNode subQueryAST,
+      ASTNode parentQueryExpression,
+      SubQueryTypeDef operator,
+      ASTNode originalSQAST,
+      Context ctx) {
+    super();
+    this.subQueryAST = subQueryAST;
+    this.parentQueryExpression = parentQueryExpression;
+    this.operator = operator;
+    this.outerQueryId = outerQueryId;
+    this.sqIdx = sqIdx;
+    this.alias = "sq_" + this.sqIdx;
+    this.numCorrExprsinSQ = 0;
+    String s = ctx.getTokenRewriteStream().toString(
+        originalSQAST.getTokenStartIndex(), originalSQAST.getTokenStopIndex());
+    originalSQASTOrigin = new ASTNodeOrigin("SubQuery", alias, s, alias, originalSQAST);
+    numOfCorrelationExprsAddedToSQSelect = 0;
+    groupbyAddedToSQ = false;
+  }
+
+  public ASTNode getSubQueryAST() {
+    return subQueryAST;
+  }
+  public ASTNode getOuterQueryExpression() {
+    return parentQueryExpression;
+  }
+  public SubQueryTypeDef getOperator() {
+    return operator;
+  }
+
+  void validateAndRewriteAST(RowResolver outerQueryRR) throws SemanticException {
+
+    ASTNode selectClause = (ASTNode) subQueryAST.getChild(1).getChild(1);
+
+    int selectExprStart = 0;
+    if ( selectClause.getChild(0).getType() == HiveParser.TOK_HINTLIST ) {
+      selectExprStart = 1;
+    }
+
+    /*
+     * Check.5.h :: For In and Not In the SubQuery must implicitly or
+     * explicitly only contain one select item.
+     */
+    if ( operator.getType() != SubQueryType.EXISTS &&
+        operator.getType() != SubQueryType.NOT_EXISTS &&
+        selectClause.getChildCount() - selectExprStart > 1 ) {
+      throw new SemanticException(ErrorMsg.INVALID_SUBQUERY_EXPRESSION.getMsg(
+          subQueryAST, "SubQuery can contain only 1 item in Select List."));
+    }
+
+    containsAggregationExprs = false;
+    boolean containsWindowing = false;
+    for(int i= selectExprStart; i < selectClause.getChildCount(); i++ ) {
+
+      ASTNode selectItem = (ASTNode) selectClause.getChild(i);
+      int r = SubQueryUtils.checkAggOrWindowing(selectItem);
+
+      containsWindowing = containsWindowing | ( r == 2);
+      containsAggregationExprs = containsAggregationExprs | ( r == 1 );
+    }
+
+    rewrite(outerQueryRR);
+
+    SubQueryUtils.setOriginDeep(subQueryAST, originalSQASTOrigin);
+
+    /*
+     * Restriction.13.m :: In the case of an implied Group By on a
+     * correlated SubQuery, the SubQuery always returns 1 row.
+     * An exists on a SubQuery with an implied GBy will always return true.
+     * Whereas Algebraically transforming to a Join may not return true. See
+     * Specification doc for details.
+     * Similarly a not exists on a SubQuery with a implied GBY will always return false.
+     */
+    if ( operator.getType() == SubQueryType.EXISTS  &&
+        containsAggregationExprs &&
+        groupbyAddedToSQ ) {
+      throw new SemanticException(ErrorMsg.INVALID_SUBQUERY_EXPRESSION.getMsg(
+          subQueryAST,
+          "An Exists predicate on SubQuery with implicit Aggregation(no Group By clause) " +
+          "cannot be rewritten. (predicate will always return true)."));
+    }
+    if ( operator.getType() == SubQueryType.NOT_EXISTS  &&
+        containsAggregationExprs &&
+        groupbyAddedToSQ ) {
+      throw new SemanticException(ErrorMsg.INVALID_SUBQUERY_EXPRESSION.getMsg(
+          subQueryAST,
+          "A Not Exists predicate on SubQuery with implicit Aggregation(no Group By clause) " +
+          "cannot be rewritten. (predicate will always return false)."));
+    }
+
+    /*
+     * Restriction.14.h :: Correlated Sub Queries cannot contain Windowing clauses.
+     */
+    if ( containsWindowing && hasCorrelation ) {
+      throw new SemanticException(ErrorMsg.UNSUPPORTED_SUBQUERY_EXPRESSION.getMsg(
+          subQueryAST, "Correlated Sub Queries cannot contain Windowing clauses."));
+    }
+
+    /*
+     * Check.4.h :: For Exists and Not Exists, the Sub Query must
+     * have 1 or more correlated predicates.
+     */
+    if ( ( operator.getType() == SubQueryType.EXISTS ||
+        operator.getType() == SubQueryType.NOT_EXISTS ) &&
+        !hasCorrelation ) {
+      throw new SemanticException(ErrorMsg.INVALID_SUBQUERY_EXPRESSION.getMsg(
+          subQueryAST, "For Exists/Not Exists operator SubQuery must be Correlated."));
+    }
+
+  }
+
+  private void setJoinType() {
+    if ( operator.getType() == SubQueryType.NOT_IN ||
+        operator.getType() == SubQueryType.NOT_EXISTS ) {
+      joinType = JoinType.LEFTOUTER;
+    } else {
+      joinType = JoinType.LEFTSEMI;
+    }
+  }
+
+  void buildJoinCondition(RowResolver outerQueryRR, RowResolver sqRR) throws SemanticException {
+    ASTNode parentQueryJoinCond = null;
+
+    if ( parentQueryExpression != null ) {
+      parentQueryJoinCond = SubQueryUtils.buildOuterQryToSQJoinCond(
+        getOuterQueryExpression(),
+        alias,
+        sqRR);
+    }
+    joinConditionAST = SubQueryUtils.andAST(parentQueryJoinCond, joinConditionAST);
+    setJoinType();
+
+    if ( joinType == JoinType.LEFTOUTER ) {
+      if ( operator.getType() == SubQueryType.NOT_EXISTS && hasCorrelation ) {
+        postJoinConditionAST = SubQueryUtils.buildPostJoinNullCheck(subQueryJoinAliasExprs);
+      } else if ( operator.getType() == SubQueryType.NOT_IN ) {
+        postJoinConditionAST = SubQueryUtils.buildOuterJoinPostCond(alias, sqRR);
+      }
+    }
+
+    SubQueryUtils.setOriginDeep(joinConditionAST, originalSQASTOrigin);
+    SubQueryUtils.setOriginDeep(postJoinConditionAST, originalSQASTOrigin);
+  }
+
+  ASTNode updateOuterQueryFilter(ASTNode outerQryFilter) {
+    if (postJoinConditionAST == null ) {
+      return outerQryFilter;
+    } else if ( outerQryFilter == null ) {
+      return postJoinConditionAST;
+    }
+    ASTNode node = SubQueryUtils.andAST(outerQryFilter, postJoinConditionAST);
+    node.setOrigin(originalSQASTOrigin);
+    return node;
+  }
+
+  String getNextCorrExprAlias() {
+    return "sq_corr_" + numCorrExprsinSQ++;
+  }
+
+  /*
+   * - If the SubQuery has no where clause, there is nothing to rewrite.
+   * - Decompose SubQuery where clause into list of Top level conjuncts.
+   * - For each conjunct
+   *   - Break down the conjunct into (LeftExpr, LeftExprType, RightExpr,
+   *     RightExprType)
+   *   - If the top level operator is an Equality Operator we will break
+   *     it down into left and right; in all other case there is only a
+   *     lhs.
+   *   - The ExprType is based on whether the Expr. refers to the Parent
+   *     Query table sources, refers to the SubQuery sources or both.
+   *   - We assume an unqualified Column refers to a SubQuery table source.
+   *     This is because we require Parent Column references to be qualified
+   *     within the SubQuery.
+   *   - If the lhs or rhs expr refers to both Parent and SubQuery sources,
+   *     we flag this as Unsupported.
+   *   - If the conjunct as a whole, only refers to the Parent Query sources,
+   *     we flag this as an Error.
+   *   - A conjunct is Correlated if the lhs refers to SubQuery sources and rhs
+   *     refers to Parent Query sources or the reverse.
+   *   - Say the lhs refers to SubQuery and rhs refers to Parent Query sources; the
+   *     other case is handled analogously.
+   *     - remove this conjunct from the SubQuery where clause.
+   *     - for the SubQuery expression(lhs) construct a new alias
+   *     - in the correlated predicate, replace the SubQuery
+   *       expression(lhs) with the alias AST.
+   *     - add this altered predicate to the Join predicate tracked by the
+   *       QBSubQuery object.
+   *     - add the alias AST to a list of subQueryJoinAliasExprs. This
+   *       list is used in the case of Outer Joins to add null check
+   *       predicates to the Outer Query's where clause.
+   *     - Add the SubQuery expression with the alias as a SelectItem to
+   *       the SubQuery's SelectList.
+   *     - In case this SubQuery contains aggregation expressions add this SubQuery
+   *       expression to its GroupBy; add it to the front of the GroupBy.
+   *   - If predicate is not correlated, let it remain in the SubQuery
+   *     where clause.
+   */
+  private void rewrite(RowResolver parentQueryRR) throws SemanticException {
+    ASTNode selectClause = (ASTNode) subQueryAST.getChild(1).getChild(1);
+    ASTNode whereClause = null;
+    if ( subQueryAST.getChild(1).getChildCount() > 2 &&
+        subQueryAST.getChild(1).getChild(2).getType() == HiveParser.TOK_WHERE ) {
+      whereClause = (ASTNode) subQueryAST.getChild(1).getChild(2);
+    }
+
+    if ( whereClause == null ) {
+      return;
+    }
+
+    ASTNode searchCond = (ASTNode) whereClause.getChild(0);
+    List<ASTNode> conjuncts = new ArrayList<ASTNode>();
+    SubQueryUtils.extractConjuncts(searchCond, conjuncts);
+
+    ConjunctAnalyzer conjunctAnalyzer = new ConjunctAnalyzer(parentQueryRR);
+    ASTNode sqNewSearchCond = null;
+
+    for(ASTNode conjunctAST : conjuncts) {
+      Conjunct conjunct = conjunctAnalyzer.analyzeConjunct(conjunctAST);
+
+      /*
+       *  Restriction.11.m :: A SubQuery predicate that refers to an Outer
+       *  Query column must be a valid Join predicate.
+       */
+      if ( conjunct.eitherSideRefersBoth() ) {
+        throw new SemanticException(ErrorMsg.UNSUPPORTED_SUBQUERY_EXPRESSION.getMsg(
+            conjunctAST,
+            "SubQuery expression refers to both Parent and SubQuery expressions and " +
+            "is not a valid join condition."));
+      }
+
+      /*
+       * Check.12.h :: SubQuery predicates cannot only refer to Outer Query columns.
+       */
+      if ( conjunct.refersOuterOnly() ) {
+        throw new SemanticException(ErrorMsg.UNSUPPORTED_SUBQUERY_EXPRESSION.getMsg(
+            conjunctAST,
+            "SubQuery expression refers to Outer query expressions only."));
+      }
+
+      if ( conjunct.isCorrelated() ) {
+        hasCorrelation = true;
+        subQueryJoinAliasExprs = new ArrayList<ASTNode>();
+        String exprAlias = getNextCorrExprAlias();
+        ASTNode sqExprAlias = SubQueryUtils.createAliasAST(exprAlias);
+        ASTNode sqExprForCorr = SubQueryUtils.createColRefAST(alias, exprAlias);
+
+        if ( conjunct.getLeftExprType().refersSubQuery() ) {
+          ASTNode joinPredciate = SubQueryUtils.alterCorrelatedPredicate(
+              conjunctAST, sqExprForCorr, true);
+          joinConditionAST = SubQueryUtils.andAST(joinConditionAST, joinPredciate);
+          subQueryJoinAliasExprs.add(sqExprForCorr);
+          ASTNode selExpr = SubQueryUtils.createSelectItem(conjunct.getLeftExpr(), sqExprAlias);
+          selectClause.addChild(selExpr);
+          numOfCorrelationExprsAddedToSQSelect++;
+          if ( containsAggregationExprs ) {
+            ASTNode gBy = getSubQueryGroupByAST();
+            SubQueryUtils.addGroupExpressionToFront(gBy, conjunct.getLeftExpr());
+          }
+        } else {
+          ASTNode joinPredciate = SubQueryUtils.alterCorrelatedPredicate(
+              conjunctAST, sqExprForCorr, false);
+          joinConditionAST = SubQueryUtils.andAST(joinConditionAST, joinPredciate);
+          subQueryJoinAliasExprs.add(sqExprForCorr);
+          ASTNode selExpr = SubQueryUtils.createSelectItem(conjunct.getRightExpr(), sqExprAlias);
+          selectClause.addChild(selExpr);
+          numOfCorrelationExprsAddedToSQSelect++;
+          if ( containsAggregationExprs ) {
+            ASTNode gBy = getSubQueryGroupByAST();
+            SubQueryUtils.addGroupExpressionToFront(gBy, conjunct.getRightExpr());
+          }
+        }
+      } else {
+        sqNewSearchCond = SubQueryUtils.andAST(sqNewSearchCond, conjunctAST);
+      }
+    }
+
+    if ( sqNewSearchCond != searchCond ) {
+      if ( sqNewSearchCond == null ) {
+        /*
+         * for now just adding a true condition(1=1) to where clause.
+         * Can remove the where clause from the AST; requires moving all subsequent children
+         * left.
+         */
+        sqNewSearchCond = SubQueryUtils.constructTrueCond();
+      }
+      whereClause.setChild(0, sqNewSearchCond);
+    }
+
+  }
+
+  /*
+   * called if the SubQuery is Agg and Correlated.
+   * if SQ doesn't have a GroupBy, it is added to the SQ AST.
+   */
+  private ASTNode getSubQueryGroupByAST() {
+    ASTNode groupBy = null;
+    if ( subQueryAST.getChild(1).getChildCount() > 3 &&
+        subQueryAST.getChild(1).getChild(3).getType() == HiveParser.TOK_GROUPBY ) {
+      groupBy = (ASTNode) subQueryAST.getChild(1).getChild(3);
+    }
+
+    if ( groupBy != null ) {
+      return groupBy;
+    }
+
+    groupBy = SubQueryUtils.buildGroupBy();
+    groupbyAddedToSQ = true;
+
+    List<ASTNode> newChildren = new ArrayList<ASTNode>();
+    newChildren.add(groupBy);
+    if ( subQueryAST.getChildCount() > 3) {
+      for( int i = subQueryAST.getChildCount() - 1; i >= 3; i-- ) {
+        ASTNode child = (ASTNode) subQueryAST.getChild(i);
+        newChildren.add(child);
+      }
+    }
+
+    for(ASTNode child : newChildren ) {
+      subQueryAST.addChild(child);
+    }
+
+    return groupBy;
+  }
+
+
+  public String getOuterQueryId() {
+    return outerQueryId;
+  }
+
+  public JoinType getJoinType() {
+    return joinType;
+  }
+
+  public String getAlias() {
+    return alias;
+  }
+
+  public ASTNode getJoinConditionAST() {
+    return joinConditionAST;
+  }
+
+  public int getNumOfCorrelationExprsAddedToSQSelect() {
+    return numOfCorrelationExprsAddedToSQSelect;
+  }
+}

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java?rev=1535040&r1=1535039&r2=1535040&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java Wed Oct 23 14:54:17 2013
@@ -99,6 +99,7 @@ import org.apache.hadoop.hive.ql.parse.P
 import org.apache.hadoop.hive.ql.parse.PTFInvocationSpec.PartitionSpec;
 import org.apache.hadoop.hive.ql.parse.PTFInvocationSpec.PartitionedTableFunctionSpec;
 import org.apache.hadoop.hive.ql.parse.PTFInvocationSpec.PartitioningSpec;
+import org.apache.hadoop.hive.ql.parse.QBSubQuery.SubQueryType;
 import org.apache.hadoop.hive.ql.parse.WindowingSpec.BoundarySpec;
 import org.apache.hadoop.hive.ql.parse.WindowingSpec.CurrentRowSpec;
 import org.apache.hadoop.hive.ql.parse.WindowingSpec.Direction;
@@ -1758,11 +1759,105 @@ public class SemanticAnalyzer extends Ba
   }
 
   @SuppressWarnings("nls")
-  private Operator genFilterPlan(String dest, QB qb, Operator input)
+  private Operator genFilterPlan(String dest, QB qb, Operator input,
+      Map<String, Operator> aliasToOpInfo)
       throws SemanticException {
 
+    OpParseContext inputCtx = opParseCtx.get(input);
+    RowResolver inputRR = inputCtx.getRowResolver();
     ASTNode whereExpr = qb.getParseInfo().getWhrForClause(dest);
-    return genFilterPlan(qb, (ASTNode) whereExpr.getChild(0), input);
+
+    /*
+     * Handling of SubQuery Expressions:
+     * if "Where clause contains no SubQuery expressions" then
+     *   -->[true] ===CONTINUE_FILTER_PROCESSING===
+     * else
+     *   -->[false] "extract SubQuery expressions\n from Where clause"
+     *   if "this is a nested SubQuery or \nthere are more than 1 SubQuery expressions" then
+     *     -->[yes] "throw Unsupported Error"
+     *   else
+     *     --> "Rewrite Search condition to \nremove SubQuery predicate"
+     *      --> "build QBSubQuery"
+     *        --> "extract correlated predicates \nfrom Where Clause"
+     *        --> "add correlated Items to \nSelect List and Group By"
+     *        --> "construct Join Predicate \nfrom correlation predicates"
+     *     --> "Generate Plan for\n modified SubQuery"
+     *     --> "Build the Join Condition\n for Parent Query to SubQuery join"
+     *     --> "Build the QBJoinTree from the Join condition"
+     *     --> "Update Parent Query Filter\n with any Post Join conditions"
+     *     --> ===CONTINUE_FILTER_PROCESSING===
+     *   endif
+     * endif
+     */
+    ASTNode searchCond = (ASTNode) whereExpr.getChild(0);
+    List<ASTNode> subQueriesInOriginalTree = SubQueryUtils.findSubQueries(searchCond);
+
+    if ( subQueriesInOriginalTree != null ) {
+
+      /*
+       * Restriction.8.m :: We allow only 1 SubQuery expression per Query.
+       */
+      if (subQueriesInOriginalTree.size() > 1 ) {
+
+        throw new SemanticException(ErrorMsg.UNSUPPORTED_SUBQUERY_EXPRESSION.getMsg(
+            subQueriesInOriginalTree.get(1), "Only 1 SubQuery expression is supported."));
+      }
+
+      /*
+       * Clone the Search AST; apply all rewrites on the clone.
+       */
+      ASTNode clonedSearchCond = (ASTNode) ParseDriver.adaptor.dupTree(searchCond);
+      List<ASTNode> subQueries = SubQueryUtils.findSubQueries(clonedSearchCond);
+
+      for(int i=0; i < subQueries.size(); i++) {
+        ASTNode subQueryAST = subQueries.get(i);
+        ASTNode originalSubQueryAST = subQueriesInOriginalTree.get(i);
+
+        int sqIdx = i+1;
+        clonedSearchCond = SubQueryUtils.rewriteParentQueryWhere(clonedSearchCond, subQueryAST);
+
+        QBSubQuery subQuery = SubQueryUtils.buildSubQuery(qb.getId(),
+            sqIdx, subQueryAST, originalSubQueryAST, ctx);
+
+        subQuery.validateAndRewriteAST(inputRR);
+
+        QB qbSQ = new QB(subQuery.getOuterQueryId(), subQuery.getAlias(), true);
+        Phase1Ctx ctx_1 = initPhase1Ctx();
+        doPhase1(subQuery.getSubQueryAST(), qbSQ, ctx_1);
+        getMetaData(qbSQ);
+        Operator sqPlanTopOp = genPlan(qbSQ);
+        aliasToOpInfo.put(subQuery.getAlias(), sqPlanTopOp);
+        RowResolver sqRR = opParseCtx.get(sqPlanTopOp).getRowResolver();
+
+        /*
+         * Check.5.h :: For In and Not In the SubQuery must implicitly or
+         * explicitly only contain one select item.
+         */
+        if ( subQuery.getOperator().getType() != SubQueryType.EXISTS &&
+            subQuery.getOperator().getType() != SubQueryType.NOT_EXISTS &&
+            sqRR.getColumnInfos().size() -
+               subQuery.getNumOfCorrelationExprsAddedToSQSelect() > 1 ) {
+          throw new SemanticException(ErrorMsg.INVALID_SUBQUERY_EXPRESSION.getMsg(
+              subQueryAST, "SubQuery can contain only 1 item in Select List."));
+        }
+
+        /*
+         * Gen Join between outer Operator and SQ op
+         */
+        subQuery.buildJoinCondition(inputRR, sqRR);
+        QBJoinTree joinTree = genSQJoinTree(qb, subQuery,
+            input,
+            aliasToOpInfo);
+        /*
+         * push filters only for this QBJoinTree. Child QBJoinTrees have already been handled.
+         */
+        pushJoinFilters(qb, joinTree, aliasToOpInfo, false);
+        input = genJoinOperator(qbSQ, joinTree, aliasToOpInfo, input);
+        searchCond = subQuery.updateOuterQueryFilter(clonedSearchCond);
+      }
+    }
+
+    return genFilterPlan(qb, searchCond, input);
   }
 
   /**
@@ -4038,7 +4133,8 @@ public class SemanticAnalyzer extends Ba
   }
 
   @SuppressWarnings({"nls"})
-  private Operator genGroupByPlan1ReduceMultiGBY(List<String> dests, QB qb, Operator input)
+  private Operator genGroupByPlan1ReduceMultiGBY(List<String> dests, QB qb, Operator input,
+      Map<String, Operator> aliasToOpInfo)
       throws SemanticException {
 
     QBParseInfo parseInfo = qb.getParseInfo();
@@ -4118,7 +4214,7 @@ public class SemanticAnalyzer extends Ba
       curr = forwardOp;
 
       if (parseInfo.getWhrForClause(dest) != null) {
-        curr = genFilterPlan(dest, qb, forwardOp);
+        curr = genFilterPlan(dest, qb, forwardOp, aliasToOpInfo);
       }
 
       // Generate GroupbyOperator
@@ -6035,17 +6131,21 @@ public class SemanticAnalyzer extends Ba
   }
 
   private Operator genJoinOperator(QB qb, QBJoinTree joinTree,
-      Map<String, Operator> map) throws SemanticException {
+      Map<String, Operator> map,
+      Operator joiningOp) throws SemanticException {
     QBJoinTree leftChild = joinTree.getJoinSrc();
-    Operator joinSrcOp = null;
-    if (leftChild != null) {
-      Operator joinOp = genJoinOperator(qb, leftChild, map);
+    Operator joinSrcOp = joiningOp instanceof JoinOperator ? joiningOp : null;
+
+    if (joinSrcOp == null && leftChild != null) {
+      joinSrcOp = genJoinOperator(qb, leftChild, map, null);
+    }
+
+    if ( joinSrcOp != null ) {
       ArrayList<ASTNode> filter = joinTree.getFiltersForPushing().get(0);
       for (ASTNode cond : filter) {
-        joinOp = genFilterPlan(qb, cond, joinOp);
+        joinSrcOp = genFilterPlan(qb, cond, joinSrcOp);
       }
-
-      joinSrcOp = genJoinReduceSinkChild(qb, joinTree, joinOp, null, 0);
+      joinSrcOp = genJoinReduceSinkChild(qb, joinTree, joinSrcOp, null, 0);
     }
 
     Operator[] srcOps = new Operator[joinTree.getBaseSrc().length];
@@ -6240,7 +6340,7 @@ public class SemanticAnalyzer extends Ba
   private Operator genJoinPlan(QB qb, Map<String, Operator> map)
       throws SemanticException {
     QBJoinTree joinTree = qb.getQbJoinTree();
-    Operator joinOp = genJoinOperator(qb, joinTree, map);
+    Operator joinOp = genJoinOperator(qb, joinTree, map, null);
     return joinOp;
   }
 
@@ -6250,8 +6350,20 @@ public class SemanticAnalyzer extends Ba
    */
   private void pushJoinFilters(QB qb, QBJoinTree joinTree,
       Map<String, Operator> map) throws SemanticException {
-    if (joinTree.getJoinSrc() != null) {
-      pushJoinFilters(qb, joinTree.getJoinSrc(), map);
+    pushJoinFilters(qb, joinTree, map, true);
+  }
+
+  /**
+   * Extract the filters from the join condition and push them on top of the
+   * source operators. This procedure traverses the query tree recursively,
+   */
+  private void pushJoinFilters(QB qb, QBJoinTree joinTree,
+      Map<String, Operator> map,
+      boolean recursively) throws SemanticException {
+    if ( recursively ) {
+      if (joinTree.getJoinSrc() != null) {
+        pushJoinFilters(qb, joinTree.getJoinSrc(), map);
+      }
     }
     ArrayList<ArrayList<ASTNode>> filters = joinTree.getFiltersForPushing();
     int pos = 0;
@@ -6404,6 +6516,134 @@ public class SemanticAnalyzer extends Ba
     return joinTree;
   }
 
+  /*
+   * Setup a QBJoinTree between a SubQuery and its Parent Query. The Parent Query
+   * is the lhs of the Join.
+   *
+   * The Parent Query is represented by the last Operator needed to process its From Clause.
+   * In case of a single table Query this will be a TableScan, but it can be a Join Operator
+   * if the Parent Query contains Join clauses, or in case of a single source from clause,
+   * the source could be a SubQuery or a PTF invocation.
+   *
+   * We setup the QBJoinTree with the above constrains in place. So:
+   * - the lhs of the QBJoinTree can be a another QBJoinTree if the Parent Query operator
+   *   is a JoinOperator. In this case we get its QBJoinTree from the 'joinContext'
+   * - the rhs is always a reference to the SubQuery. Its alias is obtained from the
+   *   QBSubQuery object.
+   *
+   * The QBSubQuery also provides the Joining Condition AST. The Joining Condition has been
+   * transformed in QBSubQuery setup, before this call. The Joining condition has any correlated
+   * predicates and a predicate for joining the Parent Query expression with the SubQuery.
+   *
+   * The QBSubQuery also specifies what kind of Join to construct.
+   *
+   * Given this information, once we initialize the QBJoinTree, we call the 'parseJoinCondition'
+   * method to validate and parse Join conditions.
+   */
+  private QBJoinTree genSQJoinTree(QB qb, QBSubQuery subQuery,
+      Operator joiningOp,
+      Map<String, Operator> aliasToOpInfo)
+          throws SemanticException {
+    QBJoinTree joinTree = new QBJoinTree();
+    JoinCond[] condn = new JoinCond[1];
+
+    switch (subQuery.getJoinType()) {
+    case LEFTOUTER:
+      joinTree.setNoOuterJoin(false);
+      condn[0] = new JoinCond(0, 1, JoinType.LEFTOUTER);
+      break;
+    case RIGHTOUTER:
+      joinTree.setNoOuterJoin(false);
+      condn[0] = new JoinCond(0, 1, JoinType.RIGHTOUTER);
+      break;
+    case FULLOUTER:
+      joinTree.setNoOuterJoin(false);
+      condn[0] = new JoinCond(0, 1, JoinType.FULLOUTER);
+      break;
+    case LEFTSEMI:
+      joinTree.setNoSemiJoin(false);
+      condn[0] = new JoinCond(0, 1, JoinType.LEFTSEMI);
+      break;
+    default:
+      condn[0] = new JoinCond(0, 1, JoinType.INNER);
+      joinTree.setNoOuterJoin(true);
+      break;
+    }
+    joinTree.setJoinCond(condn);
+
+    if ( joiningOp instanceof JoinOperator ) {
+      QBJoinTree leftTree = joinContext.get(joiningOp);
+      joinTree.setJoinSrc(leftTree);
+      String[] leftChildAliases = leftTree.getLeftAliases();
+      String leftAliases[] = new String[leftChildAliases.length + 1];
+      for (int i = 0; i < leftChildAliases.length; i++) {
+        leftAliases[i] = leftChildAliases[i];
+      }
+      leftAliases[leftChildAliases.length] = leftTree.getRightAliases()[0];
+      joinTree.setLeftAliases(leftAliases);
+    } else {
+      String alias = unescapeIdentifier(
+          SubQueryUtils.getAlias(joiningOp, aliasToOpInfo).toLowerCase());
+      joinTree.setLeftAlias(alias);
+      String[] leftAliases = new String[1];
+      leftAliases[0] = alias;
+      joinTree.setLeftAliases(leftAliases);
+      String[] children = new String[2];
+      children[0] = alias;
+      joinTree.setBaseSrc(children);
+      joinTree.setId(qb.getId());
+      joinTree.getAliasToOpInfo().put(
+          getModifiedAlias(qb, alias), aliasToOpInfo.get(alias));
+    }
+
+    String rightalias = unescapeIdentifier(subQuery.getAlias().toLowerCase());
+    String[] rightAliases = new String[1];
+    rightAliases[0] = rightalias;
+    joinTree.setRightAliases(rightAliases);
+    String[] children = joinTree.getBaseSrc();
+    if (children == null) {
+      children = new String[2];
+    }
+    children[1] = rightalias;
+    joinTree.setBaseSrc(children);
+    joinTree.setId(qb.getId());
+    joinTree.getAliasToOpInfo().put(
+        getModifiedAlias(qb, rightalias), aliasToOpInfo.get(rightalias));
+    // remember rhs table for semijoin
+    if (joinTree.getNoSemiJoin() == false) {
+      joinTree.addRHSSemijoin(rightalias);
+    }
+
+    ArrayList<ArrayList<ASTNode>> expressions = new ArrayList<ArrayList<ASTNode>>();
+    expressions.add(new ArrayList<ASTNode>());
+    expressions.add(new ArrayList<ASTNode>());
+    joinTree.setExpressions(expressions);
+
+    ArrayList<Boolean> nullsafes = new ArrayList<Boolean>();
+    joinTree.setNullSafes(nullsafes);
+
+    ArrayList<ArrayList<ASTNode>> filters = new ArrayList<ArrayList<ASTNode>>();
+    filters.add(new ArrayList<ASTNode>());
+    filters.add(new ArrayList<ASTNode>());
+    joinTree.setFilters(filters);
+    joinTree.setFilterMap(new int[2][]);
+
+    ArrayList<ArrayList<ASTNode>> filtersForPushing =
+        new ArrayList<ArrayList<ASTNode>>();
+    filtersForPushing.add(new ArrayList<ASTNode>());
+    filtersForPushing.add(new ArrayList<ASTNode>());
+    joinTree.setFiltersForPushing(filtersForPushing);
+
+    ASTNode joinCond = subQuery.getJoinConditionAST();
+    ArrayList<String> leftSrc = new ArrayList<String>();
+    parseJoinCondition(joinTree, joinCond, leftSrc);
+    if (leftSrc.size() == 1) {
+      joinTree.setLeftAlias(leftSrc.get(0));
+    }
+
+    return joinTree;
+  }
+
   private QBJoinTree genJoinTree(QB qb, ASTNode joinParseTree,
       Map<String, Operator> aliasToOpInfo)
       throws SemanticException {
@@ -7194,7 +7434,8 @@ public class SemanticAnalyzer extends Ba
   }
 
   @SuppressWarnings("nls")
-  private Operator genBodyPlan(QB qb, Operator input) throws SemanticException {
+  private Operator genBodyPlan(QB qb, Operator input, Map<String, Operator> aliasToOpInfo)
+      throws SemanticException {
     QBParseInfo qbp = qb.getParseInfo();
 
     TreeSet<String> ks = new TreeSet<String>(qbp.getClauseNames());
@@ -7290,7 +7531,7 @@ public class SemanticAnalyzer extends Ba
               curr = inputs.get(dest);
 
               if (qbp.getWhrForClause(dest) != null) {
-                curr = genFilterPlan(dest, qb, curr);
+                curr = genFilterPlan(dest, qb, curr, aliasToOpInfo);
               }
 
               if (qbp.getAggregationExprsForClause(dest).size() != 0
@@ -7320,7 +7561,7 @@ public class SemanticAnalyzer extends Ba
               curr = genPostGroupByBodyPlan(curr, dest, qb);
             }
           } else {
-            curr = genGroupByPlan1ReduceMultiGBY(commonGroupByDestGroup, qb, input);
+            curr = genGroupByPlan1ReduceMultiGBY(commonGroupByDestGroup, qb, input, aliasToOpInfo);
           }
         }
       }
@@ -8120,7 +8361,7 @@ public class SemanticAnalyzer extends Ba
       srcOpInfo = lastPTFOp != null ? lastPTFOp : srcOpInfo;
     }
 
-    Operator bodyOpInfo = genBodyPlan(qb, srcOpInfo);
+    Operator bodyOpInfo = genBodyPlan(qb, srcOpInfo, aliasToOpInfo);
 
     if (LOG.isDebugEnabled()) {
       LOG.debug("Created Plan for Query Block " + qb.getId());

Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java Wed Oct 23 14:54:17 2013
@@ -0,0 +1,418 @@
+package org.apache.hadoop.hive.ql.parse;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.antlr.runtime.tree.TreeWizard;
+import org.antlr.runtime.tree.TreeWizard.ContextVisitor;
+import org.apache.hadoop.hive.ql.Context;
+import org.apache.hadoop.hive.ql.ErrorMsg;
+import org.apache.hadoop.hive.ql.exec.ColumnInfo;
+import org.apache.hadoop.hive.ql.exec.FunctionRegistry;
+import org.apache.hadoop.hive.ql.exec.Operator;
+import org.apache.hadoop.hive.ql.parse.QBSubQuery.SubQueryType;
+import org.apache.hadoop.hive.ql.parse.QBSubQuery.SubQueryTypeDef;
+
+public class SubQueryUtils {
+
+  static void extractConjuncts(ASTNode node, List<ASTNode> conjuncts) {
+    if (node.getType() != HiveParser.KW_AND ) {
+      conjuncts.add(node);
+      return;
+    }
+    extractConjuncts((ASTNode)node.getChild(0), conjuncts);
+    extractConjuncts((ASTNode)node.getChild(1), conjuncts);
+  }
+
+  /*
+   * Remove the SubQuery from the Where CLause Tree.
+   * return the remaining WhereClause.
+   */
+  static ASTNode rewriteParentQueryWhere(ASTNode whereCond, ASTNode subQuery)
+      throws SemanticException {
+    ParentQueryWhereClauseRewrite rewrite =
+        new ParentQueryWhereClauseRewrite(whereCond, subQuery);
+    return rewrite.remove();
+  }
+
+  static ASTNode constructTrueCond() {
+    ASTNode eq = (ASTNode) ParseDriver.adaptor.create(HiveParser.EQUAL, "=");
+    ASTNode lhs = (ASTNode) ParseDriver.adaptor.create(HiveParser.Number, "1");
+    ASTNode rhs = (ASTNode) ParseDriver.adaptor.create(HiveParser.Number, "1");
+    ParseDriver.adaptor.addChild(eq, lhs);
+    ParseDriver.adaptor.addChild(eq, rhs);
+    return eq;
+  }
+
+  static ASTNode andAST(ASTNode left, ASTNode right) {
+    if ( left == null ) {
+      return right;
+    } else if ( right == null ) {
+      return left;
+    } else {
+      Object o = ParseDriver.adaptor.create(HiveParser.KW_AND, "AND");
+      ParseDriver.adaptor.addChild(o, left);
+      ParseDriver.adaptor.addChild(o, right);
+      return (ASTNode) o;
+    }
+  }
+
+  static ASTNode orAST(ASTNode left, ASTNode right) {
+    if ( left == null ) {
+      return right;
+    } else if ( right == null ) {
+      return left;
+    } else {
+      Object o = ParseDriver.adaptor.create(HiveParser.KW_OR, "OR");
+      ParseDriver.adaptor.addChild(o, left);
+      ParseDriver.adaptor.addChild(o, right);
+      return (ASTNode) o;
+    }
+  }
+
+  static ASTNode isNull(ASTNode expr) {
+    ASTNode node = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_FUNCTION, "TOK_FUNCTION");
+    node.addChild((ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_ISNULL, "TOK_ISNULL"));
+    node.addChild(expr);
+    return node;
+  }
+
+
+  /*
+   * Check that SubQuery is a top level conjuncts.
+   * Remove it from the Where Clause AST.
+   */
+  static class ParentQueryWhereClauseRewrite {
+    ASTNode root;
+    ASTNode subQuery;
+
+    ParentQueryWhereClauseRewrite(ASTNode root, ASTNode subQuery) {
+      this.root = root;
+      this.subQuery = subQuery;
+    }
+
+    ASTNode getParentInWhereClause(ASTNode node) {
+      if (node == null || node == root) {
+        return null;
+      }
+      return (ASTNode) node.getParent();
+    }
+
+    boolean removeSubQuery(ASTNode node) {
+      if (node.getType() == HiveParser.KW_AND) {
+        boolean r = removeSubQuery((ASTNode) node.getChild(0));
+        if (!r) {
+          r = removeSubQuery((ASTNode) node.getChild(1));
+        }
+        return r;
+      } else if (node.getType() == HiveParser.KW_NOT) {
+        ASTNode child = (ASTNode) node.getChild(0);
+        if (child == subQuery) {
+          ASTNode sqOpType = (ASTNode) subQuery.getChild(0).getChild(0);
+          if (sqOpType.getType() == HiveParser.KW_EXISTS) {
+            sqOpType.getToken().setType(HiveParser.TOK_SUBQUERY_OP_NOTEXISTS);
+          } else {
+            sqOpType.getToken().setType(HiveParser.TOK_SUBQUERY_OP_NOTIN);
+          }
+          ASTNode parent = getParentInWhereClause(node);
+          if (parent == null) {
+            root = subQuery;
+          } else {
+            int nodeIdx = node.getChildIndex();
+            parent.setChild(nodeIdx, subQuery);
+          }
+          return removeSubQuery(subQuery);
+
+        }
+        return false;
+      } else if (node == subQuery) {
+        ASTNode parent = getParentInWhereClause(node);
+        ASTNode gParent = getParentInWhereClause(parent);
+        ASTNode sibling = null;
+
+        if (parent != null) {
+          if (subQuery.getChildIndex() == 0) {
+            sibling = (ASTNode) parent.getChild(1);
+          } else {
+            sibling = (ASTNode) parent.getChild(0);
+          }
+        }
+
+        /*
+         * SubQuery was only condition in where clause
+         */
+        if (sibling == null) {
+          root = constructTrueCond();
+        } // SubQuery was just one conjunct
+        else if (gParent == null) {
+          root = sibling;
+        } else {
+          // otherwise replace parent by sibling.
+          int pIdx = parent.getChildIndex();
+          gParent.setChild(pIdx, sibling);
+        }
+        return true;
+      } else {
+        return false;
+      }
+    }
+
+    ASTNode remove() throws SemanticException {
+      boolean r = removeSubQuery(root);
+      if (r) {
+        return root;
+      }
+      /*
+       *  Restriction.7.h :: SubQuery predicates can appear only as top level conjuncts.
+       */
+      throw new SemanticException(ErrorMsg.UNSUPPORTED_SUBQUERY_EXPRESSION.getMsg(
+          subQuery, "Only SubQuery expressions that are top level conjuncts are allowed"));
+    }
+  }
+
+  static List<ASTNode> findSubQueries(ASTNode node)
+      throws SemanticException {
+    TreeWizard tw = new TreeWizard(ParseDriver.adaptor, HiveParser.tokenNames);
+    SubQueryVisitor visitor = new SubQueryVisitor();
+    tw.visit(node, HiveParser.TOK_SUBQUERY_EXPR, visitor);
+    return visitor.getSubQueries();
+  }
+
+  static class SubQueryVisitor implements ContextVisitor {
+    String errMsg;
+    boolean throwError = false;
+    ASTNode errorNode;
+    List<ASTNode> subQueries;
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public void visit(Object t, Object parent, int childIndex, Map labels) {
+      if (subQueries == null ) {
+        subQueries = new ArrayList<ASTNode>();
+      }
+      subQueries.add((ASTNode)t);
+    }
+
+    public List<ASTNode> getSubQueries() {
+      return subQueries;
+    }
+
+  }
+
+  static QBSubQuery buildSubQuery(String outerQueryId,
+      int sqIdx,
+      ASTNode sqAST,
+      ASTNode originalSQAST,
+      Context ctx) throws SemanticException {
+    ASTNode sqOp = (ASTNode) sqAST.getChild(0);
+    ASTNode sq = (ASTNode) sqAST.getChild(1);
+    ASTNode outerQueryExpr = (ASTNode) sqAST.getChild(2);
+   return new QBSubQuery(outerQueryId, sqIdx, sq, outerQueryExpr,
+       buildSQOperator(sqOp),
+       originalSQAST,
+       ctx);
+  }
+
+  static SubQueryTypeDef buildSQOperator(ASTNode astSQOp) throws SemanticException {
+    ASTNode opAST = (ASTNode) astSQOp.getChild(0);
+    SubQueryType type = SubQueryType.get(opAST);
+    return new SubQueryTypeDef(opAST, type);
+  }
+
+  /*
+   * is this expr a UDAF invocation; does it imply windowing
+   * @return
+   * 0 if implies neither
+   * 1 if implies aggregation
+   * 2 if implies windowing
+   */
+  static int checkAggOrWindowing(ASTNode expressionTree) throws SemanticException {
+    int exprTokenType = expressionTree.getToken().getType();
+    if (exprTokenType == HiveParser.TOK_FUNCTION
+        || exprTokenType == HiveParser.TOK_FUNCTIONDI
+        || exprTokenType == HiveParser.TOK_FUNCTIONSTAR) {
+      assert (expressionTree.getChildCount() != 0);
+      if (expressionTree.getChild(expressionTree.getChildCount()-1).getType()
+          == HiveParser.TOK_WINDOWSPEC) {
+        return 2;
+      }
+      if (expressionTree.getChild(0).getType() == HiveParser.Identifier) {
+        String functionName = SemanticAnalyzer.unescapeIdentifier(expressionTree.getChild(0)
+            .getText());
+        if (FunctionRegistry.getGenericUDAFResolver(functionName) != null) {
+          return 1;
+        }
+      }
+    }
+    int r = 0;
+    for (int i = 0; i < expressionTree.getChildCount(); i++) {
+      int c = checkAggOrWindowing((ASTNode) expressionTree.getChild(i));
+      r = Math.max(r, c);
+    }
+    return r;
+  }
+
+  static List<String> getTableAliasesInSubQuery(QBSubQuery sq) {
+    List<String> aliases = new ArrayList<String>();
+    ASTNode joinAST = (ASTNode) sq.getSubQueryAST().getChild(0);
+    getTableAliasesInSubQuery((ASTNode) joinAST.getChild(0), aliases);
+    return aliases;
+  }
+
+  private static void getTableAliasesInSubQuery(ASTNode joinNode, List<String> aliases) {
+
+    if ((joinNode.getToken().getType() == HiveParser.TOK_TABREF)
+        || (joinNode.getToken().getType() == HiveParser.TOK_SUBQUERY)
+        || (joinNode.getToken().getType() == HiveParser.TOK_PTBLFUNCTION)) {
+      String tableName = SemanticAnalyzer.getUnescapedUnqualifiedTableName((ASTNode) joinNode.getChild(0))
+          .toLowerCase();
+      String alias = joinNode.getChildCount() == 1 ? tableName
+          : SemanticAnalyzer.unescapeIdentifier(joinNode.getChild(joinNode.getChildCount() - 1)
+          .getText().toLowerCase());
+      alias = (joinNode.getToken().getType() == HiveParser.TOK_PTBLFUNCTION) ?
+          SemanticAnalyzer.unescapeIdentifier(joinNode.getChild(1).getText().toLowerCase()) :
+            alias;
+      aliases.add(alias);
+    } else {
+      ASTNode left = (ASTNode) joinNode.getChild(0);
+      ASTNode right = (ASTNode) joinNode.getChild(1);
+      getTableAliasesInSubQuery(left, aliases);
+      getTableAliasesInSubQuery(right, aliases);
+    }
+  }
+
+  /*
+   * construct the ASTNode for the SQ column that will join with the OuterQuery Expression.
+   * So for 'select ... from R1 where A in (select B from R2...)'
+   * this will build (= outerQueryExpr 'ast returned by call to buildSQJoinExpr')
+   */
+  static ASTNode buildOuterQryToSQJoinCond(ASTNode outerQueryExpr,
+      String sqAlias,
+      RowResolver sqRR) {
+    ASTNode node = (ASTNode) ParseDriver.adaptor.create(HiveParser.EQUAL, "=");
+    node.addChild(outerQueryExpr);
+    node.addChild(buildSQJoinExpr(sqAlias, sqRR, false));
+    return node;
+  }
+
+  /*
+   * construct the ASTNode for the SQ column that will join with the OuterQuery Expression.
+   * So for 'select ... from R1 where A in (select B from R2...)'
+   * this will build (. (TOK_TABLE_OR_COL Identifier[SQ_1]) Identifier[B])
+   * where 'SQ_1' is the alias generated for the SubQuery.
+   */
+  static ASTNode buildSQJoinExpr(String sqAlias, RowResolver sqRR,
+      boolean useInternalName) {
+
+    List<ColumnInfo> signature = sqRR.getRowSchema().getSignature();
+    ColumnInfo joinColumn = signature.get(0);
+    String[] joinColName = sqRR.reverseLookup(joinColumn.getInternalName());
+    return createColRefAST(sqAlias, useInternalName ?
+        joinColumn.getInternalName() : joinColName[1]);
+  }
+
+  static ASTNode buildOuterJoinPostCond(String sqAlias, RowResolver sqRR) {
+    return isNull(buildSQJoinExpr(sqAlias, sqRR, false));
+  }
+
+  @SuppressWarnings("rawtypes")
+  static String getAlias(Operator o, Map<String, Operator> aliasToOpInfo) {
+    for(Map.Entry<String, Operator> e : aliasToOpInfo.entrySet()) {
+      if ( e.getValue() == o) {
+        return e.getKey();
+      }
+    }
+    return null;
+  }
+
+  static ASTNode createColRefAST(String tabAlias, String colName) {
+    ASTNode dot = (ASTNode) ParseDriver.adaptor.create(HiveParser.DOT, ".");
+    ASTNode tabAst = createTabRefAST(tabAlias);
+    ASTNode colAst = (ASTNode) ParseDriver.adaptor.create(HiveParser.Identifier, colName);
+    dot.addChild(tabAst);
+    dot.addChild(colAst);
+    return dot;
+  }
+
+  static ASTNode createAliasAST(String colName) {
+    return (ASTNode) ParseDriver.adaptor.create(HiveParser.Identifier, colName);
+  }
+
+  static ASTNode createTabRefAST(String tabAlias) {
+    ASTNode tabAst = (ASTNode)
+        ParseDriver.adaptor.create(HiveParser.TOK_TABLE_OR_COL, "TOK_TABLE_OR_COL");
+    ASTNode tabName = (ASTNode) ParseDriver.adaptor.create(HiveParser.Identifier, tabAlias);
+    tabAst.addChild(tabName);
+    return tabAst;
+  }
+
+  static ASTNode buildSelectExpr(ASTNode expression) {
+    ASTNode selAst = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_SELEXPR, "TOK_SELEXPR");
+    selAst.addChild(expression);
+    return selAst;
+  }
+
+  static ASTNode buildGroupBy() {
+    ASTNode gBy = (ASTNode) ParseDriver.adaptor.create(HiveParser.TOK_GROUPBY, "TOK_GROUPBY");
+    return gBy;
+  }
+
+  static ASTNode createSelectItem(ASTNode expr, ASTNode alias) {
+    ASTNode selectItem = (ASTNode)
+        ParseDriver.adaptor.create(HiveParser.TOK_SELEXPR, "TOK_SELEXPR");
+    selectItem.addChild(expr);
+    selectItem.addChild(alias);
+    return selectItem;
+  }
+
+  static ASTNode alterCorrelatedPredicate(ASTNode correlatedExpr, ASTNode sqAlias, boolean left) {
+    if ( left ) {
+      correlatedExpr.setChild(0, sqAlias);
+    } else {
+      correlatedExpr.setChild(1, sqAlias);
+    }
+    return correlatedExpr;
+  }
+
+  static void addGroupExpressionToFront(ASTNode gBy, ASTNode expr) {
+    ASTNode grpExpr = (ASTNode)
+        ParseDriver.adaptor.create(HiveParser.TOK_GROUPING_SETS_EXPRESSION,
+            "TOK_GROUPING_SETS_EXPRESSION");
+    grpExpr.addChild(expr);
+    List<ASTNode> newChildren = new ArrayList<ASTNode>();
+    newChildren.add(expr);
+    int i = gBy.getChildCount() - 1;
+    while ( i >= 0 ) {
+      newChildren.add((ASTNode) gBy.deleteChild(i));
+      i--;
+    }
+    for(ASTNode child : newChildren ) {
+      gBy.addChild(child);
+    }
+  }
+
+  static ASTNode buildPostJoinNullCheck(List<ASTNode> subQueryJoinAliasExprs) {
+    ASTNode check = null;
+    for(ASTNode expr : subQueryJoinAliasExprs) {
+      check = orAST(check, isNull(expr));
+    }
+    return check;
+  }
+
+  static void setOriginDeep(ASTNode node, ASTNodeOrigin origin) {
+    if ( node == null ) {
+      return;
+    }
+    node.setOrigin(origin);
+    int childCnt = node.getChildCount();
+    for(int i=0; i<childCnt; i++) {
+      setOriginDeep((ASTNode)node.getChild(i), origin);
+    }
+  }
+
+}
+
+
+
+

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java?rev=1535040&r1=1535039&r2=1535040&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java Wed Oct 23 14:54:17 2013
@@ -70,6 +70,7 @@ import org.apache.hadoop.hive.serde2.typ
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
 import org.apache.hadoop.hive.serde2.typeinfo.VarcharTypeInfo;
 
+
 /**
  * The Factory for creating typecheck processors. The typecheck processors are
  * used to processes the syntax trees for expressions and convert them into
@@ -156,13 +157,16 @@ public final class TypeCheckProcFactory 
         + "%|" + HiveParser.KW_IF + "%|" + HiveParser.KW_CASE + "%|"
         + HiveParser.KW_WHEN + "%|" + HiveParser.KW_IN + "%|"
         + HiveParser.KW_ARRAY + "%|" + HiveParser.KW_MAP + "%|"
-        + HiveParser.KW_STRUCT + "%"),
+        + HiveParser.KW_STRUCT + "%|" + HiveParser.KW_EXISTS + "%|"
+        + HiveParser.TOK_SUBQUERY_OP_NOTIN + "%"),
         getStrExprProcessor());
     opRules.put(new RuleRegExp("R4", HiveParser.KW_TRUE + "%|"
         + HiveParser.KW_FALSE + "%"), getBoolExprProcessor());
     opRules.put(new RuleRegExp("R5", HiveParser.TOK_DATELITERAL + "%"), getDateExprProcessor());
     opRules.put(new RuleRegExp("R6", HiveParser.TOK_TABLE_OR_COL + "%"),
         getColumnExprProcessor());
+    opRules.put(new RuleRegExp("R7", HiveParser.TOK_SUBQUERY_OP + "%"),
+        getSubQueryExprProcessor());
 
     // The dispatcher fires the processor corresponding to the closest matching
     // rule and passes the context along
@@ -1120,4 +1124,44 @@ public final class TypeCheckProcFactory 
   public static DefaultExprProcessor getDefaultExprProcessor() {
     return new DefaultExprProcessor();
   }
+
+  /**
+   * Processor for subquery expressions..
+   */
+  public static class SubQueryExprProcessor implements NodeProcessor {
+
+    @Override
+    public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
+        Object... nodeOutputs) throws SemanticException {
+
+      TypeCheckCtx ctx = (TypeCheckCtx) procCtx;
+      if (ctx.getError() != null) {
+        return null;
+      }
+
+      ExprNodeDesc desc = TypeCheckProcFactory.processGByExpr(nd, procCtx);
+      if (desc != null) {
+        return desc;
+      }
+
+      ASTNode expr = (ASTNode) nd;
+      ASTNode sqNode = (ASTNode) expr.getParent().getChild(1);
+      /*
+       * Restriction.1.h :: SubQueries only supported in the SQL Where Clause.
+       */
+      ctx.setError(ErrorMsg.UNSUPPORTED_SUBQUERY_EXPRESSION.getMsg(sqNode,
+          "Currently SubQuery expressions are only allowed as Where Clause predicates"),
+          sqNode);
+      return null;
+    }
+  }
+
+  /**
+   * Factory method to get SubQueryExprProcessor.
+   *
+   * @return DateExprProcessor.
+   */
+  public static SubQueryExprProcessor getSubQueryExprProcessor() {
+    return new SubQueryExprProcessor();
+  }
 }

Added: hive/trunk/ql/src/test/queries/clientnegative/subquery_exists_implicit_gby.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/subquery_exists_implicit_gby.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/subquery_exists_implicit_gby.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/subquery_exists_implicit_gby.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,10 @@
+
+
+select * 
+from src b 
+where exists 
+  (select count(*) 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientnegative/subquery_in_groupby.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/subquery_in_groupby.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/subquery_in_groupby.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/subquery_in_groupby.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,5 @@
+
+
+select count(*) 
+from src 
+group by src.key in (select key from src s1 where s1.key > '9')
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientnegative/subquery_in_select.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/subquery_in_select.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/subquery_in_select.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/subquery_in_select.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,6 @@
+
+
+
+select src.key in (select key from src s1 where s1.key > '9') 
+from src
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientnegative/subquery_multiple_cols_in_select.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/subquery_multiple_cols_in_select.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/subquery_multiple_cols_in_select.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/subquery_multiple_cols_in_select.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,7 @@
+
+
+explain
+ select * 
+from src 
+where src.key in (select * from src s1 where s1.key > '9')
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientnegative/subquery_notexists_implicit_gby.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/subquery_notexists_implicit_gby.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/subquery_notexists_implicit_gby.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/subquery_notexists_implicit_gby.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,10 @@
+
+
+select * 
+from src b 
+where not exists 
+  (select sum(1)
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientnegative/subquery_subquery_chain.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/subquery_subquery_chain.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/subquery_subquery_chain.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/subquery_subquery_chain.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,6 @@
+
+explain
+select * 
+from src 
+where src.key in (select key from src) in (select key from src)
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientnegative/subquery_windowing_corr.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/subquery_windowing_corr.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/subquery_windowing_corr.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/subquery_windowing_corr.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,26 @@
+DROP TABLE part;
+
+-- data setup
+CREATE TABLE part( 
+    p_partkey INT,
+    p_name STRING,
+    p_mfgr STRING,
+    p_brand STRING,
+    p_type STRING,
+    p_size INT,
+    p_container STRING,
+    p_retailprice DOUBLE,
+    p_comment STRING
+);
+
+LOAD DATA LOCAL INPATH '../data/files/part_tiny.txt' overwrite into table part;
+
+
+-- corr and windowing 
+select p_mfgr, p_name, p_size 
+from part a 
+where a.p_size in 
+  (select first_value(p_size) over(partition by p_mfgr order by p_size) 
+   from part b 
+   where a.p_brand = b.p_brand)
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientnegative/subquery_with_or_cond.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientnegative/subquery_with_or_cond.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientnegative/subquery_with_or_cond.q (added)
+++ hive/trunk/ql/src/test/queries/clientnegative/subquery_with_or_cond.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,5 @@
+
+select count(*) 
+from src 
+where src.key in (select key from src s1 where s1.key > '9') or src.value is not null
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientpositive/subquery_exists.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/subquery_exists.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/subquery_exists.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/subquery_exists.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,45 @@
+
+
+-- no agg, corr
+explain
+select * 
+from src b 
+where exists 
+  (select a.key 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+;
+
+select * 
+from src b 
+where exists 
+  (select a.key 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+;
+
+-- view test
+create view cv1 as 
+select * 
+from src b 
+where exists
+  (select a.key 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9')
+;
+
+select * from cv1
+;
+
+-- sq in from
+select * 
+from (select * 
+      from src b 
+      where exists 
+          (select a.key 
+          from src a 
+          where b.value = a.value  and a.key = b.key and a.value > 'val_9')
+     ) a
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientpositive/subquery_in.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/subquery_in.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/subquery_in.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/subquery_in.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,155 @@
+DROP TABLE part;
+
+-- data setup
+CREATE TABLE part( 
+    p_partkey INT,
+    p_name STRING,
+    p_mfgr STRING,
+    p_brand STRING,
+    p_type STRING,
+    p_size INT,
+    p_container STRING,
+    p_retailprice DOUBLE,
+    p_comment STRING
+);
+
+LOAD DATA LOCAL INPATH '../data/files/part_tiny.txt' overwrite into table part;
+
+DROP TABLE lineitem;
+CREATE TABLE lineitem (L_ORDERKEY      INT,
+                                L_PARTKEY       INT,
+                                L_SUPPKEY       INT,
+                                L_LINENUMBER    INT,
+                                L_QUANTITY      DOUBLE,
+                                L_EXTENDEDPRICE DOUBLE,
+                                L_DISCOUNT      DOUBLE,
+                                L_TAX           DOUBLE,
+                                L_RETURNFLAG    STRING,
+                                L_LINESTATUS    STRING,
+                                l_shipdate      STRING,
+                                L_COMMITDATE    STRING,
+                                L_RECEIPTDATE   STRING,
+                                L_SHIPINSTRUCT  STRING,
+                                L_SHIPMODE      STRING,
+                                L_COMMENT       STRING)
+ROW FORMAT DELIMITED
+FIELDS TERMINATED BY '|';
+
+LOAD DATA LOCAL INPATH '../data/files/lineitem.txt' OVERWRITE INTO TABLE lineitem;
+
+-- non agg, non corr
+explain
+ select * 
+from src 
+where src.key in (select key from src s1 where s1.key > '9')
+;
+
+select * 
+from src 
+where src.key in (select key from src s1 where s1.key > '9')
+;
+
+-- non agg, corr
+explain 
+select * 
+from src b 
+where b.key in
+        (select a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+;
+
+select * 
+from src b 
+where b.key in
+        (select a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+;
+
+-- agg, non corr
+explain
+select p_name, p_size 
+from 
+part where part.p_size in 
+	(select avg(p_size) 
+	 from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	)
+;
+select p_name, p_size 
+from 
+part where part.p_size in 
+	(select avg(p_size) 
+	 from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	)
+;
+
+-- agg, corr
+explain
+select p_mfgr, p_name, p_size 
+from part b where b.p_size in 
+	(select min(p_size) 
+	 from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2 and b.p_mfgr = a.p_mfgr
+	)
+;
+
+select p_mfgr, p_name, p_size 
+from part b where b.p_size in 
+	(select min(p_size) 
+	 from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2 and b.p_mfgr = a.p_mfgr
+	)
+;
+
+-- distinct, corr
+explain 
+select * 
+from src b 
+where b.key in
+        (select distinct a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+;
+
+select * 
+from src b 
+where b.key in
+        (select distinct a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+;
+
+-- non agg, non corr, windowing
+select p_mfgr, p_name, p_size 
+from part 
+where part.p_size in 
+  (select first_value(p_size) over(partition by p_mfgr order by p_size) from part)
+;
+
+-- non agg, non corr, with join in Parent Query
+explain
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR')
+;
+
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR')
+;
+
+-- non agg, corr, with join in Parent Query
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR' and l_linenumber = li.l_linenumber)
+;

Added: hive/trunk/ql/src/test/queries/clientpositive/subquery_multiinsert.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/subquery_multiinsert.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/subquery_multiinsert.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/subquery_multiinsert.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,45 @@
+CREATE TABLE src_4( 
+  key STRING, 
+  value STRING
+)
+;
+
+CREATE TABLE src_5( 
+  key STRING, 
+  value STRING
+)
+;
+
+explain
+from src b 
+INSERT OVERWRITE TABLE src_4 
+  select * 
+  where b.key in 
+   (select a.key 
+    from src a 
+    where b.value = a.value and a.key > '9'
+   ) 
+INSERT OVERWRITE TABLE src_5 
+  select *  
+  where b.key not in  ( select key from src s1 where s1.key > '2') 
+  order by key 
+;
+
+from src b 
+INSERT OVERWRITE TABLE src_4 
+  select * 
+  where b.key in 
+   (select a.key 
+    from src a 
+    where b.value = a.value and a.key > '9'
+   ) 
+INSERT OVERWRITE TABLE src_5 
+  select *  
+  where b.key not in  ( select key from src s1 where s1.key > '2') 
+  order by key 
+;
+
+select * from src_4
+;
+select * from src_5
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientpositive/subquery_notexists.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/subquery_notexists.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/subquery_notexists.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/subquery_notexists.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,41 @@
+
+
+-- no agg, corr
+explain
+select * 
+from src b 
+where not exists 
+  (select a.key 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_2'
+  )
+;
+
+select * 
+from src b 
+where not exists 
+  (select a.key 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_2'
+  )
+;
+
+-- distinct, corr
+explain
+select * 
+from src b 
+where not exists 
+  (select distinct a.key 
+  from src a 
+  where b.value = a.value and a.value > 'val_2'
+  )
+;
+
+select * 
+from src b 
+where not exists 
+  (select a.key 
+  from src a 
+  where b.value = a.value and a.value > 'val_2'
+  )
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientpositive/subquery_notin.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/subquery_notin.q?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/subquery_notin.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/subquery_notin.q Wed Oct 23 14:54:17 2013
@@ -0,0 +1,129 @@
+DROP TABLE part;
+
+-- data setup
+CREATE TABLE part( 
+    p_partkey INT,
+    p_name STRING,
+    p_mfgr STRING,
+    p_brand STRING,
+    p_type STRING,
+    p_size INT,
+    p_container STRING,
+    p_retailprice DOUBLE,
+    p_comment STRING
+);
+
+LOAD DATA LOCAL INPATH '../data/files/part_tiny.txt' overwrite into table part;
+
+DROP TABLE lineitem;
+CREATE TABLE lineitem (L_ORDERKEY      INT,
+                                L_PARTKEY       INT,
+                                L_SUPPKEY       INT,
+                                L_LINENUMBER    INT,
+                                L_QUANTITY      DOUBLE,
+                                L_EXTENDEDPRICE DOUBLE,
+                                L_DISCOUNT      DOUBLE,
+                                L_TAX           DOUBLE,
+                                L_RETURNFLAG    STRING,
+                                L_LINESTATUS    STRING,
+                                l_shipdate      STRING,
+                                L_COMMITDATE    STRING,
+                                L_RECEIPTDATE   STRING,
+                                L_SHIPINSTRUCT  STRING,
+                                L_SHIPMODE      STRING,
+                                L_COMMENT       STRING)
+ROW FORMAT DELIMITED
+FIELDS TERMINATED BY '|';
+
+LOAD DATA LOCAL INPATH '../data/files/lineitem.txt' OVERWRITE INTO TABLE lineitem;
+
+-- non agg, non corr
+explain
+select * 
+from src 
+where src.key not in  
+  ( select key  from src s1 
+    where s1.key > '2'
+  )
+;
+
+select * 
+from src 
+where src.key not in  ( select key from src s1 where s1.key > '2')
+order by key
+;
+
+-- non agg, corr
+explain
+select p_mfgr, b.p_name, p_size 
+from part b 
+where b.p_name not in 
+  (select p_name 
+  from (select p_mfgr, p_name, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+  where r <= 2 and b.p_mfgr = a.p_mfgr 
+  )
+;
+
+select p_mfgr, b.p_name, p_size 
+from part b 
+where b.p_name not in 
+  (select p_name 
+  from (select p_mfgr, p_name, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+  where r <= 2 and b.p_mfgr = a.p_mfgr 
+  )
+order by p_mfgr, b.p_name
+;
+
+-- agg, non corr
+explain
+select p_name, p_size 
+from 
+part where part.p_size not in 
+  (select avg(p_size) 
+  from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+  where r <= 2
+  )
+;
+select p_name, p_size 
+from 
+part where part.p_size not in 
+  (select avg(p_size) 
+  from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+  where r <= 2
+  )
+order by p_name, p_size
+;
+
+-- agg, corr
+explain
+select p_mfgr, p_name, p_size 
+from part b where b.p_size not in 
+  (select min(p_size) 
+  from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+  where r <= 2 and b.p_mfgr = a.p_mfgr
+  )
+;
+
+select p_mfgr, p_name, p_size 
+from part b where b.p_size not in 
+  (select min(p_size) 
+  from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+  where r <= 2 and b.p_mfgr = a.p_mfgr
+  )
+order by p_mfgr, p_size
+;
+
+-- non agg, non corr, Group By in Parent Query
+select li.l_partkey, count(*) 
+from lineitem li 
+where li.l_linenumber = 1 and 
+  li.l_orderkey not in (select l_orderkey from lineitem where l_shipmode = 'AIR') 
+group by li.l_partkey
+;
+
+-- alternate not in syntax
+select * 
+from src 
+where not src.key in  ( select key from src s1 where s1.key > '2')
+order by key
+;

Added: hive/trunk/ql/src/test/results/clientnegative/subquery_exists_implicit_gby.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/subquery_exists_implicit_gby.q.out?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/subquery_exists_implicit_gby.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/subquery_exists_implicit_gby.q.out Wed Oct 23 14:54:17 2013
@@ -0,0 +1,7 @@
+FAILED: SemanticException Line 7:7 Invalid SubQuery expression 'key' in definition of SubQuery sq_1 [
+exists 
+  (select count(*) 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+] used as sq_1 at Line 5:6: An Exists predicate on SubQuery with implicit Aggregation(no Group By clause) cannot be rewritten. (predicate will always return true).

Added: hive/trunk/ql/src/test/results/clientnegative/subquery_in_groupby.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/subquery_in_groupby.q.out?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/subquery_in_groupby.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/subquery_in_groupby.q.out Wed Oct 23 14:54:17 2013
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10249]: Line 5:37 Unsupported SubQuery Expression ''9'': Currently SubQuery expressions are only allowed as Where Clause predicates

Added: hive/trunk/ql/src/test/results/clientnegative/subquery_in_select.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/subquery_in_select.q.out?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/subquery_in_select.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/subquery_in_select.q.out Wed Oct 23 14:54:17 2013
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10249]: Line 4:35 Unsupported SubQuery Expression ''9'': Currently SubQuery expressions are only allowed as Where Clause predicates

Added: hive/trunk/ql/src/test/results/clientnegative/subquery_multiple_cols_in_select.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/subquery_multiple_cols_in_select.q.out?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/subquery_multiple_cols_in_select.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/subquery_multiple_cols_in_select.q.out Wed Oct 23 14:54:17 2013
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10250]: Line 6:14 Invalid SubQuery expression 'key': SubQuery can contain only 1 item in Select List.

Added: hive/trunk/ql/src/test/results/clientnegative/subquery_notexists_implicit_gby.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/subquery_notexists_implicit_gby.q.out?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/subquery_notexists_implicit_gby.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/subquery_notexists_implicit_gby.q.out Wed Oct 23 14:54:17 2013
@@ -0,0 +1,7 @@
+FAILED: SemanticException Line 7:7 Invalid SubQuery expression 'key' in definition of SubQuery sq_1 [
+exists 
+  (select sum(1)
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+] used as sq_1 at Line 5:10: A Not Exists predicate on SubQuery with implicit Aggregation(no Group By clause) cannot be rewritten. (predicate will always return false).

Added: hive/trunk/ql/src/test/results/clientnegative/subquery_subquery_chain.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/subquery_subquery_chain.q.out?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/subquery_subquery_chain.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/subquery_subquery_chain.q.out Wed Oct 23 14:54:17 2013
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10249]: Line 5:14 Unsupported SubQuery Expression 'key': Only 1 SubQuery expression is supported.

Added: hive/trunk/ql/src/test/results/clientnegative/subquery_windowing_corr.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/subquery_windowing_corr.q.out?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/subquery_windowing_corr.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/subquery_windowing_corr.q.out Wed Oct 23 14:54:17 2013
@@ -0,0 +1,43 @@
+PREHOOK: query: DROP TABLE part
+PREHOOK: type: DROPTABLE
+POSTHOOK: query: DROP TABLE part
+POSTHOOK: type: DROPTABLE
+PREHOOK: query: -- data setup
+CREATE TABLE part( 
+    p_partkey INT,
+    p_name STRING,
+    p_mfgr STRING,
+    p_brand STRING,
+    p_type STRING,
+    p_size INT,
+    p_container STRING,
+    p_retailprice DOUBLE,
+    p_comment STRING
+)
+PREHOOK: type: CREATETABLE
+POSTHOOK: query: -- data setup
+CREATE TABLE part( 
+    p_partkey INT,
+    p_name STRING,
+    p_mfgr STRING,
+    p_brand STRING,
+    p_type STRING,
+    p_size INT,
+    p_container STRING,
+    p_retailprice DOUBLE,
+    p_comment STRING
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: default@part
+PREHOOK: query: LOAD DATA LOCAL INPATH '../data/files/part_tiny.txt' overwrite into table part
+PREHOOK: type: LOAD
+PREHOOK: Output: default@part
+POSTHOOK: query: LOAD DATA LOCAL INPATH '../data/files/part_tiny.txt' overwrite into table part
+POSTHOOK: type: LOAD
+POSTHOOK: Output: default@part
+FAILED: SemanticException Line 9:8 Unsupported SubQuery Expression '1' in definition of SubQuery sq_1 [
+a.p_size in 
+  (select first_value(p_size) over(partition by p_mfgr order by p_size) 
+   from part b 
+   where a.p_brand = b.p_brand)
+] used as sq_1 at Line 7:15: Correlated Sub Queries cannot contain Windowing clauses.

Added: hive/trunk/ql/src/test/results/clientnegative/subquery_with_or_cond.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientnegative/subquery_with_or_cond.q.out?rev=1535040&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientnegative/subquery_with_or_cond.q.out (added)
+++ hive/trunk/ql/src/test/results/clientnegative/subquery_with_or_cond.q.out Wed Oct 23 14:54:17 2013
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10249]: Line 4:14 Unsupported SubQuery Expression 'key': Only SubQuery expressions that are top level conjuncts are allowed