julianhyde commented on a change in pull request #1078: [CALCITE-896] Remove 
Aggregate if grouping columns are unique and all functions are splittable
URL: https://github.com/apache/calcite/pull/1078#discussion_r261428663
 
 

 ##########
 File path: 
core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java
 ##########
 @@ -58,37 +68,63 @@ public AggregateRemoveRule(Class<? extends Aggregate> 
aggregateClass,
     // distinct to make it correct up-front, we can get rid of the reference
     // to the child here.
     super(
-        operand(aggregateClass,
+        operandJ(aggregateClass, null, agg -> isAggregateSupported(agg),
             operand(RelNode.class, any())),
         relBuilderFactory, null);
   }
 
+  private static boolean isAggregateSupported(Aggregate aggregate) {
+    if (aggregate.indicator ||
+        aggregate.getGroupType() != Aggregate.Group.SIMPLE) {
+      return false;
+    }
+    // If any aggregate functions do not support splitting, bail out
+    for (AggregateCall aggregateCall : aggregate.getAggCallList()) {
+      if (aggregateCall.filterArg >= 0 ||
+          aggregateCall.getAggregation()
+              .unwrap(SqlSplittableAggFunction.class) == null) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   //~ Methods ----------------------------------------------------------------
 
   public void onMatch(RelOptRuleCall call) {
     final Aggregate aggregate = call.rel(0);
     final RelNode input = call.rel(1);
-    if (!aggregate.getAggCallList().isEmpty() || aggregate.indicator) {
-      return;
-    }
     final RelMetadataQuery mq = call.getMetadataQuery();
     if (!SqlFunctions.isTrue(mq.areColumnsUnique(input, 
aggregate.getGroupSet()))) {
       return;
     }
-    // Distinct is "GROUP BY c1, c2" (where c1, c2 are a set of columns on
-    // which the input is unique, i.e. contain a key) and has no aggregate
-    // functions. It can be removed.
-    final RelNode newInput = convert(input, 
aggregate.getTraitSet().simplify());
 
-    // If aggregate was projecting a subset of columns, add a project for the
-    // same effect.
+    final RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
+    final List<RexNode> projects = new LinkedList<>();
+    for (AggregateCall aggCall : aggregate.getAggCallList()) {
+      final SqlAggFunction aggregation = aggCall.getAggregation();
+      final SqlSplittableAggFunction splitter =
+          Objects.requireNonNull(
+              aggregation.unwrap(SqlSplittableAggFunction.class));
+      final RexNode singleton = splitter.singleton(
+          rexBuilder, input.getRowType(), aggCall);
+      projects.add(singleton);
+    }
+
+    final RelNode newInput = convert(input, 
aggregate.getTraitSet().simplify());
     final RelBuilder relBuilder = call.builder();
     relBuilder.push(newInput);
-    if (newInput.getRowType().getFieldCount()
+    if (!projects.isEmpty()) {
+      projects.addAll(0, relBuilder.fields(aggregate.getGroupSet().asList()));
+      relBuilder.project(projects);
+    } else if (newInput.getRowType().getFieldCount()
         > aggregate.getRowType().getFieldCount()) {
+      // If aggregate was projecting a subset of columns, and there were no
+      // aggregate functions, add a project for the same effect.
       relBuilder.project(relBuilder.fields(aggregate.getGroupSet().asList()));
     }
-    call.transformTo(relBuilder.build());
+    final RelNode newRel = relBuilder.build();
+    call.transformTo(newRel);
 
 Review comment:
   the variable doesn't seem necessary

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to