private Frame decorrelateInputWithValueGenerator(RelNode rel) {
    // currently only handles one input input
    assert rel.getInputs().size() == 1;
    RelNode oldInput = rel.getInput(0);
    final Frame frame = map.get(oldInput);

    final SortedMap<CorDef, Integer> corDefOutputs =
            new TreeMap<>(frame.corDefOutputs);

    final Collection<CorRef> corVarList = cm.mapRefRelToCorRef.get(rel);

    // Try to populate correlation variables using local fields.
    // This means that we do not need a value generator.
    if (rel instanceof Filter) {
      SortedMap<CorDef, Integer> coreMap = new TreeMap<>();
      for (CorRef correlation : corVarList) {
        final CorDef def = correlation.def();
        // If the correlation/variable is already provided by the input
        // then we don't have to look for equivalent expressions and 
        // we don't need to create value generator for them.
        if (corDefOutputs.containsKey(def)) {
          coreMap.put(def, corDefOutputs.get(def));
          continue;
        }
        // If the correlation/variable is in the map then we already
        // seen this before in this loop so we don't need to treat it again.
        if (coreMap.containsKey(def)) {
          continue;
        }
        try {
          findCorrelationEquivalent(correlation, ((Filter) rel).getCondition());
        } catch (Util.FoundOne e) {
          // we need to keep predicate kind e.g. EQUAL or NOT EQUAL
          // so that later while decorrelating LogicalCorrelate appropriate join predicate
          // is generated
          def.setPredicateKind((SqlOperator) ((Pair)((Pair)e.getNode()).getValue()).getKey());
          def.setIsLeft((boolean)((Pair)((Pair) e.getNode()).getValue()).getValue());
          final Integer oldInputRef = (Integer) ((Pair) e.getNode()).getKey();
          final Integer newInputRef = frame.oldToNewOutputs.get(oldInputRef);
          coreMap.put(def, newInputRef);
        }
      }
      // If all correlation variables are now satisfied, skip creating a value
      // generator.
      if (coreMap.size() == corVarList.size()) {
        coreMap.putAll(frame.corDefOutputs);
        return register(oldInput, frame.r,
                frame.oldToNewOutputs, coreMap);
      }
    }


    int leftInputOutputCount = frame.r.getRowType().getFieldCount();

    // can directly add positions into corDefOutputs since join
    // does not change the output ordering from the inputs.
    RelNode valueGenRel =
            createValueGenerator(
                    corVarList,
                    leftInputOutputCount,
                    corDefOutputs);

    RelNode join = relBuilder.push(frame.r).push(valueGenRel)
        .join(JoinRelType.INNER, rexBuilder.makeLiteral(true)).build();

    // Join or Filter does not change the old input ordering. All
    // input fields from newLeftInput(i.e. the original input to the old
    // Filter) are in the output and in the same position.
    return register(oldInput, join, frame.oldToNewOutputs, corDefOutputs);
  }
Create RelNode tree that produces a list of correlated variables.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveRelDecorrelator.java