public void addRemovableSelfJoinPair(int factor1, int factor2) {
    int leftFactor;
    int rightFactor;

    // Put the factor with more fields on the left so it will be
    // preserved after the self-join is removed.
    if (getNumFieldsInJoinFactor(factor1)
            > getNumFieldsInJoinFactor(factor2)) {
      leftFactor = factor1;
      rightFactor = factor2;
    } else {
      leftFactor = factor2;
      rightFactor = factor1;
    }

    // Compute a column mapping such that if a column from the right
    // factor is also referenced in the left factor, we will map the
    // right reference to the left to avoid redundant references.
    final Map<Integer, Integer> columnMapping = new HashMap<>();

    // First, locate the originating column for all simple column
    // references in the left factor.
    final RelNode left = getJoinFactor(leftFactor);
    final RelMetadataQuery mq = left.getCluster().getMetadataQuery();
    final Map<Integer, Integer> leftFactorColMapping = new HashMap<>();
    for (int i = 0; i < left.getRowType().getFieldCount(); i++) {
      final RelColumnOrigin colOrigin = mq.getColumnOrigin(left, i);
      if (colOrigin != null && !colOrigin.isDerived()) {
        leftFactorColMapping.put(
                colOrigin.getOriginColumnOrdinal(),
                i);
      }
    }

    // Then, see if the right factor references any of the same columns
    // by locating their originating columns.  If there are matches,
    // then we want to store the corresponding offset into the left
    // factor.
    RelNode right = getJoinFactor(rightFactor);
    for (int i = 0; i < right.getRowType().getFieldCount(); i++) {
      final RelColumnOrigin colOrigin = mq.getColumnOrigin(right, i);
      if (colOrigin == null || colOrigin.isDerived()) {
        continue;
      }
      Integer leftOffset =
              leftFactorColMapping.get(colOrigin.getOriginColumnOrdinal());
      if (leftOffset == null) {
        continue;
      }
      columnMapping.put(i, leftOffset);
    }

    HiveLoptMultiJoin.RemovableSelfJoin selfJoin =
            new HiveLoptMultiJoin.RemovableSelfJoin(leftFactor, rightFactor, columnMapping);

    removableSelfJoinPairs.put(leftFactor, selfJoin);
    removableSelfJoinPairs.put(rightFactor, selfJoin);
  }
Adds to a map that keeps track of removable self-join pairs.

@param factor1 one of the factors in the self-join
@param factor2 the second factor in the self-join
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveLoptMultiJoin.java