void validateAndRewriteAST(RowResolver outerQueryRR,
      boolean forHavingClause,
      String outerQueryAlias,
      Set<String> outerQryAliases) throws SemanticException {

    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.QUERY_HINT ) {
      selectExprStart = 1;
    }

    /*
     * Restriction.16.s :: Correlated Expression in Outer Query must not contain
     * unqualified column references.
     * disabled : if it's obvious, we allow unqualified refs
     */

    /*
     * Restriction 17.s :: SubQuery cannot use the same table alias as one used in
     * the Outer Query.
     */
    List<String> sqAliases = SubQueryUtils.getTableAliasesInSubQuery(fromClause);
    String sharedAlias = null;
    for(String s : sqAliases ) {
      if ( outerQryAliases.contains(s) ) {
        sharedAlias = s;
      }
    }
    if ( sharedAlias != null) {
      ASTNode whereClause = SubQueryUtils.subQueryWhere(insertClause);
    }

    /*
     * 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 ) {
      subQueryAST.setOrigin(originalSQASTOrigin);
      throw new SemanticException(ASTErrorUtils.getMsg(
          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 == 3);
      containsAggregationExprs = containsAggregationExprs | ( r == 1 );
    }

    rewrite(outerQueryRR, forHavingClause, outerQueryAlias, insertClause, selectClause);

    /*
     * 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(ASTErrorUtils.getMsg(
          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(ASTErrorUtils.getMsg(
          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(ASTErrorUtils.getMsg(
          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(ASTErrorUtils.getMsg(
          ErrorMsg.INVALID_SUBQUERY_EXPRESSION.getMsg(),
          subQueryAST, "For Exists/Not Exists operator SubQuery must be Correlated."));
    }

  }
@param parentQueryRR
@param forHavingClause
@param outerQueryAlias
@return true if it is correlated scalar subquery with an aggregate
@throws SemanticException
ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java