private void removeSJEdges() throws SemanticException {
      LinkedHashMap<ReduceSinkOperator, SemiJoinBranchInfo> rs2sj = new LinkedHashMap<>();
      for (Entry<ReduceSinkOperator, SemiJoinBranchInfo> e : pctx.getRsToSemiJoinBranchInfo().entrySet()) {
        Operator<?> rs = e.getKey();
        SemiJoinBranchInfo sji = e.getValue();
        TableScanOperator ts = sji.getTsOp();

        while (true) {
          if (rs.getChildOperators().size() != 1) {
            throw new SemanticException("Unexpected number of children");
          }
          Operator<?> child = rs.getChildOperators().get(0);
          if (child == ts) {
            break;
          }
          rs = child;
        }

        rs.getChildOperators().clear();
        ts.getParentOperators().remove(rs);
        rs2sj.put((ReduceSinkOperator) rs, sji);

        if (pctx.getRsToRuntimeValuesInfoMap().containsKey(e.getKey())) {
          RuntimeValuesInfo rvi = pctx.getRsToRuntimeValuesInfoMap().remove(e.getKey());
          pctx.getRsToRuntimeValuesInfoMap().put((ReduceSinkOperator) rs, rvi);
        }
      }
      pctx.setRsToSemiJoinBranchInfo(rs2sj);
    }
This {@link AutoCloseable} class makes it possible to show SemiJoin edges as normal operator edges temporarily.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/ParallelEdgeFixer.java