@Override
    public void onMatch(RelOptRuleCall call) {
      VbuilderPAP vb = processCall(call);
      if (vb == null) {
        return;
      }

      Aggregate aggregate = vb.aggregate;
      if (aggregate.getAggCallList().equals(vb.newAggCalls)) {
        // rule didn't make any changes
        return;
      }

      List<AggregateCall> newAggCalls = vb.newAggCalls;
      List<String> fieldNames = new ArrayList<String>();
      for (int i = 0; i < vb.newProjectsBelow.size(); i++) {
        fieldNames.add("ff_" + i);
      }
      RelNode newProjectBelow = projectFactory.createProject(aggregate.getInput(), Collections.emptyList(), vb.newProjectsBelow, fieldNames);

      RelNode newAgg = aggregate.copy(aggregate.getTraitSet(), newProjectBelow, aggregate.getGroupSet(),
          aggregate.getGroupSets(), newAggCalls);

      RelNode newProject =
          projectFactory.createProject(newAgg, Collections.emptyList(), vb.newProjectsAbove, aggregate.getRowType().getFieldNames());

      call.transformTo(newProject);
      return;

    }
Generic support for rewriting an Aggregate into a chain of Project->Aggregate->Project.
<p>
  The transformation here works on Aggregate nodes; the operations done are the following:
</p>
<ol>
<li>Identify candidate aggregate calls</li>
<li>A new Project is inserted below the Aggregate; to help with data pre-processing</li>
<li>A new Aggregate is created in which the aggregation is done by the sketch function</li>
<li>A new Project is inserted on top of the Aggregate; which unwraps the resulting estimation from the sketch representation</li>
</ol>
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveRewriteToDataSketchesRules.java