private static JoinLeafPredicateInfo constructJoinLeafPredicateInfo(List<RelNode> inputs,
            List<RelDataTypeField> systemFieldList, RexNode pe) throws CalciteSemanticException {
      JoinLeafPredicateInfo jlpi = null;
      List<Integer> filterNulls = new ArrayList<Integer>();
      List<List<RexNode>> joinExprs = new ArrayList<List<RexNode>>();
      for (int i=0; i<inputs.size(); i++) {
        joinExprs.add(new ArrayList<RexNode>());
      }

      // 1. Split leaf join predicate to expressions from left, right
      RexNode otherConditions = HiveRelOptUtil.splitHiveJoinCondition(systemFieldList, inputs, pe,
          joinExprs, filterNulls, new ArrayList<SqlOperator>());

      if (otherConditions.isAlwaysTrue()) {
        // 2. Collect child projection indexes used
        List<Set<Integer>> projsJoinKeysInChildSchema =
                new ArrayList<Set<Integer>>();
        for (int i=0; i<inputs.size(); i++) {
          ImmutableSet.Builder<Integer> projsFromInputJoinKeysInChildSchema = ImmutableSet.builder();
          InputReferencedVisitor irvLeft = new InputReferencedVisitor();
          irvLeft.apply(joinExprs.get(i));
          projsFromInputJoinKeysInChildSchema.addAll(irvLeft.inputPosReferenced);
          projsJoinKeysInChildSchema.add(projsFromInputJoinKeysInChildSchema.build());
        }

        // 3. Translate projection indexes to join schema, by adding offset.
        List<Set<Integer>> projsJoinKeysInJoinSchema =
                new ArrayList<Set<Integer>>();
        // The offset of the first input does not need to change.
        projsJoinKeysInJoinSchema.add(projsJoinKeysInChildSchema.get(0));
        for (int i=1; i<inputs.size(); i++) {
          int offSet = inputs.get(i-1).getRowType().getFieldCount();
          ImmutableSet.Builder<Integer> projsFromInputJoinKeysInJoinSchema = ImmutableSet.builder();
          for (Integer indx : projsJoinKeysInChildSchema.get(i)) {
            projsFromInputJoinKeysInJoinSchema.add(indx + offSet);
          }
          projsJoinKeysInJoinSchema.add(projsFromInputJoinKeysInJoinSchema.build());
        }

        // 4. Construct JoinLeafPredicateInfo
        jlpi = new JoinLeafPredicateInfo(pe.getKind(), joinExprs,
            projsJoinKeysInChildSchema, projsJoinKeysInJoinSchema);
      } else {
        // 2. Construct JoinLeafPredicateInfo
        ImmutableBitSet refCols = InputFinder.bits(pe);
        int count = 0;
        for (int i=0; i<inputs.size(); i++) {
          final int length = inputs.get(i).getRowType().getFieldCount();
          ImmutableBitSet inputRange = ImmutableBitSet.range(count, count + length);
          if (inputRange.contains(refCols)) {
            joinExprs.get(i).add(pe);
          }
          count += length;
        }
        jlpi = new JoinLeafPredicateInfo(SqlKind.OTHER, joinExprs,
            new ArrayList<Set<Integer>>(), new ArrayList<Set<Integer>>());
      }

      return jlpi;
    }
JoinLeafPredicateInfo represents leaf predicate in Join condition
(conjuctive lement).<br>
<p>
JoinLeafPredicateInfo:<br>
1. Stores list of expressions from left and right child which is part of
equi join keys.<br>
2. Stores set of projection indexes from left and right child which is part
of equi join keys; the indexes are both in child and Join node schema.<br>
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveCalciteUtil.java