@SuppressWarnings("rawtypes")
  private void parseJoinCondition(QBJoinTree joinTree, ASTNode joinCond,
                                  List<String> leftSrc, JoinType type,
                                  Map<String, Operator> aliasToOpInfo) throws SemanticException {
    if (joinCond == null) {
      return;
    }

    switch (joinCond.getToken().getType()) {
    case HiveParser.KW_OR:
      parseJoinCondPopulateAlias(joinTree, (ASTNode) joinCond.getChild(0),
          new ArrayList<String>(), new ArrayList<String>(),
          null, aliasToOpInfo);
      parseJoinCondPopulateAlias(joinTree, (ASTNode) joinCond.getChild(1),
          new ArrayList<String>(), new ArrayList<String>(),
          null, aliasToOpInfo);
      joinTree.addPostJoinFilter(joinCond);
      break;

    case HiveParser.KW_AND:
      parseJoinCondition(joinTree, (ASTNode) joinCond.getChild(0), leftSrc, type, aliasToOpInfo);
      parseJoinCondition(joinTree, (ASTNode) joinCond.getChild(1), leftSrc, type, aliasToOpInfo);
      break;

    case HiveParser.EQUAL_NS:
    case HiveParser.EQUAL:
      ASTNode leftCondn = (ASTNode) joinCond.getChild(0);
      List<String> leftCondAl1 = new ArrayList<String>();
      List<String> leftCondAl2 = new ArrayList<String>();
      parseJoinCondPopulateAlias(joinTree, leftCondn, leftCondAl1, leftCondAl2,
          null, aliasToOpInfo);

      ASTNode rightCondn = (ASTNode) joinCond.getChild(1);
      List<String> rightCondAl1 = new ArrayList<String>();
      List<String> rightCondAl2 = new ArrayList<String>();
      parseJoinCondPopulateAlias(joinTree, rightCondn, rightCondAl1,
          rightCondAl2, null, aliasToOpInfo);

      // is it a filter or a join condition
      // if it is filter see if it can be pushed above the join
      // filter cannot be pushed if
      // * join is full outer or
      // * join is left outer and filter is on left alias or
      // * join is right outer and filter is on right alias
      if (((leftCondAl1.size() != 0) && (leftCondAl2.size() != 0))
          || ((rightCondAl1.size() != 0) && (rightCondAl2.size() != 0))) {
        joinTree.addPostJoinFilter(joinCond);
      } else {
        applyEqualityPredicateToQBJoinTree(joinTree, type, leftSrc,
            joinCond, leftCondn, rightCondn,
            leftCondAl1, leftCondAl2,
            rightCondAl1, rightCondAl2);
      }
      break;

    default:
      boolean isFunction = (joinCond.getType() == HiveParser.TOK_FUNCTION);

      // Create all children
      int childrenBegin = (isFunction ? 1 : 0);
      List<List<String>> leftAlias = new ArrayList<List<String>>(joinCond.getChildCount() - childrenBegin);
      List<List<String>> rightAlias = new ArrayList<List<String>>(joinCond.getChildCount() - childrenBegin);
      for (int ci = 0; ci < joinCond.getChildCount() - childrenBegin; ci++) {
        List<String> left = new ArrayList<String>();
        List<String> right = new ArrayList<String>();
        leftAlias.add(left);
        rightAlias.add(right);
      }

      for (int ci = childrenBegin; ci < joinCond.getChildCount(); ci++) {
        parseJoinCondPopulateAlias(joinTree, (ASTNode) joinCond.getChild(ci),
            leftAlias.get(ci - childrenBegin), rightAlias.get(ci
                - childrenBegin), null, aliasToOpInfo);
      }

      boolean leftAliasNull = true;
      for (List<String> left : leftAlias) {
        if (left.size() != 0) {
          leftAliasNull = false;
          break;
        }
      }

      boolean rightAliasNull = true;
      for (List<String> right : rightAlias) {
        if (right.size() != 0) {
          rightAliasNull = false;
          break;
        }
      }

      if (!leftAliasNull && !rightAliasNull) {
        joinTree.addPostJoinFilter(joinCond);
      } else {
        if (!leftAliasNull) {
          if (type.equals(JoinType.LEFTOUTER)
              || type.equals(JoinType.FULLOUTER)) {
            joinTree.getFilters().get(0).add(joinCond);
          } else {
            joinTree.getFiltersForPushing().get(0).add(joinCond);
          }
        } else {
          if (type.equals(JoinType.RIGHTOUTER)
              || type.equals(JoinType.FULLOUTER)) {
            joinTree.getFilters().get(1).add(joinCond);
          } else {
            joinTree.getFiltersForPushing().get(1).add(joinCond);
          }
        }
      }

      break;
    }
  }
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