AMashenkov commented on code in PR #3413:
URL: https://github.com/apache/ignite-3/pull/3413#discussion_r1532074928


##########
modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/MapReduceAggregates.java:
##########
@@ -356,10 +486,190 @@ private static MapReduceAgg 
createSimpleAgg(AggregateCall call, int reduceArgume
         return new MapReduceAgg(argList, call, reduceCall, USE_INPUT_FIELD);
     }
 
+    /**
+     * TODO: Rename to MakeExpr.
+     * Produces intermediate expressions that modify results of MAP/REDUCE 
aggregate.
+     * For example: after splitting a function into a MAP aggregate and REDUCE 
aggregate it is necessary to add casts to
+     * output of a REDUCE phase aggregate.
+     *
+     * <p>In order to avoid creating unnecessary projections, use {@link 
MapReduceAggregates#USE_INPUT_FIELD}.
+     */
     @FunctionalInterface
     private interface MakeReduceExpr {
 
-        /** Creates an expression that produces result of REDUCE phase of an 
aggregate. */
+        /**
+         * Creates an expression that applies a performs computation (e.g. 
applies some function, adds a cast)
+         * on {@code args} fields of input relation.
+         *
+         * @param rexBuilder Expression builder.
+         * @param input Input relation.
+         * @param args Arguments.
+         * @param typeFactory Type factory.
+         *
+         * @return Expression.
+         */
         RexNode makeExpr(RexBuilder rexBuilder, RelNode input, List<Integer> 
args, IgniteTypeFactory typeFactory);
     }
+
+    private static MapReduceAgg createAvgAgg(
+            RelOptCluster cluster,
+            AggregateCall call,
+            int reduceArgumentOffset,
+            RelDataType inputType,
+            boolean canBeNull
+    ) {
+        RelDataTypeFactory tf = cluster.getTypeFactory();
+        RelDataTypeSystem typeSystem = tf.getTypeSystem();
+
+        RelDataType fieldType = 
inputType.getFieldList().get(call.getArgList().get(0)).getType();
+
+        // In case of AVG(NULL) return a simple version of an aggregate, 
because result is always NULL.
+        if (fieldType.getSqlTypeName() == SqlTypeName.NULL) {
+            return createSimpleAgg(call, reduceArgumentOffset);
+        }
+
+        // AVG(x) : SUM(x)/COUNT0(x)
+        // MAP    : SUM(x) / COUNT(x)
+
+        // SUM(x) as s
+        RelDataType mapSumType = typeSystem.deriveSumType(tf, fieldType);
+        if (canBeNull) {
+            mapSumType = tf.createTypeWithNullability(mapSumType, true);
+        }
+
+        AggregateCall mapSum0 = AggregateCall.create(
+                SqlStdOperatorTable.SUM,
+                call.isDistinct(),
+                call.isApproximate(),
+                call.ignoreNulls(),
+                ImmutableList.of(),
+                call.getArgList(),
+                call.filterArg,
+                null,
+                call.collation,
+                mapSumType,
+                "AVG" + reduceArgumentOffset + "_MAP_SUM");
+
+        // COUNT(x) as c
+        RelDataType mapCountType = tf.createSqlType(SqlTypeName.BIGINT);
+
+        AggregateCall mapCount0 = AggregateCall.create(
+                SqlStdOperatorTable.COUNT,
+                call.isDistinct(),
+                call.isApproximate(),
+                call.ignoreNulls(),
+                ImmutableList.of(),
+                call.getArgList(),
+                call.filterArg,
+                null,
+                call.collation,
+                mapCountType,
+                "AVG" + reduceArgumentOffset + "_MAP_COUNT");
+
+        // REDUCE : SUM0(s) as reduce_sum, SUM0(c) as reduce_count

Review Comment:
   ```suggestion
           // REDUCE : SUM(s) as reduce_sum, SUM0(c) as reduce_count
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to