protected ASTNode rewriteGroupingFunctionAST(final List<ASTNode> grpByAstExprs, ASTNode targetNode,
                                                      final boolean noneSet) {

    TreeVisitorAction action = new TreeVisitorAction() {

      @Override
      public Object pre(Object t) {
        return t;
      }

      @Override
      public Object post(Object t) {
        ASTNode root = (ASTNode) t;
        if (root.getType() == HiveParser.TOK_FUNCTION) {
          ASTNode func = (ASTNode) ParseDriver.adaptor.getChild(root, 0);
          if ("grouping".equalsIgnoreCase(func.getText()) && func.getChildCount() == 0) {
            int numberOperands = ParseDriver.adaptor.getChildCount(root);
            // We implement this logic using replaceChildren instead of replacing
            // the root node itself because windowing logic stores multiple
            // pointers to the AST, and replacing root might lead to some pointers
            // leading to non-rewritten version
            ASTNode newRoot = new ASTNode();
            // Rewritten grouping function
            ASTNode groupingFunc = (ASTNode) ParseDriver.adaptor.create(
                HiveParser.Identifier, "grouping");
            ParseDriver.adaptor.addChild(groupingFunc, ParseDriver.adaptor.create(
                HiveParser.Identifier, "rewritten"));
            newRoot.addChild(groupingFunc);
            // Grouping ID reference
            ASTNode childGroupingID;
            if (noneSet) {
              // Query does not contain CUBE, ROLLUP, or GROUPING SETS, and thus,
              // grouping should return 0
              childGroupingID = (ASTNode) ParseDriver.adaptor.create(HiveParser.IntegralLiteral,
                "0L");
            } else {
              // We refer to grouping_id column
              childGroupingID = (ASTNode) ParseDriver.adaptor.create(
                  HiveParser.TOK_TABLE_OR_COL, "TOK_TABLE_OR_COL");
              ParseDriver.adaptor.addChild(childGroupingID, ParseDriver.adaptor.create(
                  HiveParser.Identifier, VirtualColumn.GROUPINGID.getName()));
            }
            newRoot.addChild(childGroupingID);
            // Indices
            for (int i = 1; i < numberOperands; i++) {
              ASTNode c = (ASTNode) ParseDriver.adaptor.getChild(root, i);
              for (int j = 0; j < grpByAstExprs.size(); j++) {
                ASTNode grpByExpr = grpByAstExprs.get(j);
                if (grpByExpr.toStringTree().equals(c.toStringTree())) {
                  // Create and add AST node with position of grouping function input
                  // in group by clause
                  ASTNode childN = (ASTNode) ParseDriver.adaptor.create(HiveParser.IntegralLiteral,
                    String.valueOf(IntMath.mod(-j-1, grpByAstExprs.size())) + "L");
                  newRoot.addChild(childN);
                  break;
                }
              }
            }
            if (numberOperands + 1 != ParseDriver.adaptor.getChildCount(newRoot)) {
              throw new RuntimeException(ErrorMsg.HIVE_GROUPING_FUNCTION_EXPR_NOT_IN_GROUPBY.getMsg());
            }
            // Replace expression
            root.replaceChildren(0, numberOperands - 1, newRoot);
          }
        }
        return t;
      }
    };
    return (ASTNode) new TreeVisitor(ParseDriver.adaptor).visit(targetNode, action);
  }
Parse the join condition. For equality conjuncts, break them into left and
right expressions and store in the join tree. For other conditions, either
add them to the post-conditions if they apply to more than one input, add
them to the filter conditions of a given input if it applies only on
one of them and should not be pushed, e.g., left outer join with condition
that applies only to left input, or push them below the join if they
apply only to one input and can be pushed, e.g., left outer join with
condition that applies only to right input.

@param joinTree
         jointree to be populated
@param joinCond
         join condition
@param leftSrc
         left sources
@throws SemanticException
ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java