private void onMatch2(
            RelOptRuleCall call,
            LogicalCorrelate correlate,
            RelNode leftInput,
            Project aggOutputProject,
            Aggregate aggregate) {
      if (generatedCorRels.contains(correlate)) {
        // This correlator was generated by a previous invocation of
        // this rule. No further work to do.
        return;
      }

      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
      //   Project-A (a RexNode)
      //     Aggregate (groupby (0), agg0(), agg1()...)

      // check aggOutputProj projects only one expression
      List<RexNode> aggOutputProjExprs = aggOutputProject.getProjects();
      if (aggOutputProjExprs.size() != 1) {
        return;
      }

      if(correlate.getJoinType() != JoinRelType.LEFT) {
        return;
      }

      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 on the entire input
      if (!aggregate.getGroupSet().isEmpty()) {
        return;
      }

      List<AggregateCall> aggCalls = aggregate.getAggCallList();
      Set<Integer> isCount = Sets.newHashSet();

      // remember the count() positions
      int i = -1;
      for (AggregateCall aggCall : aggCalls) {
        ++i;
        if (aggCall.getAggregation() instanceof SqlCountAggFunction) {
          isCount.add(i);
        }
      }

      // now rewrite the plan to
      //
      // Project-A' (all LHS plus transformed original projections,
      //             replacing references to count() with case statement)
      //   Correlator(left correlation, condition = true)
      //     LeftInputRel
      //     Aggregate (groupby (0), agg0(), agg1()...)
      //
      LogicalCorrelate newCorrelate =
              LogicalCorrelate.create(leftInput, aggregate,
                      correlate.getCorrelationId(), correlate.getRequiredColumns(),
                      correlate.getJoinType());

      // remember this rel so we don't fire rule on it again
      // REVIEW jhyde 29-Oct-2007: rules should not save state; rule
      // should recognize patterns where it does or does not need to do
      // work
      generatedCorRels.add(newCorrelate);

      // need to update the mapCorVarToCorRel Update the output position
      // for the cor vars: only pass on the cor vars that are not used in
      // the join key.
      if (cm.mapCorToCorRel.get(correlate.getCorrelationId()) == correlate) {
        cm.mapCorToCorRel.put(correlate.getCorrelationId(), newCorrelate);
      }

      RelNode newOutput =
              aggregateCorrelatorOutput(newCorrelate, aggOutputProject, isCount);

      call.transformTo(newOutput);
    }
Planner rule that adjusts projects when counts are added.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveRelDecorrelator.java