public Frame decorrelateRel(Filter rel) {
    //
    // Rewrite logic:
    //
    // 1. If a Filter references a correlated field in its filter
    // condition, rewrite the Filter to be
    //   Filter
    //     Join(cross product)
    //       OriginalFilterInput
    //       ValueGenerator(produces distinct sets of correlated variables)
    // and rewrite the correlated fieldAccess in the filter condition to
    // reference the Join output.
    //
    // 2. If Filter does not reference correlated variables, simply
    // rewrite the filter condition using new input.
    //

    final RelNode oldInput = rel.getInput();
    Frame frame = getInvoke(oldInput, rel);
    if (frame == null) {
      // If input has not been rewritten, do not rewrite this rel.
      return null;
    }

    Frame oldInputFrame = frame;
    // If this Filter has correlated reference, create value generator
    // and produce the correlated variables in the new output.
    if (cm.mapRefRelToCorRef.containsKey(rel)) {
      frame = decorrelateInputWithValueGenerator(rel);
    }

    boolean valueGenerator = true;
    if(frame.r == oldInputFrame.r) {
      // this means correated value generator wasn't generated
      valueGenerator = false;
    }

    boolean isSemiJoin = false;
    if (oldInput instanceof LogicalCorrelate) {
      isSemiJoin = ((LogicalCorrelate) oldInput).getJoinType() == JoinRelType.SEMI ||
              ((LogicalCorrelate) oldInput).getJoinType() == JoinRelType.ANTI;
    }

    if(isSemiJoin && !cm.mapRefRelToCorRef.containsKey(rel)) {
      // this conditions need to be pushed into semi-join since this condition
      // corresponds to IN
      Join join = ((Join)frame.r);
      final List<RexNode> conditions = new ArrayList<>();
      RexNode joinCond = join.getCondition();
      conditions.add(joinCond);
      conditions.add(decorrelateExpr(rel.getCondition(), valueGenerator));
      final RexNode condition =
          RexUtil.composeConjunction(rexBuilder, conditions, false);

      RelNode newRel;
      if (((LogicalCorrelate) oldInput).getJoinType() == JoinRelType.SEMI) {
        newRel = HiveSemiJoin.getSemiJoin(frame.r.getCluster(), frame.r.getTraitSet(),
                join.getLeft(), join.getRight(), condition);
      } else {
        newRel = HiveAntiJoin.getAntiJoin(frame.r.getCluster(), frame.r.getTraitSet(),
                join.getLeft(), join.getRight(), condition);
      }

      return register(rel, newRel, frame.oldToNewOutputs, frame.corDefOutputs);
    }
    // Replace the filter expression to reference output of the join
    // Map filter to the new filter over join
    relBuilder.push(frame.r).filter(
        (decorrelateExpr(rel.getCondition(), valueGenerator)));
    // Filter does not change the input ordering.
    // Filter rel does not permute the input.
    // All corvars produced by filter will have the same output positions in the
    // input rel.
    return register(rel, relBuilder.build(), frame.oldToNewOutputs,
        frame.corDefOutputs);
  }
Returns whether one type is just a widening of another.

<p>For example:<ul>
<li>{@code VARCHAR(10)} is a widening of {@code VARCHAR(5)}.
<li>{@code VARCHAR(10)} is a widening of {@code VARCHAR(10) NOT NULL}.
</ul>
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveRelDecorrelator.java