@Override
    public RelNode visit(HiveJoin join) {
      HiveJoin newJoin = (HiveJoin) visitChildren(join);
      if (newJoin.getJoinType() != JoinRelType.INNER && !newJoin.isSemiJoin()) {
        // Nothing to do
        return newJoin;
      }
      RelMetadataQuery mq = newJoin.getCluster().getMetadataQuery();
      boolean leftValid = isValidRelNodePlan(newJoin.getLeft(), mq);
      boolean rightValid = isValidRelNodePlan(newJoin.getRight(), mq);
      if (leftValid == rightValid) {
        // Both are valid or invalid, nothing to do here
        return newJoin;
      }
      RelNode leftInput = newJoin.getLeft();
      RelNode rightInput = newJoin.getRight();
      if (!leftValid) {
        leftInput = createBoxOperator(newJoin.getCluster(), leftInput);
      } else {
        rightInput = createBoxOperator(newJoin.getCluster(), rightInput);
      }
      return newJoin.copy(
          newJoin.getTraitSet(), ImmutableList.of(leftInput, rightInput));
    }
Rule that replaces Box operators by the plan they hold.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/views/HiveMaterializedViewBoxing.java