@Override
    public void onMatch(RelOptRuleCall call) {
      final LogicalCorrelate correlate = call.rel(0);
      final RelNode left = call.rel(1);
      final Aggregate aggregate = call.rel(2);
      final Project project = call.rel(3);
      RelNode right = call.rel(4);
      final RelOptCluster cluster = correlate.getCluster();

      setCurrent(call.getPlanner().getRoot(), correlate);

      // Check for this pattern.
      // The pattern matching could be simplified if rules can be applied
      // during decorrelation.
      //
      // CorrelateRel(left correlation, condition = true)
      //   LeftInputRel
      //   Aggregate (groupby (0) single_value())
      //     Project-A (may reference coVar)
      //       RightInputRel
      if(correlate.getJoinType() != JoinRelType.LEFT) {
        return;
      }
      final JoinRelType joinType = correlate.getJoinType();

      // corRel.getCondition was here, however Correlate was updated so it
      // never includes a join condition. The code was not modified for brevity.
      RexNode joinCond = rexBuilder.makeLiteral(true);
      if ((joinType != JoinRelType.LEFT)
              || (joinCond != rexBuilder.makeLiteral(true))) {
        return;
      }

      // check that the agg is of the following type:
      // doing a single_value() on the entire input
      if ((!aggregate.getGroupSet().isEmpty())
              || (aggregate.getAggCallList().size() != 1)
              || !(aggregate.getAggCallList().get(0).getAggregation()
              instanceof SqlSingleValueAggFunction)) {
        return;
      }

      // check this project only projects one expression, i.e. scalar
      // subqueries.
      if (project.getProjects().size() != 1) {
        return;
      }

      int nullIndicatorPos;

      if ((right instanceof Filter)
              && cm.mapRefRelToCorRef.containsKey(right)) {
        // rightInputRel has this shape:
        //
        //       Filter (references corvar)
        //         FilterInputRel

        // If rightInputRel is a filter and contains correlated
        // reference, make sure the correlated keys in the filter
        // condition forms a unique key of the RHS.

        Filter filter = (Filter) right;
        right = filter.getInput();

        assert right instanceof HepRelVertex;
        right = ((HepRelVertex) right).getCurrentRel();

        // check filter input contains no correlation
        if (RelOptUtil.getVariablesUsed(right).size() > 0) {
          return;
        }

        // extract the correlation out of the filter

        // First breaking up the filter conditions into equality
        // comparisons between rightJoinKeys(from the original
        // filterInputRel) and correlatedJoinKeys. correlatedJoinKeys
        // can be expressions, while rightJoinKeys need to be input
        // refs. These comparisons are AND'ed together.
        List<RexNode> tmpRightJoinKeys = Lists.newArrayList();
        List<RexNode> correlatedJoinKeys = Lists.newArrayList();
        HiveRelOptUtil.splitCorrelatedFilterCondition(
                filter,
                tmpRightJoinKeys,
                correlatedJoinKeys,
                false);

        // check that the columns referenced in these comparisons form
        // an unique key of the filterInputRel
        final List<RexInputRef> rightJoinKeys = new ArrayList<>();
        for (RexNode key : tmpRightJoinKeys) {
          assert key instanceof RexInputRef;
          rightJoinKeys.add((RexInputRef) key);
        }

        // check that the columns referenced in rightJoinKeys form an
        // unique key of the filterInputRel
        if (rightJoinKeys.isEmpty()) {
          return;
        }

        // The join filters out the nulls.  So, it's ok if there are
        // nulls in the join keys.
        final RelMetadataQuery mq = call.getMetadataQuery();
        if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, right,
                rightJoinKeys)) {
          //SQL2REL_LOGGER.fine(rightJoinKeys.toString()
           //       + "are not unique keys for "
            //      + right.toString());
          return;
        }

        RexUtil.FieldAccessFinder visitor =
                new RexUtil.FieldAccessFinder();
        RexUtil.apply(visitor, correlatedJoinKeys, null);
        List<RexFieldAccess> correlatedKeyList =
                visitor.getFieldAccessList();

        if (!checkCorVars(correlate, project, filter, correlatedKeyList)) {
          return;
        }

        // Change the plan to this structure.
        // Note that the aggregateRel is removed.
        //
        // Project-A' (replace corvar to input ref from the Join)
        //   Join (replace corvar to input ref from LeftInputRel)
        //     LeftInputRel
        //     RightInputRel(oreviously FilterInputRel)

        // Change the filter condition into a join condition
        joinCond =
                removeCorrelationExpr(filter.getCondition(), false);

        nullIndicatorPos =
                left.getRowType().getFieldCount()
                        + rightJoinKeys.get(0).getIndex();
      } else if (cm.mapRefRelToCorRef.containsKey(project)) {
        // check filter input contains no correlation
        if (RelOptUtil.getVariablesUsed(right).size() > 0) {
          return;
        }

        if (!checkCorVars(correlate, project, null, null)) {
          return;
        }

        // Change the plan to this structure.
        //
        // Project-A' (replace corvar to input ref from Join)
        //   Join (left, condition = true)
        //     LeftInputRel
        //     Aggregate(groupby(0), single_value(0), s_v(1)....)
        //       Project-B (everything from input plus literal true)
        //         ProjInputRel

        // make the new projRel to provide a null indicator
        right =
                createProjectWithAdditionalExprs(right,
                        ImmutableList.of(
                                Pair.<RexNode, String>of(
                                        rexBuilder.makeLiteral(true), "nullIndicator")));

        // make the new aggRel
        right =
                HiveRelOptUtil.createSingleValueAggRel(cluster, right, HiveRelFactories.HIVE_AGGREGATE_FACTORY);

        // The last field:
        //     single_value(true)
        // is the nullIndicator
        nullIndicatorPos =
                left.getRowType().getFieldCount()
                        + right.getRowType().getFieldCount() - 1;
      } else {
        return;
      }

      // make the new join rel
      Join join = (Join) relBuilder.push(left).push(right)
          .join(joinType, joinCond).build();

      RelNode newProject =
              projectJoinOutputWithNullability(join, project, nullIndicatorPos);

      call.transformTo(newProject);

      removeCorVarFromTree(correlate);
    }
Planner rule that removes correlations for scalar projects.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveRelDecorrelator.java