private static @Nullable HiveLoptJoinTree addToTop(
          RelMetadataQuery mq,
          RelBuilder relBuilder,
          HiveLoptMultiJoin multiJoin,
          HiveLoptSemiJoinOptimizer semiJoinOpt,
          HiveLoptJoinTree joinTree,
          int factorToAdd,
          List<RexNode> filtersToAdd,
          boolean selfJoin) {
    // self-joins can never be created at the top of an existing
    // join tree because it needs to be paired directly with the
    // other self-join factor
    if (selfJoin && isJoinTree(joinTree.getJoinTree())) {
      return null;
    }

    // if the factor being added is null-generating, create the join
    // as a left outer join since it's being added to the RHS side of
    // the join; createJoinSubTree may swap the inputs and therefore
    // convert the left outer join to a right outer join; if the original
    // MultiJoin was a full outer join, these should be the only
    // factors in the join, so create the join as a full outer join
    JoinRelType joinType;
    if (multiJoin.getMultiJoinRel().isFullOuterJoin()) {
      assert multiJoin.getNumJoinFactors() == 2;
      joinType = JoinRelType.FULL;
    } else if (multiJoin.isNullGenerating(factorToAdd)) {
      joinType = JoinRelType.LEFT;
    } else {
      joinType = JoinRelType.INNER;
    }

    HiveLoptJoinTree rightTree =
            new HiveLoptJoinTree(
                    semiJoinOpt.getChosenSemiJoin(factorToAdd),
                    factorToAdd);

    // in the case of a left or right outer join, use the specific
    // outer join condition
    RexNode condition;
    if ((joinType == JoinRelType.LEFT) || (joinType == JoinRelType.RIGHT)) {
      condition = requireNonNull(multiJoin.getOuterJoinCond(factorToAdd),
              "multiJoin.getOuterJoinCond(factorToAdd)");
    } else {
      condition =
              addFilters(
                      multiJoin,
                      joinTree,
                      -1,
                      rightTree,
                      filtersToAdd,
                      false);
    }

    return createJoinSubtree(
            mq,
            relBuilder,
            multiJoin,
            joinTree,
            rightTree,
            condition,
            joinType,
            filtersToAdd,
            true,
            selfJoin);
  }
Creates a join tree with the new factor added to the top of the tree.

@param multiJoin join factors being optimized
@param semiJoinOpt optimal semijoins for each factor
@param joinTree current join tree
@param factorToAdd new factor to be added
@param filtersToAdd filters remaining to be added; modifies the list to
remove filters that can be added to the join tree
@param selfJoin true if the join being created is a self-join that's
removable

@return new join tree
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveLoptOptimizeJoinRule.java